diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1c303f38f..62bbd4088 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -46,11 +46,24 @@ exports.findNextMatch = function(startPos) { return undefined; }; + exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the comment that is not rendered + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentblock", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 671bd79d6..50e861fe4 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -43,8 +43,20 @@ exports.findNextMatch = function(startPos) { exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the inline comment + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentinline", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 23940fd88..ead7fc0af 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -117,4 +117,16 @@ exports.parseIfClause = function(filterCondition) { return [listWidget]; }; +exports.serialize = function(tree, serialize) { + var filterCondition = tree.attributes.filter.value; + var ifClause = serialize(tree.children[0].children); + var elseClause = serialize(tree.children[1].children); + var serialized = '<% if ' + filterCondition + ' %>' + ifClause; + if(elseClause) { + serialized += '<% else %>' + elseClause; + } + serialized += '<% endif %>'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js index 45481bf07..60c82f0a7 100644 --- a/core/modules/parsers/wikiparser/rules/dash.js +++ b/core/modules/parsers/wikiparser/rules/dash.js @@ -37,4 +37,9 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + var dash = tree.entity === "–" ? "--" : "---"; + return dash; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js index dc3917daf..7f15c8a95 100644 --- a/core/modules/parsers/wikiparser/rules/entity.js +++ b/core/modules/parsers/wikiparser/rules/entity.js @@ -37,4 +37,9 @@ exports.parse = function() { return [{type: "entity", entity: this.match[0]}]; }; +// Serialize method for the entity rule +exports.serialize = function(tree, serialize) { + return tree.entity; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/extlink.js b/core/modules/parsers/wikiparser/rules/extlink.js index 5b9f57adf..58b7e772e 100644 --- a/core/modules/parsers/wikiparser/rules/extlink.js +++ b/core/modules/parsers/wikiparser/rules/extlink.js @@ -53,4 +53,13 @@ exports.parse = function() { } }; +// Serialize method for the extlink rule +exports.serialize = function(tree, serialize) { + if(tree.type === "text") { + return tree.text; + } else if(tree.type === "element" && tree.tag === "a") { + return tree.attributes.href.value; + } +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 73bdff813..c66009f85 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,4 +71,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index c0b19a941..cb992dbed 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,4 +70,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index 85bd14d5c..a4259e574 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -93,5 +93,20 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree, serialize) { + // Type of definition: "function", "procedure", or "widget" + var type = tree.isFunctionDefinition ? "function" : (tree.isProcedureDefinition ? "procedure" : "widget"); + // Name of the function, procedure, or widget + var name = tree.attributes.name.value; + // Parameters with default values + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js index 94f517cd4..39ef6fc5c 100644 --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js @@ -57,4 +57,19 @@ exports.parse = function() { return tree; }; +exports.serialize = function(tree,serialize) { + // Serialized text with hard line breaks + var serialized = '"""\n'; + // Serialize each node in the tree + tree.forEach(function(node) { + if(node.type === "element" && node.tag === "br") { + serialized += "\n"; + } else { + serialized += serialize([node]).join(''); + } + }); + serialized += '\n"""'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 7a0ecb9db..79df971e5 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -45,4 +45,16 @@ exports.parse = function() { children: tree }]; }; + +exports.serialize = function(tree, serialize) { + // Heading level + var headingLevel = tree.tag.length - 1; + // Classes + var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; + // Serialized heading text + var headingText = serialize(tree.children).join(''); + // Construct the serialized string + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 61c4ad9e1..911099b37 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -195,4 +195,19 @@ exports.isLegalTag = function(tag) { } }; +exports.serialize = function(tree, serialize) { + var tag = tree.tag; + var attributes = Object.keys(tree.attributes).map(function(key) { + return key + '="' + tree.attributes[key].value + '"'; + }).join(" "); + // Children + var children = tree.children ? serialize(tree.children).join('') : ''; + // Self-closing tag + if(tree.isSelfClosing) { + return "<" + tag + (attributes ? " " + attributes : "") + " />"; + } + // Opening and closing tags + return "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 6f58225e0..8591e544e 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -130,4 +130,17 @@ exports.parseImage = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Width attribute + var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; + // Height attribute + var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; + // Tooltip attribute + var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; + // Source attribute + var source = tree.attributes.source.value; + // Construct the serialized string + return "[img" + width + height + " [" + tooltip + source + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index bb1832255..7025d20f2 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -51,4 +51,11 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Filter attribute + var filter = tree.attributes.filter.value; + // Construct the serialized string + return "\\import " + filter; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index d89c201b9..8dc8411aa 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -153,4 +153,28 @@ exports.parse = function() { return [listStack[0]]; }; +exports.serialize = function(tree, serialize) { + // Serialize the list recursively + return serializeList(tree, serialize, 0); +}; + +// utility to handle recursion of list +function serializeList(node, serialize, depth) { + // List tag + var listTag = node.tag; + // List item tag + var itemTag = listTypes[listTag[0]].itemTag; + // Serialized list items + var items = node.children.map(function(child) { + // Classes + var classes = child.attributes && child.attributes.class ? child.attributes.class.value.split(" ").join(".") : ""; + // Serialized children + var children = serialize(child.children).join(''); + // Construct the serialized list item + return Array(depth + 1).join(listTag[0]) + (classes ? "." + classes : "") + " " + children; + }).join("\n"); + // Return the serialized list + return items; +} + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index a2c10e04a..c3b0e92e9 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -53,4 +53,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index e9f79f09e..a62596414 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -46,4 +46,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 2001f70d5..31a93f27b 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -89,4 +89,17 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.attributes.name.value; + // Parameters + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index 60bbd8901..692f03ea7 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -57,4 +57,13 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Parameters + var params = tree.orderedAttributes.map(function(param) { + return param.name + (param.value ? ":" + param.value : ""); + }).join(","); + // Construct the serialized string + return "\\parameters(" + params + ")"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 72a6de067..4814a4ba1 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -65,4 +65,11 @@ exports.parse = function() { return []; }; +exports.serialize = function(tree) { + // Parser mode + var mode = tree.parser.parseAsInline ? "inline" : "block"; + // Construct the serialized string + return "\\parsermode " + mode; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js index 4707fa0d0..e2cc48a7e 100644 --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js @@ -117,4 +117,13 @@ exports.parseLink = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Tooltip text + var tooltip = tree.children[0].text; + // URL + var url = tree.attributes.href.value; + // Construct the serialized string + return "[ext[" + (tooltip !== url ? tooltip + "|" : "") + url + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js index 66c19dc88..74a275e42 100644 --- a/core/modules/parsers/wikiparser/rules/prettylink.js +++ b/core/modules/parsers/wikiparser/rules/prettylink.js @@ -35,7 +35,7 @@ exports.parse = function() { var text = this.match[1], link = this.match[2] || text, textEndPos = this.parser.source.indexOf("|", start); - if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { + if(textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { textEndPos = this.matchRegExp.lastIndex - 2; } var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start; @@ -67,4 +67,13 @@ exports.parse = function() { } }; +exports.serialize = function(tree) { + // Link text + var text = tree.children[0].text; + // Link target + var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value; + // Construct the serialized string + return "[[" + text + (text !== target ? "|" + target : "") + "]]"; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 03e330b43..b21627564 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -6,36 +6,259 @@ tags: [[$:/tags/test-spec]] Tests the wikitext inverse-rendering from Wiki AST. \*/ -(function(){ -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; +describe('WikiAST serialization tests', function () { + var wiki = new $tw.Wiki(); -describe("WikiAST serialization tests", function() { + wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); + it('should render tiddlers with no special markup as-is', function () { + // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerOne') + ); + }); - // Create a wiki - var wiki = new $tw.Wiki(); - // Add a couple of tiddlers - wiki.addTiddler({title: "TiddlerOne", text: "The quick brown fox"}); - wiki.addTiddler({title: "TiddlerTwo", text: "The rain in Spain\nfalls mainly on the plain"}); - wiki.addTiddler({title: "TiddlerThree", text: "The speed of sound\n\nThe light of speed"}); - wiki.addTiddler({title: "TiddlerFour", text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend"}); + wiki.addTiddler({ title: 'TiddlerTwo', text: 'The rain in Spain\nfalls mainly on the plain' }); + it('should preserve single new lines', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerTwo') + ); + }); - it("should render tiddlers with no special markup as-is", function() { - // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerOne')); - }); - it("should preserve single new lines", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerTwo')); - }); - it("should preserve double new lines to create paragraphs", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerThree')); - }); - - it("should render inline code and block code", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerFour')); - }); + wiki.addTiddler({ title: 'TiddlerThree', text: 'The speed of sound\n\nThe light of speed' }); + it('should preserve double new lines to create paragraphs', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerThree') + ); + }); + + wiki.addTiddler({ + title: 'TiddlerFour', + text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', + }); + it('should render inline code and block code', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerFour') + ); + }); + + // Test case for commentblock rule + wiki.addTiddler({ + title: 'CommentBlockTest', + text: '\n\nSome text\n\n\n\nMore text', + }); + it('should serialize block comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentBlockTest').trimEnd()); + }); + + // Test case for commentinline rule + wiki.addTiddler({ + title: 'CommentInlineTest', + text: 'This is some text with an inline comment and some more text.', + }); + it('should serialize inline comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentInlineTest').trimEnd()); + }); + + // Test case for conditional rule + wiki.addTiddler({ + title: 'ConditionalTest', + text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', + }); + it('should serialize conditional statements correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ConditionalTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ConditionalTest').trimEnd()); + }); + + // Test case for dash rule + wiki.addTiddler({ + title: 'DashTest', + text: 'This is an en-dash: --\n\nThis is an em-dash: ---', + }); + it('should serialize dashes correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('DashTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); + }); + + // Test case for entity rule + wiki.addTiddler({ + title: 'EntityTest', + text: 'This is a copyright symbol: ©', + }); + it('should serialize HTML entities correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('EntityTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('EntityTest').trimEnd()); + }); + + // Test case for extlink rule + wiki.addTiddler({ + title: 'ExtLinkTest', + text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', + }); + it('should serialize external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ExtLinkTest').trimEnd()); + }); + + // Test case for filteredtranscludeblock rule + wiki.addTiddler({ + title: 'FilteredTranscludeBlockTest', + text: '{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize block-level filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeBlockTest').trimEnd()); + }); + + // Test case for filteredtranscludeinline rule + wiki.addTiddler({ + title: 'FilteredTranscludeInlineTest', + text: '{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize inline filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeInlineTest').trimEnd()); + }); + + // Test case based on the rule code's comment + wiki.addTiddler({ + title: 'FunctionDefinition', + text: '\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end', + }); + it('should serialize function, procedure, and widget definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); + }); + + // Test case for hardlinebreaks rule + wiki.addTiddler({ + title: 'HardLineBreaksTest', + text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n', + }); + it('should serialize hard line breaks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HardLineBreaksTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HardLineBreaksTest').trimEnd()); + }); + + // Test case for heading rule + wiki.addTiddler({ + title: 'HeadingTest', + text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', + }); + it('should serialize headings correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HeadingTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HeadingTest').trimEnd()); + }); + + // Test case for html rule + wiki.addTiddler({ + title: 'HtmlTest', + text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n', + }); + it('should serialize HTML elements and widgets correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HtmlTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HtmlTest').trimEnd()); + }); + + // Test case for image rule + wiki.addTiddler({ + title: 'ImageTest', + text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', + }); + it('should serialize image tags correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); + }); + + // Test case for import rule + wiki.addTiddler({ + title: 'ImportTest', + text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', + }); + it('should serialize import pragma correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); + }); + + // Test case for list rule + wiki.addTiddler({ + title: 'ListTest', + text: '* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three', + }); + it('should serialize lists correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); + }); + + // Test case for macrocallblock rule + wiki.addTiddler({ + title: 'MacroCallBlockTest', + text: '<>', + }); + it('should serialize block macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); + }); + + // Test case for macrocallinline rule + wiki.addTiddler({ + title: 'MacroCallInlineTest', + text: 'This is a macro call: <>', + }); + it('should serialize inline macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallInlineTest').trimEnd()); + }); + + // Test case for macrodef rule + wiki.addTiddler({ + title: 'MacroDefTest', + text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', + }); + it('should serialize macro definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroDefTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); + }); + + // Test case for parameters rule + wiki.addTiddler({ + title: 'ParametersTest', + text: '\\parameters(param:defaultvalue,param2:defaultvalue)', + }); + it('should serialize parameter definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParametersTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); + }); + + // Test case for parsermode rule + wiki.addTiddler({ + title: 'ParserModeTest', + text: '\\parsermode block\n\\parsermode inline', + }); + it('should serialize parser mode specifications correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParserModeTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); + }); + + // Test case for prettyextlink rule + wiki.addTiddler({ + title: 'PrettyExtLinkTest', + text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', + }); + it('should serialize pretty external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); + }); + + // Test case for prettylink rule + wiki.addTiddler({ + title: 'PrettyLinkTest', + text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', + }); + it('should serialize pretty links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); + }); }); - -})();