From 37338b13e4392cc053e3670a2dbb5f09bc2db901 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:23:31 +0800 Subject: [PATCH 01/52] refactor: extract a new $tw.wiki.getParser --- core/modules/wiki.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 2850dec5fff..e53b0d387d3 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1035,6 +1035,18 @@ Options include: exports.parseText = function(type,text,options) { text = text || ""; options = options || {}; + var Parser = this.getParser(type,options) + // Return the parser instance + return new Parser(type,text,{ + parseAsInline: options.parseAsInline, + wiki: this, + _canonical_uri: options._canonical_uri, + configTrimWhiteSpace: options.configTrimWhiteSpace + }); +}; + +exports.getParser = function(type,options) { + options = $tw.utils.extend({},options); // Select a parser var Parser = $tw.Wiki.parsers[type]; if(!Parser && $tw.utils.getFileExtensionInfo(type)) { @@ -1046,13 +1058,7 @@ exports.parseText = function(type,text,options) { if(!Parser) { return null; } - // Return the parser instance - return new Parser(type,text,{ - parseAsInline: options.parseAsInline, - wiki: this, - _canonical_uri: options._canonical_uri, - configTrimWhiteSpace: options.configTrimWhiteSpace - }); + return Parser; }; /* From 8a12498fa96aa76973a6dbd8d28698bd3ef4418e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:23:59 +0800 Subject: [PATCH 02/52] feat: allow $tw.utils.getParseTreeText to render other rules' text --- core/modules/utils/parsetree.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index a74b8f3f81e..7e7542d3481 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -106,7 +106,7 @@ exports.findParseTreeNode = function(nodeArray,search) { /* Helper to get the text of a parse tree node or array of nodes */ -exports.getParseTreeText = function getParseTreeText(tree) { +exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -115,6 +115,14 @@ exports.getParseTreeText = function getParseTreeText(tree) { } else { if(tree.type === "text") { output.push(tree.text); + } else { + var Parser = $tw.wiki.getParser(tiddlerType); + var Rule = Parser.prototype.blockRuleClasses[tree.type] || + Parser.prototype.inlineRuleClasses[tree.type] || + Parser.prototype.pragmaRuleClasses[tree.type]; + if(Rule && Rule.prototype.getText) { + output.push(Rule.prototype.getText(tree)); + } } if(tree.children) { return getParseTreeText(tree.children); From 09c2e71e228dbe8b6d0e30364dd8d9244f6e1f4e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:25:23 +0800 Subject: [PATCH 03/52] feat: two example getText handler --- core/modules/parsers/wikiparser/rules/codeblock.js | 4 ++++ core/modules/parsers/wikiparser/rules/horizrule.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 6c3480566b9..71efe2dfd82 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,4 +57,8 @@ exports.parse = function() { }]; }; +exports.getText = function(tree) { + return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; +} + })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index bacad06ed9e..2e69e1986ec 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,4 +31,8 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; +exports.getText = function() { + return "---"; +} + })(); From a0708a17cb9c3f43e26752e0a3233f69bbf6baf1 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:29:22 +0800 Subject: [PATCH 04/52] Revert "feat: allow $tw.utils.getParseTreeText to render other rules' text" This reverts commit 8a12498fa96aa76973a6dbd8d28698bd3ef4418e. --- core/modules/utils/parsetree.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index 7e7542d3481..a74b8f3f81e 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -106,7 +106,7 @@ exports.findParseTreeNode = function(nodeArray,search) { /* Helper to get the text of a parse tree node or array of nodes */ -exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { +exports.getParseTreeText = function getParseTreeText(tree) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -115,14 +115,6 @@ exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { } else { if(tree.type === "text") { output.push(tree.text); - } else { - var Parser = $tw.wiki.getParser(tiddlerType); - var Rule = Parser.prototype.blockRuleClasses[tree.type] || - Parser.prototype.inlineRuleClasses[tree.type] || - Parser.prototype.pragmaRuleClasses[tree.type]; - if(Rule && Rule.prototype.getText) { - output.push(Rule.prototype.getText(tree)); - } } if(tree.children) { return getParseTreeText(tree.children); From f882cbd7af6f0fd2796b39c6c7b0870396baf674 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:31:13 +0800 Subject: [PATCH 05/52] refactor: keep original getParseTreeText not touched --- core/modules/utils/parsetree.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index a74b8f3f81e..d553ec4f0dd 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -123,4 +123,32 @@ exports.getParseTreeText = function getParseTreeText(tree) { return output.join(""); }; +/* +Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes +*/ +exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { + var output = []; + if($tw.utils.isArray(tree)) { + $tw.utils.each(tree,function(node) { + output.push(serializeParseTree(node)); + }); + } else { + if(tree.type === "text") { + output.push(tree.text); + } else { + var Parser = $tw.wiki.getParser(tiddlerType); + var Rule = Parser.prototype.blockRuleClasses[tree.type] || + Parser.prototype.inlineRuleClasses[tree.type] || + Parser.prototype.pragmaRuleClasses[tree.type]; + if(Rule && Rule.prototype.getText) { + output.push(Rule.prototype.getText(tree)); + } + } + if(tree.children) { + return getParseTreeText(tree.children); + } + } + return output.join(""); +}; + })(); From be3f037a57217fc2131f34ae8e967d3aad9bb989 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:34:18 +0800 Subject: [PATCH 06/52] refactor: use serialize in rules --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 4 ++-- core/modules/utils/parsetree.js | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 71efe2dfd82..11681261b3a 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.getText = function(tree) { +exports.serialize = function(tree) { return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; } diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 2e69e1986ec..697bd65a5c2 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,8 +31,8 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; -exports.getText = function() { - return "---"; +exports.serialize = function() { + return "\n---\n"; } })(); diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index d553ec4f0dd..ae548de0ea4 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -137,15 +137,15 @@ exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { output.push(tree.text); } else { var Parser = $tw.wiki.getParser(tiddlerType); - var Rule = Parser.prototype.blockRuleClasses[tree.type] || - Parser.prototype.inlineRuleClasses[tree.type] || - Parser.prototype.pragmaRuleClasses[tree.type]; - if(Rule && Rule.prototype.getText) { - output.push(Rule.prototype.getText(tree)); + var Rule = Parser.prototype.blockRuleClasses[tree.rule] || + Parser.prototype.inlineRuleClasses[tree.rule] || + Parser.prototype.pragmaRuleClasses[tree.rule]; + if(Rule && Rule.prototype.serialize) { + output.push(Rule.prototype.serialize(tree)); } } if(tree.children) { - return getParseTreeText(tree.children); + return serializeParseTree(tree.children); } } return output.join(""); From 4e896d18a018fd2af70b331ce82e985b7ca79cc4 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:39 +0800 Subject: [PATCH 07/52] refactor: $tw.utils.extend({},options) -> options || {} --- core/modules/wiki.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 0baf1bdcfb5..516751a1ab0 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1064,7 +1064,7 @@ exports.parseText = function(type,text,options) { }; exports.getParser = function(type,options) { - options = $tw.utils.extend({},options); + options = options || {}; // Select a parser var Parser = $tw.Wiki.parsers[type]; if(!Parser && $tw.utils.getFileExtensionInfo(type)) { @@ -1083,7 +1083,7 @@ exports.getParser = function(type,options) { Parse a tiddler according to its MIME type */ exports.parseTiddler = function(title,options) { - options = $tw.utils.extend({},options); + options = options || {}; var cacheType = options.parseAsInline ? "inlineParseTree" : "blockParseTree", tiddler = this.getTiddler(title), self = this; From 179651a189c4be09891a6af189f1214738353a94 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:47 +0800 Subject: [PATCH 08/52] Update codeinline.js --- core/modules/parsers/wikiparser/rules/codeinline.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index 048fc051c05..015c325c53b 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -55,4 +55,8 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + return "`" + tree.children.text + "`"; +} + })(); From 8cbf85592d554537fbf239d2235044e31f20c839 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:53 +0800 Subject: [PATCH 09/52] Create test-wikitext-serialize.js --- .../tiddlers/tests/test-wikitext-serialize.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 editions/test/tiddlers/tests/test-wikitext-serialize.js diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js new file mode 100644 index 00000000000..d8747ef4805 --- /dev/null +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -0,0 +1,40 @@ +/*\ +title: test-wikitext-serialize.js +type: application/javascript +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() { + + // 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"}); + + it("should render tiddlers with no special markup as-is", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree)).toBe(wiki.getTiddlerText('TiddlerOne')); + }); + it("should preserve single new lines", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree)).toBe(wiki.getTiddlerText('TiddlerTwo')); + }); + it("should preserve double new lines to create paragraphs", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree)).toBe(wiki.getTiddlerText('TiddlerThree')); + }); + + it("should render inline code and block code", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree)).toBe(wiki.getTiddlerText('TiddlerFour')); + }); +}); + +})(); From a075303932914502118f3f1e7fcce1704913a005 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:24:32 +0800 Subject: [PATCH 10/52] DEBUG: only run my tests for development, remove before PR merge --- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 8dbf6568e97..488377b4493 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -12,7 +12,8 @@ The main module of the Jasmine test plugin for TiddlyWiki5 /*global $tw: true */ "use strict"; -var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]"; +// DEBUG: only run my tests for development, remove before PR merge +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 05dec729a0f7a266ebc69afac6777cf64003c031 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:43:40 +0800 Subject: [PATCH 11/52] lint: if --- core/modules/parsers/wikiparser/wikiparser.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 854171d197f..09866b0646d 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -218,8 +218,8 @@ WikiParser.prototype.parsePragmas = function() { var subTree = nextMatch.rule.parse(); if(subTree.length > 0) { // Set the start and end positions of the pragma rule if - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); // Quick hack; we only cope with a single parse tree node being returned, which is true at the moment currentTreeBranch.push.apply(currentTreeBranch,subTree); @@ -248,9 +248,9 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { var start = this.pos; var subTree = nextMatch.rule.parse(); // Set the start and end positions of the first and last blocks if they're not already set - if (subTree.length > 0) { - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree.length > 0) { + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); return subTree; @@ -353,10 +353,10 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) { var start = this.pos; var subTree = nextMatch.rule.parse(); // Set the start and end positions of the first and last child if they're not already set - if (subTree.length > 0) { + if(subTree.length > 0) { // Set the start and end positions of the first and last child if they're not already set - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); tree.push.apply(tree,subTree); @@ -413,9 +413,9 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx var start = this.pos; var subTree = inlineRuleMatch.rule.parse(); // Set the start and end positions of the first and last child if they're not already set - if (subTree.length > 0) { - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree.length > 0) { + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; }); tree.push.apply(tree,subTree); From 1a6a071a29336dadfe0dfde0dba0cc2373568d1a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:43:55 +0800 Subject: [PATCH 12/52] feat: add rule: 'parseBlock' metadata --- core/modules/parsers/wikiparser/wikiparser.js | 2 +- core/modules/utils/parsetree.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 09866b0646d..10acf91eccd 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -259,7 +259,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { var start = this.pos; var children = this.parseInlineRun(terminatorRegExp); var end = this.pos; - return [{type: "element", tag: "p", children: children, start: start, end: end }]; + return [{type: "element", tag: "p", children: children, start: start, end: end, rule: 'parseBlock' }]; }; /* diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index ae548de0ea4..f5b2c12d096 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -124,9 +124,10 @@ exports.getParseTreeText = function getParseTreeText(tree) { }; /* -Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes +Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes. +Based on `node.rule` metadata added in `wikiparser.js`. */ -exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { +exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -141,12 +142,11 @@ exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { Parser.prototype.inlineRuleClasses[tree.rule] || Parser.prototype.pragmaRuleClasses[tree.rule]; if(Rule && Rule.prototype.serialize) { - output.push(Rule.prototype.serialize(tree)); + output.push(Rule.prototype.serialize(tree,serializeParseTree)); + } else if(tree.rule === "parseBlock") { + output.push(serializeParseTree(tree.children,tiddlerType),"\n\n"); } } - if(tree.children) { - return serializeParseTree(tree.children); - } } return output.join(""); }; From 84e27c05b91e536daa82f933f7f14d460cdd4bc1 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:46:16 +0800 Subject: [PATCH 13/52] feat: handle tailing \n that may be missing --- core/modules/parsers/wikiparser/rules/codeinline.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- editions/test/tiddlers/tests/test-wikitext-serialize.js | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index 015c325c53b..a78b56e6b64 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -56,7 +56,7 @@ exports.parse = function() { }; exports.serialize = function(tree) { - return "`" + tree.children.text + "`"; + return "`" + tree.children[0].text + "`"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 697bd65a5c2..e9279a4d727 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -32,7 +32,7 @@ exports.parse = function() { }; exports.serialize = function() { - return "\n---\n"; + return "---\n"; } })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index d8747ef4805..03e330b4346 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -23,17 +23,18 @@ describe("WikiAST serialization tests", function() { 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 tiddlers with no special markup as-is", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree)).toBe(wiki.getTiddlerText('TiddlerOne')); + // `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)).toBe(wiki.getTiddlerText('TiddlerTwo')); + 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)).toBe(wiki.getTiddlerText('TiddlerThree')); + 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)).toBe(wiki.getTiddlerText('TiddlerFour')); + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerFour')); }); }); From 078967c830ad26a145c01bb41808f8fc24787f38 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:56:28 +0800 Subject: [PATCH 14/52] feat: allow recursive --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/codeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- core/modules/utils/parsetree.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 11681261b3a..99e25af559d 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; } diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index a78b56e6b64..4d32089ab57 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -55,8 +55,8 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { - return "`" + tree.children[0].text + "`"; +exports.serialize = function(tree,serialize) { + return "`" + serialize(tree.children) + "`"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index e9279a4d727..4fd66de415b 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,7 +31,7 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; -exports.serialize = function() { +exports.serialize = function(tree,serialize) { return "---\n"; } diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index f5b2c12d096..e825cd747dc 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -131,7 +131,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { - output.push(serializeParseTree(node)); + output.push(serializeParseTree(node,tiddlerType)); }); } else { if(tree.type === "text") { From 2aff9fecf19bc2ff918a3d2d85c94402be55121c Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 1 Aug 2024 23:29:48 +0800 Subject: [PATCH 15/52] feat: generate more rule and tests --- .../parsers/wikiparser/rules/commentblock.js | 17 +- .../parsers/wikiparser/rules/commentinline.js | 16 +- .../parsers/wikiparser/rules/conditional.js | 12 + core/modules/parsers/wikiparser/rules/dash.js | 5 + .../parsers/wikiparser/rules/entity.js | 5 + .../parsers/wikiparser/rules/extlink.js | 9 + .../rules/filteredtranscludeblock.js | 15 + .../rules/filteredtranscludeinline.js | 15 + .../parsers/wikiparser/rules/fnprocdef.js | 15 + .../wikiparser/rules/hardlinebreaks.js | 15 + .../parsers/wikiparser/rules/heading.js | 12 + core/modules/parsers/wikiparser/rules/html.js | 15 + .../modules/parsers/wikiparser/rules/image.js | 13 + .../parsers/wikiparser/rules/import.js | 7 + core/modules/parsers/wikiparser/rules/list.js | 24 ++ .../wikiparser/rules/macrocallblock.js | 11 + .../wikiparser/rules/macrocallinline.js | 11 + .../parsers/wikiparser/rules/macrodef.js | 13 + .../parsers/wikiparser/rules/parameters.js | 9 + .../parsers/wikiparser/rules/parsermode.js | 7 + .../parsers/wikiparser/rules/prettyextlink.js | 9 + .../parsers/wikiparser/rules/prettylink.js | 11 +- .../tiddlers/tests/test-wikitext-serialize.js | 287 ++++++++++++++++-- 23 files changed, 516 insertions(+), 37 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1c303f38f8d..62bbd4088ff 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 671bd79d65b..50e861fe4a6 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 23940fd88ad..ead7fc0afec 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 45481bf07bb..60c82f0a72a 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 dc3917dafc8..7f15c8a95ca 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 5b9f57adf06..58b7e772e02 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 73bdff813d0..c66009f8535 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 c0b19a941e9..cb992dbed02 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 85bd14d5c69..a4259e574b5 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 94f517cd477..39ef6fc5c3a 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 7a0ecb9db9c..79df971e513 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 61c4ad9e1ec..911099b3781 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 6f58225e0c8..8591e544e41 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 bb1832255d7..7025d20f2b9 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 d89c201b9e1..8dc8411aa83 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 a2c10e04ab6..c3b0e92e9ac 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 e9f79f09e63..a62596414b5 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 2001f70d56c..31a93f27bc6 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 60bbd89017d..692f03ea774 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 72a6de067c3..4814a4ba1e5 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 4707fa0d0a4..e2cc48a7ea7 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 66c19dc8860..74a275e42d9 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 03e330b4346..b21627564f7 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() { - - // 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"}); - - 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')); - }); -}); -})(); +describe('WikiAST serialization tests', function () { + var wiki = new $tw.Wiki(); + + 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') + ); + }); + + 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') + ); + }); + + 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()); + }); +}); From bfd116a438a61f790928e77a4cbb8a079c75ccfa Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 2 Aug 2024 22:54:45 +0800 Subject: [PATCH 16/52] feat: generate more rule and tests --- .../parsers/wikiparser/rules/emphasis/bold.js | 13 ++ .../wikiparser/rules/emphasis/italic.js | 13 ++ .../rules/emphasis/strikethrough.js | 13 ++ .../wikiparser/rules/emphasis/subscript.js | 13 ++ .../wikiparser/rules/emphasis/superscript.js | 13 ++ .../wikiparser/rules/emphasis/underscore.js | 13 ++ core/modules/parsers/wikiparser/rules/html.js | 14 +- .../parsers/wikiparser/rules/quoteblock.js | 13 ++ .../modules/parsers/wikiparser/rules/rules.js | 13 ++ .../parsers/wikiparser/rules/styleblock.js | 22 +++ .../parsers/wikiparser/rules/styleinline.js | 22 +++ .../parsers/wikiparser/rules/syslink.js | 13 ++ .../modules/parsers/wikiparser/rules/table.js | 29 ++++ .../wikiparser/rules/transcludeblock.js | 37 +++++ .../wikiparser/rules/transcludeinline.js | 37 +++++ .../parsers/wikiparser/rules/typedblock.js | 15 ++ .../parsers/wikiparser/rules/wikilink.js | 13 ++ .../wikiparser/rules/wikilinkprefix.js | 11 ++ .../tiddlers/tests/test-wikitext-serialize.js | 153 ++++++++++++++++++ 19 files changed, 463 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index 3799feeb5ae..946fff7cfc7 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'strong', children: [{ type: 'text', text: 'bold' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "''"; + // Serialize the children of the bold element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "''"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 3e0744c4da9..798429ed2a8 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'em', children: [{ type: 'text', text: 'italic' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "//"; + // Serialize the children of the italic element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "//"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index 0fb34fc526a..57221705225 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'strike', children: [{ type: 'text', text: 'strikethrough' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "~~"; + // Serialize the children of the strikethrough element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "~~"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js index 12be0fbbc44..f4d9ecc5dd9 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'sub', children: [{ type: 'text', text: 'subscript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = ",,"; + // Serialize the children of the subscript element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += ",,"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js index 5a5330d8c64..e33e75ac406 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'sup', children: [{ type: 'text', text: 'superscript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "^^"; + // Serialize the children of the superscript element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "^^"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index d36bd242d7c..640b36e02d1 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'u', children: [{ type: 'text', text: 'underscore' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "__"; + // Serialize the children of the underscore element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "__"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 911099b3781..305f037de14 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -44,7 +44,7 @@ Parse the most recent match exports.parse = function() { // Retrieve the most recent match so that recursive calls don't overwrite it var tag = this.nextTag; - if (!tag.isSelfClosing) { + if(!tag.isSelfClosing) { tag.openTagStart = tag.start; tag.openTagEnd = tag.end; } @@ -66,22 +66,22 @@ exports.parse = function() { } tag.end = this.parser.pos; tag.closeTagEnd = tag.end; - if (tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') { + if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') { tag.closeTagStart = tag.end; } else { tag.closeTagStart = tag.closeTagEnd - 2; var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd; - if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd; - while (tag.closeTagStart >= closeTagMinPos) { + if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd; + while(tag.closeTagStart >= closeTagMinPos) { var char = this.parser.source[tag.closeTagStart]; - if (char === '>') { + if(char === '>') { tag.closeTagStart = -1; break; } - if (char === '<') break; + if(char === '<') break; tag.closeTagStart -= 1; } - if (tag.closeTagStart < closeTagMinPos) { + if(tag.closeTagStart < closeTagMinPos) { tag.closeTagStart = tag.end; } } diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index fdd6c860b7d..3f946cf1321 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,4 +73,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'blockquote', attributes: { class: { type: 'string', value: 'tc-quote' } }, children: [{ type: 'text', text: 'Quote text' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Split the class attribute value into an array of classes, classes: ['tc-quote'] + var classes = tree.attributes.class.value.split(" "); + // Start the serialized string with the opening delimiter and classes, serialized: '<< 0) { + serialized += "|" + params.join("|"); + } + // Close the serialized string + serialized += "}}"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 3ce9dc78e63..78839f92549 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -84,4 +84,41 @@ exports.parse = function() { } }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } } } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string + var serialized = "{{"; + // Check for tiddler attribute + if(tree.attributes.$tiddler) { + serialized += tree.attributes.$tiddler.value; + // Check for field attribute + if(tree.attributes.$field) { + serialized += "##" + tree.attributes.$field.value; + } + // Check for index attribute + if(tree.attributes.$index) { + serialized += "!!" + tree.attributes.$index.value; + } + } + // Check for template attribute + if(tree.attributes.$template) { + serialized += "||" + tree.attributes.$template.value; + } + // Check for parameters + var params = []; + for(var key in tree.attributes) { + if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { + params.push(tree.attributes[key].value); + } + } + if(params.length > 0) { + serialized += "|" + params.join("|"); + } + // Close the serialized string + serialized += "}}"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index 07c88be15fb..daaefb7b77d 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -83,4 +83,19 @@ exports.parse = function() { } }; +exports.serialize = function (tree, serialize) { + // tree: { type: 'element', tag: 'pre', children: [{ type: 'text', text: 'This will be rendered as JavaScript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter and type + var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute) + if(tree.attributes && tree.attributes.type) { + serialized += tree.attributes.type.value; + } + serialized += '\n'; // Serialize the children of the block + serialized += serialize(tree.children); // Close the serialized string + serialized += "\n$$$"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 6b195f9ff96..5762aeee40d 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -65,4 +65,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'link', attributes: { to: { type: 'string', value: 'AWikiLink' } }, children: [{ type: 'text', text: 'AWikiLink' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Check if the link is suppressed + var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; + // Initialize the serialized string + var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; + // Append the link text + serialized += tree.attributes.to.value; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index 60cb3d992ce..be902edc860 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -37,4 +37,15 @@ exports.parse = function() { return [{type: "text", text: linkText.substr(1)}]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'text', text: 'SuppressedLink' } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the unwikilink character + var serialized = $tw.config.textPrimitives.unWikiLink; + // Append the text + serialized += tree.text; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index b21627564f7..1ab8512261f 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -10,6 +10,60 @@ Tests the wikitext inverse-rendering from Wiki AST. describe('WikiAST serialization tests', function () { var wiki = new $tw.Wiki(); + wiki.addTiddler({ + title: 'BoldEmphasisTest', + text: "This is ''bold'' text" + }); + it('should serialize bold emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('BoldEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('BoldEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'ItalicEmphasisTest', + text: "This is //italic// text" + }); + it('should serialize italic emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ItalicEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ItalicEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'StrikethroughEmphasisTest', + text: "This is ~~strikethrough~~ text" + }); + it('should serialize strikethrough emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StrikethroughEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StrikethroughEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SubscriptEmphasisTest', + text: "This is ,,subscript,, text" + }); + it('should serialize subscript emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SubscriptEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SubscriptEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SuperscriptEmphasisTest', + text: "This is ^^superscript^^ text" + }); + it('should serialize superscript emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SuperscriptEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SuperscriptEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'UnderscoreEmphasisTest', + text: "This is __underscore__ text" + }); + it('should serialize underscore emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('UnderscoreEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); + }); + 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. @@ -261,4 +315,103 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); }); + + wiki.addTiddler({ + title: 'QuoteBlockTest', + text: '<<` around this list will also have the class `myClass`\n* List item 2\n@@', + }); + it('should serialize style blocks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StyleBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'StyleInlineTest', + text: '@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@', + }); + it('should serialize style inlines correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StyleInlineTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SysLinkTest', + text: '$:TiddlerTitle\n~$:TiddlerTitle' + }); + it('should serialize system links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SysLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SysLinkTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TableTest', + text: '|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |' + }); + it('should serialize tables correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TableTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TableTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TranscludeBlockTest', + text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + }); + it('should serialize block-level transclusions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TranscludeBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TranscludeInlineTest', + text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + }); + it('should serialize inline-level transclusions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TranscludeInlineTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TypedBlockTest', + text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$' + }); + it('should serialize typed blocks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TypedBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TypedBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'WikiLinkTest', + text: 'AWikiLink\nAnotherLink\n~SuppressedLink' + }); + it('should serialize wiki links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('WikiLinkTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'WikiLinkPrefixTest', + text: '~SuppressedLink' + }); + it('should serialize suppressed wiki links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkPrefixTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('WikiLinkPrefixTest').trimEnd()); + }); }); From d0678716aa21a4938d10ba99f669f86b5af09d0f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 00:10:38 +0800 Subject: [PATCH 17/52] fix: remove pragma:true, otherwise following text will become children of it --- core/modules/parsers/wikiparser/rules/commentblock.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 62bbd4088ff..0fc3c04223c 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -25,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "\n\nSome text\n\n\n\nMore text', @@ -106,7 +105,6 @@ describe('WikiAST serialization tests', function () { 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.', @@ -116,7 +114,6 @@ describe('WikiAST serialization tests', function () { 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 %>', @@ -126,7 +123,6 @@ describe('WikiAST serialization tests', function () { 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: ---', @@ -136,7 +132,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); }); - // Test case for entity rule wiki.addTiddler({ title: 'EntityTest', text: 'This is a copyright symbol: ©', @@ -146,7 +141,6 @@ describe('WikiAST serialization tests', function () { 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/', @@ -156,7 +150,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -166,7 +159,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -185,8 +177,8 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); }); + return; - // 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', @@ -196,7 +188,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -206,7 +197,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -216,7 +206,6 @@ describe('WikiAST serialization tests', function () { 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]]', @@ -226,7 +215,6 @@ describe('WikiAST serialization tests', function () { 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]]', @@ -236,7 +224,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -246,7 +233,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); - // Test case for macrocallblock rule wiki.addTiddler({ title: 'MacroCallBlockTest', text: '<>', @@ -256,7 +242,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); }); - // Test case for macrocallinline rule wiki.addTiddler({ title: 'MacroCallInlineTest', text: 'This is a macro call: <>', @@ -266,7 +251,6 @@ describe('WikiAST serialization tests', function () { 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', @@ -276,7 +260,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); }); - // Test case for parameters rule wiki.addTiddler({ title: 'ParametersTest', text: '\\parameters(param:defaultvalue,param2:defaultvalue)', @@ -286,7 +269,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); }); - // Test case for parsermode rule wiki.addTiddler({ title: 'ParserModeTest', text: '\\parsermode block\n\\parsermode inline', @@ -296,7 +278,6 @@ describe('WikiAST serialization tests', function () { 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]]', @@ -306,7 +287,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); }); - // Test case for prettylink rule wiki.addTiddler({ title: 'PrettyLinkTest', text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', From 383e1b68b5d790c7594879c66dd630032446d133 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 02:04:26 +0800 Subject: [PATCH 20/52] fix: some test --- .../parsers/wikiparser/rules/fnprocdef.js | 4 +-- .../wikiparser/rules/hardlinebreaks.js | 25 ++++++++--------- .../parsers/wikiparser/rules/heading.js | 11 +++----- core/modules/parsers/wikiparser/rules/html.js | 2 +- .../modules/parsers/wikiparser/rules/image.js | 10 +++---- .../tiddlers/tests/test-wikitext-serialize.js | 28 +++++++++---------- 6 files changed, 37 insertions(+), 43 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index a4259e574b5..82c4b621741 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -104,8 +104,8 @@ exports.serialize = function(tree, serialize) { }).join(","); // Definition text var definition = tree.attributes.value.value; - // Construct the serialized string - return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end"; + // Construct the serialized string, concat the children because pragma rule wrap everything below it as children + return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children) + "\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js index 39ef6fc5c3a..9f26c3d956e 100644 --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js @@ -53,23 +53,22 @@ exports.parse = function() { } } } while(match && !match[1]); - // Return the nodes + // Mark first and last node, and return the nodes + if(tree[0]) tree[0].isRuleStart = true; + if(tree[tree.length-1]) tree[tree.length-1].isRuleEnd = true; 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; + // we get each of element on tree from `parse` one by one here. + var text = tree.tag === 'br' ? '\n' : tree.text; + if(tree.isRuleStart) { + return '"""\n' + text; + } + if(tree.isRuleEnd) { + return text + '"""'; + } + return text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 79df971e513..67470c9c50f 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -47,14 +47,11 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // Heading level - var headingLevel = tree.tag.length - 1; - // Classes + // Get heading level from number after `h` + var headingLevel = parseInt(tree.tag.substr(1),10); 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; + var headingText = serialize(tree.children); + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 656759ed825..1e3f9865bd1 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -199,7 +199,7 @@ 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) : ''; // Self-closing tag diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 8591e544e41..33454f46ec2 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -131,16 +131,14 @@ exports.parseImage = function(source,pos) { }; exports.serialize = function(tree) { - // Width attribute + // DEBUG: console tree + console.warn(`tree`, JSON.stringify(tree, null, ' ')); 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 padSpace = width || height ? " " : ""; 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 + "]]"; + return "[img" + width + height + padSpace + "[" + tooltip + source + "]]"; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index d3ab4dc04c7..69800a81ff7 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -7,7 +7,7 @@ Tests the wikitext inverse-rendering from Wiki AST. \*/ -describe('WikiAST serialization tests', function () { +describe('WikiAST serialization unit tests', function () { var wiki = new $tw.Wiki(); wiki.addTiddler({ @@ -64,35 +64,35 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); }); - wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); + wiki.addTiddler({ title: 'SimpleTextTest', 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') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('SimpleTextTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('SimpleTextTest') ); }); - wiki.addTiddler({ title: 'TiddlerTwo', text: 'The rain in Spain\nfalls mainly on the plain' }); + wiki.addTiddler({ title: 'SoftLineBreakTest', 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') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('SoftLineBreakTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('SoftLineBreakTest') ); }); - wiki.addTiddler({ title: 'TiddlerThree', text: 'The speed of sound\n\nThe light of speed' }); + wiki.addTiddler({ title: 'BlockRule', 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') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('BlockRule').tree).trimEnd()).toBe( + wiki.getTiddlerText('BlockRule') ); }); wiki.addTiddler({ - title: 'TiddlerFour', + title: 'CodeBlockTest', 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') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('CodeBlockTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('CodeBlockTest') ); }); @@ -177,7 +177,6 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); }); - return; wiki.addTiddler({ title: 'HardLineBreaksTest', @@ -214,6 +213,7 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); }); + return; wiki.addTiddler({ title: 'ImportTest', From 63613ceec04b20e9355e839cf3620150c62ab8b9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 16:21:55 +0800 Subject: [PATCH 21/52] feat: $tw.utils.serializeAttribute --- core/modules/parsers/parseutils.js | 31 +++++++++++++++++++ .../test/tiddlers/tests/test-html-parser.js | 31 +++++++++++++++++++ plugins/tiddlywiki/jasmine/jasmine-plugin.js | 2 +- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 2a2e3630947..b11300bfe2e 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -385,4 +385,35 @@ exports.parseAttribute = function(source,pos) { return node; }; +/* +Given a parsed attribute node, serialize it back into its source string representation. +*/ +exports.serializeAttribute = function(node) { + if(!node || typeof node !== 'object' || !node.name || !node.type) { + return null; + } + + var attributeString = node.name; + + if(node.type === 'string') { + if(node.value === 'true') { + return attributeString; + } + attributeString += '="' + node.value + '"'; + } else if(node.type === 'filtered') { + attributeString += '={{{' + node.filter + '}}}'; + } else if(node.type === 'indirect') { + attributeString += '={{' + node.textReference + '}}'; + } else if(node.type === 'substituted') { + attributeString += '=`' + node.rawValue + '`'; + } else if(node.type === 'macro') { + // Assuming macro serialization is complex and handled elsewhere + attributeString += '=' + node.value.serialize(); + } else { + return null; // Unsupported type + } + + return attributeString; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index d2266ca5ee0..4d07bc4f928 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -173,6 +173,37 @@ describe("HTML tag new parser tests", function() { ); }); + + describe('serializeAttribute', function () { + it('should serialize string attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'blah' })).toBe('p="blah"'); + expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'true' })).toBe('p'); + }); + + it('should serialize filtered attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'filtered', name: 'p', filter: 'blah' })).toBe('p={{{blah}}}'); + }); + + it('should serialize indirect attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'indirect', name: 'p', textReference: 'blah' })).toBe('p={{blah}}'); + }); + + it('should serialize substituted attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'substituted', name: 'p', rawValue: 'blah' })).toBe('p=`blah`'); + }); + + it('should return null for unsupported types', function () { + expect($tw.utils.serializeAttribute({ type: 'unknown', name: 'p', value: 'blah' })).toBeNull(); + }); + + it('should return null for invalid input', function () { + expect($tw.utils.serializeAttribute(null)).toBeNull(); + expect($tw.utils.serializeAttribute({})).toBeNull(); + expect($tw.utils.serializeAttribute({ type: 'string' })).toBeNull(); + expect($tw.utils.serializeAttribute({ name: 'p' })).toBeNull(); + }); + }); + it("should parse HTML tags", function() { expect(parser.parseTag("",1)).toEqual( null diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 488377b4493..73d5b55d5e0 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -13,7 +13,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 "use strict"; // DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]] [[test-html-parser.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 7b4ea476f35974eb933d44e4d5836e817f10b7f5 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 20:29:55 +0800 Subject: [PATCH 22/52] fix: use "" for string param --- core/modules/parsers/wikiparser/rules/image.js | 6 ++---- editions/test/tiddlers/tests/test-wikitext-serialize.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 33454f46ec2..f046c59f1bb 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -131,10 +131,8 @@ exports.parseImage = function(source,pos) { }; exports.serialize = function(tree) { - // DEBUG: console tree - console.warn(`tree`, JSON.stringify(tree, null, ' ')); - var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; - var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; + var width = tree.attributes.width ? " " + $tw.utils.serializeAttribute(tree.attributes.width) : ""; + var height = tree.attributes.height ? " " + $tw.utils.serializeAttribute(tree.attributes.height) : ""; var padSpace = width || height ? " " : ""; var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; var source = tree.attributes.source.value; diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 69800a81ff7..8e73c8ef911 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -207,7 +207,7 @@ describe('WikiAST serialization unit tests', function () { 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]]', + 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(); From f69795c62e9c25533141b975836cc91e486d21cc Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 22:41:58 +0800 Subject: [PATCH 23/52] feat: list --- .../parsers/wikiparser/rules/import.js | 6 +- core/modules/parsers/wikiparser/rules/list.js | 70 +++++++++++++------ .../tiddlers/tests/test-wikitext-serialize.js | 4 +- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index 7025d20f2b9..2142f7a583f 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -51,11 +51,11 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Filter attribute var filter = tree.attributes.filter.value; - // Construct the serialized string - return "\\import " + filter; + // Construct the serialized string with children that is actually the sibling below the pragma. + return "\\import " + filter + "\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index fbda167113d..704ad60aea1 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -153,28 +153,54 @@ exports.parse = function() { return [listStack[0]]; }; -exports.serialize = function(tree, serialize) { - // Serialize the list recursively - return serializeList(tree, serialize, 0); -}; +exports.serialize = function (tree, serialize) { + // Helper function to find the marker for a given list container tag and item tag + function findMarker(listTag, itemTag) { + for(var key in listTypes) { + if(listTypes[key].listTag === listTag && listTypes[key].itemTag === itemTag) { + return key; // Return the marker associated with the list tag and item tag + } + } + return ''; // Return empty string if no matching marker is found + } + + // Recursive function to serialize list nodes, handling nested lists and formatting output + function serializeList(node, markerPrefix) { + var result = []; + if(node.type === 'element' && ['ul', 'ol', 'dl', 'blockquote'].includes(node.tag)) { + node.children.forEach(function (child) { + if(['li', 'dt', 'dd', 'div'].includes(child.tag)) { + var currentMarker = findMarker(node.tag, child.tag); + // Handle class attributes + var classAttr = child.attributes && child.attributes.class ? '.' + child.attributes.class.value : ''; + // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. + var content = []; + $tw.utils.each(child.children,function (subNode) { + // Check if the child is a nested list or a simple line of list item + if(['ul', 'ol', 'dl', 'blockquote'].includes(subNode.tag)) { + // Recursive call for nested lists + if(content.length > 0) { + result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + content = [] + } + result.push(serializeList(subNode, markerPrefix + currentMarker).trim()) + } else { + content.push(serialize(subNode)) ; + } + return ''; // Default return for unhandled node types + }); + if(content.length > 0) { + result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + content = [] + } + } + }); + } + return result.join('\n'); + } -// 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); - // Construct the serialized list item - return Array(depth + 1).join(listTag[0]) + (classes ? "." + classes : "") + " " + children; - }).join("\n"); - // Return the serialized list - return items; -} + // Begin serialization from the root node, with an empty string as the initial marker prefix + return serializeList(tree, '') + '\n\n'; +}; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 8e73c8ef911..e19a2d922d8 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -213,11 +213,10 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); }); - return; wiki.addTiddler({ title: 'ImportTest', - text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', + text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]', }); it('should serialize import pragma correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); @@ -232,6 +231,7 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); + return; wiki.addTiddler({ title: 'MacroCallBlockTest', From 9df36a2b15a5f1c66a647819e96dea4b273d0b1c Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:29:33 +0800 Subject: [PATCH 24/52] refactor: ' -> " --- .../parsers/wikiparser/rules/conditional.js | 10 +++---- core/modules/parsers/wikiparser/rules/list.js | 27 ++++++++++------- .../wikiparser/rules/macrocallblock.js | 30 ++++++++++++------- .../wikiparser/rules/macrocallinline.js | 28 +++++++++++------ .../parsers/wikiparser/rules/macrodef.js | 2 +- .../parsers/wikiparser/rules/parameters.js | 2 +- .../tiddlers/tests/test-wikitext-serialize.js | 8 ++--- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 2 +- 8 files changed, 68 insertions(+), 41 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 88d243d0e5d..3a4486cf2ab 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -121,24 +121,24 @@ exports.serialize = function(tree, serialize) { var filterCondition = tree.attributes.filter.value; var ifClause = serialize(tree.children[0].children); var elseClause = tree.children[1].children; - var serialized = '<% if ' + filterCondition + '%>' + ifClause; + var serialized = "<% if " + filterCondition + "%>" + ifClause; if(elseClause && elseClause.length > 0) { for(var i = 0; i < elseClause.length; i++) { - if(elseClause[i].type === 'list' && elseClause[i].attributes.filter) { + if(elseClause[i].type === "list" && elseClause[i].attributes.filter) { // Handle elseif clause var elseifCondition = elseClause[i].attributes.filter.value; var elseifClause = serialize(elseClause[i].children[0]); - serialized += '<% elseif ' + elseifCondition + '%>' + elseifClause; + serialized += "<% elseif " + elseifCondition + "%>" + elseifClause; } if(elseClause[i].children[1]) { var elseClauseText = serialize(elseClause[i].children[1]); - serialized += '<% else %>' + elseClauseText; + serialized += "<% else %>" + elseClauseText; } } } - serialized += '<% endif %>'; + serialized += "<% endif %>"; return serialized; }; diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index 704ad60aea1..71a7cab5e59 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -63,6 +63,13 @@ var listTypes = { ">": {listTag: "blockquote", itemTag: "div"} }; +var listTags = Object.values(listTypes).map(function(type) { + return type.listTag; +}); +var itemTags = Object.values(listTypes).map(function(type) { + return type.itemTag; +}); + /* Parse the most recent match */ @@ -161,46 +168,46 @@ exports.serialize = function (tree, serialize) { return key; // Return the marker associated with the list tag and item tag } } - return ''; // Return empty string if no matching marker is found + return ""; // Return empty string if no matching marker is found } // Recursive function to serialize list nodes, handling nested lists and formatting output function serializeList(node, markerPrefix) { var result = []; - if(node.type === 'element' && ['ul', 'ol', 'dl', 'blockquote'].includes(node.tag)) { + if(node.type === "element" && listTags.includes(node.tag)) { node.children.forEach(function (child) { - if(['li', 'dt', 'dd', 'div'].includes(child.tag)) { + if(itemTags.includes(child.tag)) { var currentMarker = findMarker(node.tag, child.tag); // Handle class attributes - var classAttr = child.attributes && child.attributes.class ? '.' + child.attributes.class.value : ''; + var classAttr = child.attributes && child.attributes.class ? "." + child.attributes.class.value : ""; // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. var content = []; $tw.utils.each(child.children,function (subNode) { // Check if the child is a nested list or a simple line of list item - if(['ul', 'ol', 'dl', 'blockquote'].includes(subNode.tag)) { + if(listTags.includes(subNode.tag)) { // Recursive call for nested lists if(content.length > 0) { - result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } result.push(serializeList(subNode, markerPrefix + currentMarker).trim()) } else { content.push(serialize(subNode)) ; } - return ''; // Default return for unhandled node types + return ""; // Default return for unhandled node types }); if(content.length > 0) { - result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } } }); } - return result.join('\n'); + return result.join("\n"); } // Begin serialization from the root node, with an empty string as the initial marker prefix - return serializeList(tree, '') + '\n\n'; + return serializeList(tree, "") + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index c3b0e92e9ac..923484baec2 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -32,7 +32,7 @@ exports.findNextMatch = function(startPos) { var c = this.parser.source.charAt(nextCall.end); // Ensure EOL after parsed macro // If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym - if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) { + if((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) { this.nextCall = nextCall; return nextStart; } @@ -53,15 +53,25 @@ 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 + ">>"; +/* +Serialize a macro call node to wikitext +*/ +exports.serialize = function (node) { + // Start with macro opener + var result = "<<"; + if(node.attributes && node.attributes["$variable"]) { + result += node.attributes["$variable"].value; // Add macro name + } + // Append ordered arguments if any + if(node.orderedAttributes) { + node.orderedAttributes.forEach(function (attr) { + if(attr.name !== "$variable") { + result += " " + '"' + attr.value + '"'; // Add each additional value + } + }); + } + result += ">>\n\n"; + return result; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index a62596414b5..bc0ac7f2257 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -46,15 +46,25 @@ 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 + ">>"; +/* +Same as macrocallblock but without \n\n +*/ +exports.serialize = function (node) { + // Start with macro opener + var result = "<<"; + if(node.attributes && node.attributes["$variable"]) { + result += node.attributes["$variable"].value; // Add macro name + } + // Append ordered arguments if any + if(node.orderedAttributes) { + node.orderedAttributes.forEach(function (attr) { + if(attr.name !== "$variable") { + result += " " + '"' + attr.value + '"'; // Add each additional value + } + }); + } + result += ">>"; + return result; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 31a93f27bc6..735c7958a5a 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -99,7 +99,7 @@ exports.serialize = function(tree) { // Definition text var definition = tree.attributes.value.value; // Construct the serialized string - return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end"; + return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index 692f03ea774..ddb3a65ab9a 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -63,7 +63,7 @@ exports.serialize = function(tree) { return param.name + (param.value ? ":" + param.value : ""); }).join(","); // Construct the serialized string - return "\\parameters(" + params + ")"; + return "\\parameters(" + params + ")\n\n" + serialize(tree.children); }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index e19a2d922d8..03241754967 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -231,11 +231,10 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); - return; wiki.addTiddler({ title: 'MacroCallBlockTest', - text: '<>', + text: '<>\n\n<<.def "macro calls">>', }); it('should serialize block macro calls correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); @@ -244,7 +243,7 @@ describe('WikiAST serialization unit tests', function () { wiki.addTiddler({ title: 'MacroCallInlineTest', - text: 'This is a macro call: <>', + text: 'These are macro calls in a line: <> and <<.def "macro calls">>', }); it('should serialize inline macro calls correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); @@ -271,12 +270,13 @@ describe('WikiAST serialization unit tests', function () { wiki.addTiddler({ title: 'ParserModeTest', - text: '\\parsermode block\n\\parsermode inline', + text: '\\parsermode block\n\n\\parsermode inline\n\nTest.', }); 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()); }); + return; wiki.addTiddler({ title: 'PrettyExtLinkTest', diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 73d5b55d5e0..488377b4493 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -13,7 +13,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 "use strict"; // DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]] [[test-html-parser.js]]"; +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 2a75077747a979125cfe3dee35cc09c913c30864 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:35:16 +0800 Subject: [PATCH 25/52] fix: parsemode don't have node --- .../parsers/wikiparser/rules/parsermode.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 4814a4ba1e5..c5ec0fdd1c3 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -34,6 +34,7 @@ Parse the most recent match */ exports.parse = function() { // Move past the pragma invocation + var start = this.parser.pos; this.parser.pos = this.matchRegExp.lastIndex; // Parse whitespace delimited tokens terminated by a line break var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg, @@ -61,15 +62,17 @@ exports.parse = function() { this.parser.parseAsInline = true; } } - // No parse tree nodes to return - return []; + return [{ + type: "parsermode", + parseAsInline: this.parser.parseAsInline, + start: start, + end: this.parser.pos + }]; }; -exports.serialize = function(tree) { - // Parser mode - var mode = tree.parser.parseAsInline ? "inline" : "block"; - // Construct the serialized string - return "\\parsermode " + mode; +exports.serialize = function(tree,serialize) { + var mode = tree.parseAsInline ? "inline" : "block"; + return "\\parsermode " + mode + "\n\n" + serialize(tree.children); }; })(); From c39297698f995798d96809a23270ef665bd2c34f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:48:29 +0800 Subject: [PATCH 26/52] fix: render invisible comment and parsemode as data element --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 ++- core/modules/parsers/wikiparser/rules/commentinline.js | 3 ++- core/modules/parsers/wikiparser/rules/macrodef.js | 2 +- core/modules/parsers/wikiparser/rules/parameters.js | 2 +- core/modules/parsers/wikiparser/rules/parsermode.js | 3 ++- core/modules/utils/parsetree.js | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 0fc3c04223c..56a0857dda2 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,7 +55,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "commentblock", + type: "element", + tag: "data", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 50e861fe4a6..5ddcd8c8291 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,7 +48,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "commentinline", + type: "element", + tag: "data", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 735c7958a5a..9dec0768250 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -89,7 +89,7 @@ exports.parse = function() { return parseTreeNodes; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Macro name var name = tree.attributes.name.value; // Parameters diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index ddb3a65ab9a..6be51c24b48 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Parameters var params = tree.orderedAttributes.map(function(param) { return param.name + (param.value ? ":" + param.value : ""); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index c5ec0fdd1c3..713bb36ed06 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,7 +63,8 @@ exports.parse = function() { } } return [{ - type: "parsermode", + type: "element", + tag: "data", parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index 76ff385f0e4..670d6307b90 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -133,7 +133,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { $tw.utils.each(tree,function(node) { output.push(serializeParseTree(node,tiddlerType)); }); - } else { + } else if(tree) { if(tree.type === "text" && !tree.rule) { output.push(tree.text); } else { From b22ca2b3df081123062b01486490d8f89cd5d433 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 18:54:15 +0800 Subject: [PATCH 27/52] feat: add void: true, in ast node to prevent render --- core/modules/parsers/wikiparser/rules/commentblock.js | 6 +++--- core/modules/parsers/wikiparser/rules/commentinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/parsermode.js | 4 ++-- core/modules/widgets/widget.js | 3 ++- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 3 +-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 56a0857dda2..1e9b2c62248 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,8 +55,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "element", - tag: "data", + type: "comment", + void: true, text: commentText, start: commentStart, end: commentEnd @@ -64,7 +64,7 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - return tree.text + "\n\n"; + return tree.text + "\n\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 5ddcd8c8291..01f76c1c688 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,8 +48,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "element", - tag: "data", + type: "comment", + void: true, text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 713bb36ed06..9aea958d2e9 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,8 +63,8 @@ exports.parse = function() { } } return [{ - type: "element", - tag: "data", + type: "parsermode", + void: true, parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index eb84fab4a8e..73c299d69b3 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -553,7 +553,8 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; - parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; + // Skip void node that is not intended for render. Show error for missing widgets. + parseTreeNode = {type: "text", text: parseTreeNode.void ? "" : "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable $tw.utils.each(options.variables,function(value,name) { diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 488377b4493..8dbf6568e97 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -12,8 +12,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 /*global $tw: true */ "use strict"; -// DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; +var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 5b2c3dbace13f78e4fc253fc84388d13301d94c5 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:18:01 +0000 Subject: [PATCH 28/52] feat: use void widget, so methods always return a widget --- core/modules/widgets/void.js | 49 ++++++++++++++++++++++++++++++++++ core/modules/widgets/widget.js | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100755 core/modules/widgets/void.js diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js new file mode 100755 index 00000000000..e7b982a3536 --- /dev/null +++ b/core/modules/widgets/void.js @@ -0,0 +1,49 @@ +/*\ +title: $:/core/modules/widgets/Void.js +type: application/javascript +module-type: widget + +Void widget that is not intended for render. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var VoidNodeWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +VoidNodeWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +VoidNodeWidget.prototype.render = function(parent,nextSibling) { + // Nothing to do for a void node +}; + +/* +Compute the internal state of the widget +*/ +VoidNodeWidget.prototype.execute = function() { + // Nothing to do for a void node +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +VoidNodeWidget.prototype.refresh = function(changedTiddlers) { + return false; +}; + +exports.void = VoidNodeWidget; + +})(); diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 73c299d69b3..6f2842d193c 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -554,7 +554,7 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { if(!WidgetClass) { WidgetClass = this.widgetClasses.text; // Skip void node that is not intended for render. Show error for missing widgets. - parseTreeNode = {type: "text", text: parseTreeNode.void ? "" : "Undefined widget '" + parseTreeNode.type + "'"}; + parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable $tw.utils.each(options.variables,function(value,name) { From 7bc408b3b0f9f0e1dc705a9dc85df3de94a5d555 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:38:54 +0000 Subject: [PATCH 29/52] feat: ast to use new widget type void --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 +-- core/modules/parsers/wikiparser/rules/commentinline.js | 3 +-- core/modules/parsers/wikiparser/rules/parsermode.js | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1e9b2c62248..a1510b8bcf8 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,8 +55,7 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "comment", - void: true, + type: "void", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 01f76c1c688..183eea447d9 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,8 +48,7 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "comment", - void: true, + type: "void", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 9aea958d2e9..ba165a28340 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,8 +63,7 @@ exports.parse = function() { } } return [{ - type: "parsermode", - void: true, + type: "void", parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos From 82ae7678a720b15c9f135e5ee6f21951c46af69a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:39:20 +0000 Subject: [PATCH 30/52] test: add rule: 'parseBlock' and isRuleEnd: true --- .../Parameterised-ParseTreeNodes.tid | 2 +- .../tiddlers/tests/test-wikitext-parser.js | 60 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid index 916e2abfb8d..6db3f8be2f8 100644 --- a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid @@ -26,4 +26,4 @@ title: TiddlerOne + title: ExpectedResult -

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file +

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83,"rule":"parseBlock"}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 04d041ec9c8..0cb1a9f5577 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -26,87 +26,87 @@ describe("WikiText parser tests", function() { it("should parse tags", function() { expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 5, children : [ { type : 'text', text : '
', start : 0, end : 5 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'text', text : '
', start : 0, end : 5 } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] ); expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] ); expect(parse("
\n\nsome text
")).toEqual( - [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] + [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] ); expect(parse("
\n\nsome text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] ); expect(parse("
\n\n!some heading
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading
', start : 47, end : 71 } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading', start : 47, end : 71 } ] } ] } ] } ] } ] ); expect(parse("
\n!some heading
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] ); // Regression test for issue (#3306) expect(parse("
\n\nSome text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] ); }); @@ -206,38 +206,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":14,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":">")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -256,17 +256,17 @@ describe("WikiText parser tests", function() { ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] + [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] + [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', rule: 'parseBlock', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( @@ -294,7 +294,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed @@ -309,7 +309,7 @@ describe("WikiText parser tests", function() { it("should parse horizontal rules", function() { expect(parse("---Not a rule\n\n----\n\nBetween\n\n---")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', rule: 'parseBlock', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] ); @@ -318,7 +318,7 @@ describe("WikiText parser tests", function() { it("should parse hard linebreak areas", function() { expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual( - [ { type : 'element', tag : 'p', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34 } ], start : 0, end : 37 } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks', isRuleStart: true }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] ); From 893edf9ae3980794c093d3292ce457e868a6319f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 01:34:30 +0800 Subject: [PATCH 31/52] lint: quote --- .../tiddlers/tests/test-wikitext-serialize.js | 416 +++++++++--------- 1 file changed, 208 insertions(+), 208 deletions(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 03241754967..6b7ea72e076 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -7,391 +7,391 @@ Tests the wikitext inverse-rendering from Wiki AST. \*/ -describe('WikiAST serialization unit tests', function () { +describe("WikiAST serialization unit tests", function () { var wiki = new $tw.Wiki(); wiki.addTiddler({ - title: 'BoldEmphasisTest', - text: "This is ''bold'' text" + title: "BoldEmphasisTest", + text: "This is ''bold'' text", }); - it('should serialize bold emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('BoldEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('BoldEmphasisTest').trimEnd()); + it("should serialize bold emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("BoldEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("BoldEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'ItalicEmphasisTest', - text: "This is //italic// text" + title: "ItalicEmphasisTest", + text: "This is //italic// text", }); - it('should serialize italic emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ItalicEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ItalicEmphasisTest').trimEnd()); + it("should serialize italic emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ItalicEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ItalicEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'StrikethroughEmphasisTest', - text: "This is ~~strikethrough~~ text" + title: "StrikethroughEmphasisTest", + text: "This is ~~strikethrough~~ text", }); - it('should serialize strikethrough emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StrikethroughEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StrikethroughEmphasisTest').trimEnd()); + it("should serialize strikethrough emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StrikethroughEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StrikethroughEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'SubscriptEmphasisTest', - text: "This is ,,subscript,, text" + title: "SubscriptEmphasisTest", + text: "This is ,,subscript,, text", }); - it('should serialize subscript emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SubscriptEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SubscriptEmphasisTest').trimEnd()); + it("should serialize subscript emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SubscriptEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SubscriptEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'SuperscriptEmphasisTest', - text: "This is ^^superscript^^ text" + title: "SuperscriptEmphasisTest", + text: "This is ^^superscript^^ text", }); - it('should serialize superscript emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SuperscriptEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SuperscriptEmphasisTest').trimEnd()); + it("should serialize superscript emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SuperscriptEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SuperscriptEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'UnderscoreEmphasisTest', - text: "This is __underscore__ text" + title: "UnderscoreEmphasisTest", + text: "This is __underscore__ text", }); - it('should serialize underscore emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('UnderscoreEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); + it("should serialize underscore emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("UnderscoreEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("UnderscoreEmphasisTest").trimEnd()); }); - wiki.addTiddler({ title: 'SimpleTextTest', text: 'The quick brown fox' }); - it('should render tiddlers with no special markup as-is', function () { + wiki.addTiddler({ title: "SimpleTextTest", 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('SimpleTextTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('SimpleTextTest') + expect($tw.utils.serializeParseTree(wiki.parseTiddler("SimpleTextTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("SimpleTextTest") ); }); - wiki.addTiddler({ title: 'SoftLineBreakTest', text: 'The rain in Spain\nfalls mainly on the plain' }); - it('should preserve single new lines', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('SoftLineBreakTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('SoftLineBreakTest') + wiki.addTiddler({ title: "SoftLineBreakTest", text: "The rain in Spain\nfalls mainly on the plain" }); + it("should preserve single new lines", function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler("SoftLineBreakTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("SoftLineBreakTest") ); }); - wiki.addTiddler({ title: 'BlockRule', 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('BlockRule').tree).trimEnd()).toBe( - wiki.getTiddlerText('BlockRule') + wiki.addTiddler({ title: "BlockRule", 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("BlockRule").tree).trimEnd()).toBe( + wiki.getTiddlerText("BlockRule") ); }); wiki.addTiddler({ - title: 'CodeBlockTest', - text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', + title: "CodeBlockTest", + 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('CodeBlockTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('CodeBlockTest') + it("should render inline code and block code", function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler("CodeBlockTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("CodeBlockTest") ); }); wiki.addTiddler({ - title: 'CommentBlockTest', - text: '\n\nSome text\n\n\n\nMore text', + 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()); + it("should serialize block comments correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("CommentBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'CommentInlineTest', - text: 'This is some text with an inline comment and some more text.', + 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()); + it("should serialize inline comments correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("CommentInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'ConditionalTest', - text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', + 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()); + it("should serialize conditional statements correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ConditionalTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ConditionalTest").trimEnd()); }); wiki.addTiddler({ - title: 'DashTest', - text: 'This is an en-dash: --\n\nThis is an em-dash: ---', + 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()); + it("should serialize dashes correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("DashTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("DashTest").trimEnd()); }); wiki.addTiddler({ - title: 'EntityTest', - text: 'This is a copyright symbol: ©', + 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()); + it("should serialize HTML entities correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("EntityTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("EntityTest").trimEnd()); }); wiki.addTiddler({ - title: 'ExtLinkTest', - text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', + 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()); + it("should serialize external links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ExtLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ExtLinkTest").trimEnd()); }); 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', + 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()); + 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()); }); 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', + 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()); + 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', + 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()); + 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()); }); wiki.addTiddler({ - title: 'HardLineBreaksTest', + 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()); + 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()); }); wiki.addTiddler({ - title: 'HeadingTest', - text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', + 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()); + it("should serialize headings correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HeadingTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("HeadingTest").trimEnd()); }); wiki.addTiddler({ - title: 'HtmlTest', + 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()); + 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()); }); wiki.addTiddler({ - title: 'ImageTest', + 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()); + it("should serialize image tags correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImageTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ImageTest").trimEnd()); }); wiki.addTiddler({ - title: 'ImportTest', - text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]', + title: "ImportTest", + text: "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]", }); - it('should serialize import pragma correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); + it("should serialize import pragma correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImportTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ImportTest").trimEnd()); }); 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', + 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()); + it("should serialize lists correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ListTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ListTest").trimEnd()); }); wiki.addTiddler({ - title: 'MacroCallBlockTest', + title: "MacroCallBlockTest", text: '<>\n\n<<.def "macro calls">>', }); - 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()); + 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()); }); wiki.addTiddler({ - title: 'MacroCallInlineTest', + title: "MacroCallInlineTest", text: 'These are macro calls in a line: <> and <<.def "macro calls">>', }); - 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()); + 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()); }); wiki.addTiddler({ - title: 'MacroDefTest', - text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', + 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()); + it("should serialize macro definitions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroDefTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("MacroDefTest").trimEnd()); }); wiki.addTiddler({ - title: 'ParametersTest', - text: '\\parameters(param:defaultvalue,param2:defaultvalue)', + 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()); + it("should serialize parameter definitions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParametersTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ParametersTest").trimEnd()); }); wiki.addTiddler({ - title: 'ParserModeTest', - text: '\\parsermode block\n\n\\parsermode inline\n\nTest.', + title: "ParserModeTest", + text: "\\parsermode block\n\n\\parsermode inline\n\nTest.", }); - 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()); + 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()); }); return; wiki.addTiddler({ - title: 'PrettyExtLinkTest', - text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', + 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()); + 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()); }); wiki.addTiddler({ - title: 'PrettyLinkTest', - text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', + 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()); + it("should serialize pretty links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("PrettyLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("PrettyLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'QuoteBlockTest', - text: '<<` around this list will also have the class `myClass`\n* List item 2\n@@', + title: "StyleBlockTest", + text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
    ` around this list will also have the class `myClass`\n* List item 2\n@@", }); - it('should serialize style blocks correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StyleBlockTest').trimEnd()); + it("should serialize style blocks correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'StyleInlineTest', - text: '@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@', + title: "StyleInlineTest", + text: "@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", }); - it('should serialize style inlines correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StyleInlineTest').trimEnd()); + it("should serialize style inlines correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'SysLinkTest', - text: '$:TiddlerTitle\n~$:TiddlerTitle' + title: "SysLinkTest", + text: "$:TiddlerTitle\n~$:TiddlerTitle", }); - it('should serialize system links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SysLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SysLinkTest').trimEnd()); + it("should serialize system links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SysLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SysLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'TableTest', - text: '|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |' + title: "TableTest", + text: "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |", }); - it('should serialize tables correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TableTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TableTest').trimEnd()); + it("should serialize tables correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); wiki.addTiddler({ - title: 'TranscludeBlockTest', - text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + title: "TranscludeBlockTest", + text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", }); - it('should serialize block-level transclusions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TranscludeBlockTest').trimEnd()); + it("should serialize block-level transclusions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TranscludeBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'TranscludeInlineTest', - text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + title: "TranscludeInlineTest", + text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", }); - it('should serialize inline-level transclusions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TranscludeInlineTest').trimEnd()); + it("should serialize inline-level transclusions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'TypedBlockTest', - text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$' + title: "TypedBlockTest", + text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$', }); - it('should serialize typed blocks correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TypedBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TypedBlockTest').trimEnd()); + it("should serialize typed blocks correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'WikiLinkTest', - text: 'AWikiLink\nAnotherLink\n~SuppressedLink' + title: "WikiLinkTest", + text: "AWikiLink\nAnotherLink\n~SuppressedLink", }); - it('should serialize wiki links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('WikiLinkTest').trimEnd()); + it("should serialize wiki links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("WikiLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'WikiLinkPrefixTest', - text: '~SuppressedLink' + title: "WikiLinkPrefixTest", + text: "~SuppressedLink", }); - it('should serialize suppressed wiki links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkPrefixTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('WikiLinkPrefixTest').trimEnd()); + it("should serialize suppressed wiki links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkPrefixTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("WikiLinkPrefixTest").trimEnd()); }); }); From d6b9d00ef794ef2bd85b30a349bae9066cb9bc8e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 01:34:33 +0800 Subject: [PATCH 32/52] Update widget.js --- core/modules/widgets/widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 6f2842d193c..eb84fab4a8e 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -553,7 +553,6 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; - // Skip void node that is not intended for render. Show error for missing widgets. parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable From 6ac9592bd7594d77a7c3488791d6361c5322f8cb Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:31:16 +0800 Subject: [PATCH 33/52] fix: void node need to handle its children --- .../modules/parsers/wikiparser/rules/commentblock.js | 3 ++- core/modules/parsers/wikiparser/rules/parsermode.js | 1 + core/modules/widgets/void.js | 12 ++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index a1510b8bcf8..7d9a68f142b 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -25,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":31,"end":60,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From e7d4819f0389a41b4bbe304d4c2b09db0a947235 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:52:12 +0800 Subject: [PATCH 35/52] lint: quote --- .../tiddlers/tests/test-wikitext-parser.js | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index a0cb99c9531..8a38ccc53cc 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -26,87 +26,87 @@ describe("WikiText parser tests", function() { it("should parse tags", function() { expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 4, children : [ { type : "element", tag : "br", start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'text', text : '
    ', start : 0, end : 5 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "text", text : "
    ", start : 0, end : 5 } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "element", tag : "div", start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 6, children : [ { type : "element", tag : "div", isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: "html" } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 11, children : [ { type : "element", tag : "div", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: "html" } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 20, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : "text", text : "some text", start : 5, end : 14 } ], start : 0, end : 20 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 30, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "string", value : "true", start : 4, end : 14, name: "attribute" } }, orderedAttributes: [ { type : "string", value : "true", start : 4, end : 14, name: "attribute" } ], children : [ { type : "text", text : "some text", start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: "html" } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 38, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: "html", isBlock : false, attributes : { attribute : { type : "string", name: "attribute", value : "value", start: 4, end: 22 } }, orderedAttributes: [ { type: "string", name: "attribute", value : "value", start: 4, end: 22 } ], children : [ { type : "text", text : "some text", start : 23, end : 32 } ], start : 0, end : 38 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 47, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } }, orderedAttributes: [ { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } ], children : [ { type : "text", text : "some text", start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: "html" } ] } ] ); expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "reveal", tag: "$reveal", rule: "html", attributes : { state : { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, type : { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, text : { start : 46, name : "text", type : "string", value : "", end : 54 } }, orderedAttributes: [ { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, { start : 46, name : "text", type : "string", value : "", end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 54, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } ], children : [ { type : "text", text : "some text", start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } ], children : [ { type : "text", text : "some text", start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] ); expect(parse("
    \n\nsome text
    ")).toEqual( - [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] + [ { type : "element", start : 0, attributes : { attribute : { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } }, orderedAttributes: [ { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } ], tag : "div", rule: "html", end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 41, end : 50, children : [ { type : "text", text : "some text", start : 41, end : 50 } ] } ] } ] ); expect(parse("
    \n\nsome text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 67, children : [ { type : "element", start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 46, end : 55, children : [ { type : "text", text : "some text", start : 46, end : 55 } ] } ] } ] } ] } ] ); expect(parse("
    \n\n!some heading
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading
    ', start : 47, end : 71 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 71, children : [ { type : "element", start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: "html", isBlock : true, children : [ { type : "element", tag : "h1", start: 46, end: 71, rule: "heading", attributes : { class : { type : "string", value : "", start: 47, end: 47 } }, children : [ { type : "text", text : "some heading", start : 47, end : 71 } ] } ] } ] } ] } ] ); expect(parse("
    \n!some heading
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 70, children : [ { type : "element", start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: "html", isBlock : false, children : [ { type : "text", text : "\n!some heading", start : 44, end : 58 } ] } ] } ] } ] ); // Regression test for issue (#3306) expect(parse("
    \n\nSome text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 48, children : [ { type : "element", start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { }, orderedAttributes: [ ], tag : "span", end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: "html", isBlock : false, children : [ { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "span", end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 19, end : 28, children : [ { type : "text", text : "Some text", start : 19, end : 28 } ] } ] } ] } ] } ] } ] ); }); @@ -193,12 +193,12 @@ describe("WikiText parser tests", function() { it("should block mode filtered transclusions", function() { expect(parse("{{{ filter }}}")).toEqual( - [ { type: 'list', attributes: { filter: { type: 'string', value: ' filter ', start: 3, end: 11 } }, isBlock: true, start: 0, end: 14, rule: "filteredtranscludeblock" } ] + [ { type: "list", attributes: { filter: { type: "string", value: " filter ", start: 3, end: 11 } }, isBlock: true, start: 0, end: 14, rule: "filteredtranscludeblock" } ] ); expect(parse("{{{ fil\nter }}}")).toEqual( - [ { type: 'list', attributes: { filter: { type: 'string', value: ' fil\nter ', start: 3, end: 12 } }, isBlock: true, start: 0, end: 15, rule: "filteredtranscludeblock" } ] + [ { type: "list", attributes: { filter: { type: "string", value: " fil\nter ", start: 3, end: 12 } }, isBlock: true, start: 0, end: 15, rule: "filteredtranscludeblock" } ] ); }); @@ -206,38 +206,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":14,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":">")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -246,7 +246,7 @@ describe("WikiText parser tests", function() { it("should parse block macro calls", function() { expect(parse("<>\n<>\r\n<>\n<>")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: 'transclude', start: 9, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: 'transclude', start: 19, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: 'transclude', start: 30, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: "transclude", start: 9, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: "transclude", start: 19, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: "transclude", start: 30, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] ); expect(parse("<>")).toEqual( @@ -256,17 +256,17 @@ describe("WikiText parser tests", function() { ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 10, children: [ { type: "text", text: "<< carrots", start : 0, end : 10 } ] }, { type: "transclude", start: 12, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 6, children: [ { type: "text", text: "before", start : 0, end : 6 } ] }, { type: "transclude", start: 8, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', rule: 'parseBlock', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: "element", tag: "p", rule: "parseBlock", start: 9, end: 14, children: [ { type: "text", text: "after", start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( @@ -276,7 +276,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>' >>")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] ); }); @@ -294,7 +294,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed @@ -309,7 +309,7 @@ describe("WikiText parser tests", function() { it("should parse horizontal rules", function() { expect(parse("---Not a rule\n\n----\n\nBetween\n\n---")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', rule: 'parseBlock', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 13, children : [ { type : "entity", entity : "—", start: 0, end: 3, rule: "dash" }, { type : "text", text : "Not a rule", start : 3, end : 13 } ] }, { type : "element", tag : "hr", start: 15, end: 20, rule: "horizrule" }, { type : "element", tag : "p", rule: "parseBlock", start : 21, end : 28, children : [ { type : "text", text : "Between", start : 21, end : 28 } ] }, { type : "element", tag : "hr", start: 30, end: 33, rule: "horizrule" } ] ); @@ -318,7 +318,7 @@ describe("WikiText parser tests", function() { it("should parse hard linebreak areas", function() { expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks', isRuleStart: true }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] + [ { type : "element", tag : "p", rule: "parseBlock", children : [ { type : "text", text : "Something", start : 3, end : 12, rule: "hardlinebreaks", isRuleStart: true }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] ); From af2ddaa350778ba535ebb1e1a42cbe48ab50e9ad Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:58:28 +0800 Subject: [PATCH 36/52] Update void.js --- core/modules/widgets/void.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js index cc8e803c07f..d2b6445a788 100755 --- a/core/modules/widgets/void.js +++ b/core/modules/widgets/void.js @@ -29,6 +29,7 @@ Render this widget into the DOM VoidNodeWidget.prototype.render = function(parent,nextSibling) { // Nothing to do for a void node, but render the children. Nodes generated by pragma rules are holding everything below it in the children. this.parentDomNode = parent; + this.computeAttributes() this.execute(); this.renderChildren(parent,nextSibling); }; From b8125d13b8132adf21e1fe055eb96872177af220 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 03:04:03 +0800 Subject: [PATCH 37/52] Update test-wikitext-parser.js --- editions/test/tiddlers/tests/test-wikitext-parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 8a38ccc53cc..9c3ae78ce12 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -185,7 +185,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":31,"end":60,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From 2fa454ad843827419ea5c908c6460f8ca4bd579f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 7 Aug 2024 23:53:48 +0800 Subject: [PATCH 38/52] fix: macrodef with comment (void node) not working --- core/modules/widgets/importvariables.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/modules/widgets/importvariables.js b/core/modules/widgets/importvariables.js index 3e1ac3fc6fc..1ccd0400353 100644 --- a/core/modules/widgets/importvariables.js +++ b/core/modules/widgets/importvariables.js @@ -52,7 +52,8 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:false}); if(parser) { var parseTreeNode = parser.tree[0]; - while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) { + // process AST nodes generated by pragma rules. + while(parseTreeNode && ["setvariable","set","parameters","void"].indexOf(parseTreeNode.type) !== -1) { var node = { type: "set", attributes: parseTreeNode.attributes, @@ -85,7 +86,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { // this widget. If it needs to refresh, // it'll do so along with the the whole // importvariable tree. - if (widgetPointer != this) { + if(widgetPointer != this) { widgetPointer.makeChildWidgets = function(){}; } widgetPointer = widgetPointer.children[0]; @@ -96,7 +97,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { } }); - if (widgetPointer != this) { + if(widgetPointer != this) { widgetPointer.parseTreeNode.children = this.parseTreeNode.children; } else { widgetPointer.makeChildWidgets(); From fb8732a0812c368165418a4bcf9f3499f8cd609a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 7 Aug 2024 23:58:45 +0800 Subject: [PATCH 39/52] lint: ' -> " --- .../test/tiddlers/tests/test-html-parser.js | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index 4d07bc4f928..36eeea32180 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -27,7 +27,7 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseWhiteSpace("p ",1)).toEqual( - { type : 'whitespace', start : 1, end : 3 } + { type : "whitespace", start : 1, end : 3 } ); }); @@ -36,7 +36,7 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseTokenString("p= ",1,"=")).toEqual( - { type : 'token', value : '=', start : 1, end : 2 } + { type : "token", value : "=", start : 1, end : 2 } ); }); @@ -45,10 +45,10 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseTokenRegExp("p=' ",1,/(=(?:'|"))/g).match[0]).toEqual( - '=\'' + "='" ); expect($tw.utils.parseTokenRegExp("p=blah ",2,/([^\s>]+)/g).match[0]).toEqual( - 'blah' + "blah" ); }); @@ -57,40 +57,40 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseStringLiteral("p='blah' ",2)).toEqual( - { type : 'string', start : 2, value : 'blah', end : 8 } + { type : "string", start : 2, value : "blah", end : 8 } ); expect($tw.utils.parseStringLiteral("p='' ",2)).toEqual( - { type : 'string', start : 2, value : '', end : 4 } + { type : "string", start : 2, value : "", end : 4 } ); expect($tw.utils.parseStringLiteral("p=\"blah' ",2)).toEqual( null ); expect($tw.utils.parseStringLiteral("p=\"\" ",2)).toEqual( - { type : 'string', start : 2, value : '', end : 4 } + { type : "string", start : 2, value : "", end : 4 } ); }); it("should parse macro parameters", function() { expect($tw.utils.parseMacroParameter("me",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'me', end : 2 } + { type : "macro-parameter", start : 0, value : "me", end : 2 } ); expect($tw.utils.parseMacroParameter("me:one",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one', name : 'me', end : 6 } + { type : "macro-parameter", start : 0, value : "one", name : "me", end : 6 } ); expect($tw.utils.parseMacroParameter("me:'one two three'",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 18 } + { type : "macro-parameter", start : 0, value : "one two three", name : "me", end : 18 } ); expect($tw.utils.parseMacroParameter("'one two three'",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', end : 15 } + { type : "macro-parameter", start : 0, value : "one two three", end : 15 } ); expect($tw.utils.parseMacroParameter("me:[[one two three]]",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 20 } + { type : "macro-parameter", start : 0, value : "one two three", name : "me", end : 20 } ); expect($tw.utils.parseMacroParameter("[[one two three]]",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', end : 17 } + { type : "macro-parameter", start : 0, value : "one two three", end : 17 } ); expect($tw.utils.parseMacroParameter("myparam>",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'myparam>', end : 8 } + { type : "macro-parameter", start : 0, value : "myparam>", end : 8 } ); }); @@ -99,22 +99,22 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ ], name : 'mymacro', end : 11 } + { type : "macrocall", start : 0, params : [ ], name : "mymacro", end : 11 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', end : 13 }, { type : 'macro-parameter', start : 13, value : 'two', end : 17 }, { type : 'macro-parameter', start : 17, value : 'three', end : 23 } ], name : 'mymacro', end : 25 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one", end : 13 }, { type : "macro-parameter", start : 13, value : "two", end : 17 }, { type : "macro-parameter", start : 17, value : "three", end : 23 } ], name : "mymacro", end : 25 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', name : 'p', end : 15 }, { type : 'macro-parameter', start : 15, value : 'two', name : 'q', end : 21 }, { type : 'macro-parameter', start : 21, value : 'three', end : 27 } ], name : 'mymacro', end : 29 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one", name : "p", end : 15 }, { type : "macro-parameter", start : 15, value : "two", name : "q", end : 21 }, { type : "macro-parameter", start : 21, value : "three", end : 27 } ], name : "mymacro", end : 29 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', end : 25 } ], name : 'mymacro', end : 27 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one two three", end : 25 } ], name : "mymacro", end : 27 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', name : 'r', end : 27 } ], name : 'mymacro', end : 29 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one two three", name : "r", end : 27 } ], name : "mymacro", end : 29 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'two', name : 'one', end : 17 }, { type : 'macro-parameter', start : 17, value : 'four and five', name : 'three', end : 39 } ], name : 'myMacro', end : 41 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "two", name : "one", end : 17 }, { type : "macro-parameter", start : 17, value : "four and five", name : "three", end : 39 } ], name : "myMacro", end : 41 } ); }); @@ -123,84 +123,84 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseAttribute("p='blah' ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p=\"blah\" ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p=\"bl\nah\" ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'bl\nah', end : 9 } + { type : "string", start : 0, name : "p", value : "bl\nah", end : 9 } ); expect($tw.utils.parseAttribute("p={{{blah}}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : 'blah', end : 12 } + { type : "filtered", start : 0, name : "p", filter : "blah", end : 12 } ); expect($tw.utils.parseAttribute("p={{{bl\nah}}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : 'bl\nah', end : 13 } + { type : "filtered", start : 0, name : "p", filter : "bl\nah", end : 13 } ); expect($tw.utils.parseAttribute("p={{{ [{$:/layout}] }}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : ' [{$:/layout}] ', end : 23 } + { type : "filtered", start : 0, name : "p", filter : " [{$:/layout}] ", end : 23 } ); expect($tw.utils.parseAttribute("p={{blah}} ",0)).toEqual( - { type : 'indirect', start : 0, name : 'p', textReference : 'blah', end : 10 } + { type : "indirect", start : 0, name : "p", textReference : "blah", end : 10 } ); expect($tw.utils.parseAttribute("p=blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 6 } + { type : "string", start : 0, name : "p", value : "blah", end : 6 } ); expect($tw.utils.parseAttribute("p =blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } + { type : "string", start : 0, name : "p", value : "blah", end : 7 } ); expect($tw.utils.parseAttribute("p= blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } + { type : "string", start : 0, name : "p", value : "blah", end : 7 } ); expect($tw.utils.parseAttribute("p = blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p = >blah ",0)).toEqual( - { type : 'string', value : 'true', start : 0, name : 'p', end : 4 } + { type : "string", value : "true", start : 0, name : "p", end : 4 } ); expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual( - { type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 } + { type : "string", value : "true", start : 0, name : "attrib1", end : 8 } ); expect($tw.utils.parseAttribute("p=`blah` ",1)).toEqual(null); expect($tw.utils.parseAttribute("p=`blah` ",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 8 } + { start: 0, name: "p", type: "substituted", rawValue: "blah", end: 8 } ); expect($tw.utils.parseAttribute("p=```blah``` ",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 12 } + { start: 0, name: "p", type: "substituted", rawValue: "blah", end: 12 } ); expect($tw.utils.parseAttribute("p=`Hello \"There\"`",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'Hello "There"', end: 17 } + { start: 0, name: "p", type: "substituted", rawValue: 'Hello "There"', end: 17 } ); }); - describe('serializeAttribute', function () { - it('should serialize string attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'blah' })).toBe('p="blah"'); - expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'true' })).toBe('p'); + describe("serializeAttribute", function () { + it("should serialize string attributes", function () { + expect($tw.utils.serializeAttribute({ type: "string", name: "p", value: "blah" })).toBe('p="blah"'); + expect($tw.utils.serializeAttribute({ type: "string", name: "p", value: "true" })).toBe("p"); }); - it('should serialize filtered attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'filtered', name: 'p', filter: 'blah' })).toBe('p={{{blah}}}'); + it("should serialize filtered attributes", function () { + expect($tw.utils.serializeAttribute({ type: "filtered", name: "p", filter: "blah" })).toBe("p={{{blah}}}"); }); - it('should serialize indirect attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'indirect', name: 'p', textReference: 'blah' })).toBe('p={{blah}}'); + it("should serialize indirect attributes", function () { + expect($tw.utils.serializeAttribute({ type: "indirect", name: "p", textReference: "blah" })).toBe("p={{blah}}"); }); - it('should serialize substituted attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'substituted', name: 'p', rawValue: 'blah' })).toBe('p=`blah`'); + it("should serialize substituted attributes", function () { + expect($tw.utils.serializeAttribute({ type: "substituted", name: "p", rawValue: "blah" })).toBe("p=`blah`"); }); - it('should return null for unsupported types', function () { - expect($tw.utils.serializeAttribute({ type: 'unknown', name: 'p', value: 'blah' })).toBeNull(); + it("should return null for unsupported types", function () { + expect($tw.utils.serializeAttribute({ type: "unknown", name: "p", value: "blah" })).toBeNull(); }); - it('should return null for invalid input', function () { + it("should return null for invalid input", function () { expect($tw.utils.serializeAttribute(null)).toBeNull(); expect($tw.utils.serializeAttribute({})).toBeNull(); - expect($tw.utils.serializeAttribute({ type: 'string' })).toBeNull(); - expect($tw.utils.serializeAttribute({ name: 'p' })).toBeNull(); + expect($tw.utils.serializeAttribute({ type: "string" })).toBeNull(); + expect($tw.utils.serializeAttribute({ name: "p" })).toBeNull(); }); }); @@ -212,52 +212,52 @@ describe("HTML tag new parser tests", function() { null ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 7 } + { type : "element", start : 0, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 7 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', value : 'true', start : 6, name : 'attrib1', end : 14 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 14 } ], tag : 'mytag', end : 15 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", value : "true", start : 6, name : "attrib1", end : 14 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 14 } ], tag : "mytag", end : 15 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', value : 'true', start : 6, name : 'attrib1', end : 14 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 14 } ], tag : 'mytag', isSelfClosing : true, end : 16 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", value : "true", start : 6, name : "attrib1", end : 14 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 14 } ], tag : "mytag", isSelfClosing : true, end : 16 } ); expect(parser.parseTag("<$view field=\"title\" format=\"link\"/>",0)).toEqual( - { type : 'view', start : 0, attributes : { field : { start : 6, name : 'field', type : 'string', value : 'title', end : 20 }, format : { start : 20, name : 'format', type : 'string', value : 'link', end : 34 } }, orderedAttributes: [ { start: 6, name: 'field', type: 'string', value: 'title', end: 20 }, { start: 20, name: 'format', type: 'string', value: 'link', end: 34 } ], tag : '$view', isSelfClosing : true, end : 36 } + { type : "view", start : 0, attributes : { field : { start : 6, name : "field", type : "string", value : "title", end : 20 }, format : { start : 20, name : "format", type : "string", value : "link", end : 34 } }, orderedAttributes: [ { start: 6, name: "field", type: "string", value: "title", end: 20 }, { start: 20, name: "format", type: "string", value: "link", end: 34 } ], tag : "$view", isSelfClosing : true, end : 36 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 6, name : 'attrib1', value : 'something', end : 26 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'something', end: 26 } ], tag : 'mytag', end : 27 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 6, name : "attrib1", value : "something", end : 26 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "something", end: 26 } ], tag : "mytag", end : 27 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 15, name : 'attrib1', value : 'something', end : 34 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 15 }, { start: 15, name: 'attrib1', type: 'string', value: 'something', end: 34 } ], tag : 'mytag', end : 35 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 15, name : "attrib1", value : "something", end : 34 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 15 }, { start: 15, name: "attrib1", type: "string", value: "something", end: 34 } ], tag : "mytag", end : 35 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 34, name : 'attrib1', value : 'else', end : 49 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 15 }, { start: 15, name: 'attrib1', type: 'string', value: 'something', end: 34 }, { start: 34, name: 'attrib1', type: 'string', value: 'else', end: 49 } ], tag : 'mytag', end : 50 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 34, name : "attrib1", value : "else", end : 49 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 15 }, { start: 15, name: "attrib1", type: "string", value: "something", end: 34 }, { start: 34, name: "attrib1", type: "string", value: "else", end: 49 } ], tag : "mytag", end : 50 } ); expect(parser.parseTag("<$mytag attrib1='something' attrib2=else thing>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib1 : { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, attrib2 : { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, thing : { type : 'string', start : 40, name : 'thing', value : 'true', end : 46 } }, orderedAttributes: [ { start: 7, name: 'attrib1', type: 'string', value: 'something', end: 27 }, { start: 27, name: 'attrib2', type: 'string', value: 'else', end: 40 }, { start: 40, name: 'thing', type: 'string', value: 'true', end: 46 } ], tag : '$mytag', end : 47 } + { type : "mytag", start : 0, attributes : { attrib1 : { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, attrib2 : { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, thing : { type : "string", start : 40, name : "thing", value : "true", end : 46 } }, orderedAttributes: [ { start: 7, name: "attrib1", type: "string", value: "something", end: 27 }, { start: 27, name: "attrib2", type: "string", value: "else", end: 40 }, { start: 40, name: "thing", type: "string", value: "true", end: 46 } ], tag : "$mytag", end : 47 } ); expect(parser.parseTag("< $mytag attrib1='something' attrib2=else thing>",0)).toEqual( null ); expect(parser.parseTag("<$mytag attrib3=<>>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib3 : { type : 'macro', start : 7, name : 'attrib3', value : { type : 'macrocall', start : 16, params : [ { type : 'macro-parameter', start : 25, value : 'two', name : 'one', end : 33 }, { type : 'macro-parameter', start : 33, value : 'four and five', name : 'three', end : 55 } ], name : 'myMacro', end : 57 }, end : 57 } }, orderedAttributes: [ { type : 'macro', start : 7, name : 'attrib3', value : { type : 'macrocall', start : 16, params : [ { type : 'macro-parameter', start : 25, value : 'two', name : 'one', end : 33 }, { type : 'macro-parameter', start : 33, value : 'four and five', name : 'three', end : 55 } ], name : 'myMacro', end : 57 }, end : 57 } ], tag : '$mytag', end : 58 } + { type : "mytag", start : 0, attributes : { attrib3 : { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } }, orderedAttributes: [ { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } ], tag : "$mytag", end : 58 } ); expect(parser.parseTag("<$mytag attrib1='something' attrib2=else thing attrib3=<>>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib1 : { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, attrib2 : { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, thing : { type : 'string', start : 40, name : 'thing', value : 'true', end : 47 }, attrib3 : { type : 'macro', start : 47, name : 'attrib3', value : { type : 'macrocall', start : 55, params : [ { type : 'macro-parameter', start : 64, value : 'two', name : 'one', end : 72 }, { type : 'macro-parameter', start : 72, value : 'four and five', name : 'three', end : 94 } ], name : 'myMacro', end : 96 }, end : 96 } }, orderedAttributes: [ { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, { type : 'string', start : 40, name : 'thing', value : 'true', end : 47 }, { type : 'macro', start : 47, name : 'attrib3', value : { type : 'macrocall', start : 55, params : [ { type : 'macro-parameter', start : 64, value : 'two', name : 'one', end : 72 }, { type : 'macro-parameter', start : 72, value : 'four and five', name : 'three', end : 94 } ], name : 'myMacro', end : 96 }, end : 96 } ], tag : '$mytag', end : 97 } + { type : "mytag", start : 0, attributes : { attrib1 : { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, attrib2 : { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, thing : { type : "string", start : 40, name : "thing", value : "true", end : 47 }, attrib3 : { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } }, orderedAttributes: [ { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, { type : "string", start : 40, name : "thing", value : "true", end : 47 }, { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } ], tag : "$mytag", end : 97 } ); }); it("should find and parse HTML tags", function() { expect(parser.findNextTag("",1)).toEqual( - { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 18 } + { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 18 } ); expect(parser.findNextTag("something else ",0)).toEqual( null ); expect(parser.findNextTag("<> ",0)).toEqual( - { type : 'element', start : 1, attributes : { other : { type : 'string', value : 'true', start : 6, name : 'other', end : 13 }, stuff : { type : 'string', value : 'true', start : 13, name : 'stuff', end : 18 } }, orderedAttributes: [ { type : 'string', value : 'true', start : 6, name : 'other', end : 13 }, { type : 'string', value : 'true', start : 13, name : 'stuff', end : 18 } ], tag : 'some', end : 19 } + { type : "element", start : 1, attributes : { other : { type : "string", value : "true", start : 6, name : "other", end : 13 }, stuff : { type : "string", value : "true", start : 13, name : "stuff", end : 18 } }, orderedAttributes: [ { type : "string", value : "true", start : 6, name : "other", end : 13 }, { type : "string", value : "true", start : 13, name : "stuff", end : 18 } ], tag : "some", end : 19 } ); expect(parser.findNextTag("<> ",2)).toEqual( - { type : 'element', start : 21, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 28 } + { type : "element", start : 21, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 28 } ); }); From 078cd5fba2ab35819f24d835463fc77c287205ca Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 8 Aug 2024 01:16:27 +0800 Subject: [PATCH 40/52] feat: add to styleblock --- .../parsers/wikiparser/rules/quoteblock.js | 25 ++++--- .../modules/parsers/wikiparser/rules/rules.js | 36 ++++++---- .../parsers/wikiparser/rules/styleblock.js | 67 ++++++++++++++----- .../tiddlers/tests/test-wikitext-serialize.js | 10 ++- 4 files changed, 96 insertions(+), 42 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index 3f946cf1321..329d881b073 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,17 +73,20 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'blockquote', attributes: { class: { type: 'string', value: 'tc-quote' } }, children: [{ type: 'text', text: 'Quote text' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Split the class attribute value into an array of classes, classes: ['tc-quote'] - var classes = tree.attributes.class.value.split(" "); - // Start the serialized string with the opening delimiter and classes, serialized: '<< 0) { this.parser.amendRules(tokens[0],tokens.slice(1)); } - // No parse tree nodes to return - return []; + // No widget to render, return void node. + return [{ + type: "void", + attributes: { + action: {type: "string", value: tokens[0]}, + rules: {type: "string", value: tokens.slice(1).join(" ")} + }, + children: [] + }]; }; -exports.serialize = function(tree, serialize) { - // tree: { type: 'pragma', name: 'rules', args: ['except', 'ruleone', 'ruletwo', 'rulethree'] } - // serialize: function that accepts array of nodes or a node and returns a string - // Start the serialized string with the pragma name - var serialized = "\\rules"; - // Iterate over the arguments and append them to the serialized string - for(var i = 0; i < tree.args.length; i++) { - serialized += " " + tree.args[i]; +exports.serialize = function (tree, serialize) { + // tree: { type: "void", attributes: { action: { type: "string", value: "except" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [{ type: "void", attributes: { action: { type: "string", value: "only" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [] }] } + var result = []; + if(tree.attributes.action && tree.attributes.rules) { + // tree.attributes.action.value: "except" + // tree.attributes.rules.value: "ruleone ruletwo rulethree" + result.push("\\rules " + tree.attributes.action.value + " " + tree.attributes.rules.value); + tree.children.forEach(function (child) { + if(child.type === "void" && child.attributes.action && child.attributes.rules) { + // child.attributes.action.value: "only" + // child.attributes.rules.value: "ruleone ruletwo rulethree" + result.push("\\rules " + child.attributes.action.value + " " + child.attributes.rules.value); + } + }); } - // Return the complete serialized string - return serialized; + return result.join("\n"); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index 6ea89b5df9c..e054b09160a 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -67,29 +67,62 @@ exports.parse = function() { $tw.utils.addAttributeToParseTreeNode(tree[t],"style",styles.join("")); } } - return tree; + return [{ + type: "void", + children: tree + }] }; exports.serialize = function(tree, serialize) { - // tree: [{ type: 'element', tag: 'p', attributes: { class: { type: 'string', value: 'myClass' }, style: { type: 'string', value: 'background-color:red;' } }, children: [{ type: 'text', text: 'This paragraph will have the CSS class `myClass`.' }] }] - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter - var serialized = "@@"; - // Check for styles and append them to the serialized string - if(tree[0].attributes.style) { - serialized += tree[0].attributes.style.value; + // serialize: function that serializes an array of nodes or a single node to a string + var result = []; + var classes = []; + var styles = []; + + // Collect all unique classes and styles from child nodes + for(var i = 0; i < tree.children.length; i++) { + var node = tree.children[i]; + if(node.attributes && node.attributes.class) { + var nodeClasses = node.attributes.class.value.split(" "); + for(var j = 0; j < nodeClasses.length; j++) { + if(classes.indexOf(nodeClasses[j]) === -1) { + classes.push(nodeClasses[j]); + } + } + } + if(node.attributes && node.attributes.style) { + var nodeStyles = node.attributes.style.value.split(";"); + for(var k = 0; k < nodeStyles.length; k++) { + var style = nodeStyles[k].trim(); + if(style && styles.indexOf(style) === -1) { + styles.push(style); + } + } + } } - // Check for classes and append them to the serialized string - if(tree[0].attributes.class) { - var classes = tree[0].attributes.class.value.split(" "); - for(var i = 0; i < classes.length; i++) { - serialized += "." + classes[i]; + + // Add the style block header if there are any classes or styles + if(classes.length > 0 || styles.length > 0) { + if(styles.length > 0) { + result.push("@@"); + result.push(styles.join(";")); + result.push(";\n"); + } + if(classes.length > 0) { + result.push("@@."); + result.push(classes.join(".")); + result.push("\n"); } } - // Append the serialized children and the closing delimiter - serialized += "\n" + serialize(tree) + "\n@@"; - // Return the complete serialized string - return serialized; + + // Serialize each child node and add to result + for(var i = 0; i < tree.children.length; i++) { + result.push(serialize(tree.children[i])); + } + + // Add the closing @@ for the style block + result.push("@@"); + return result.join(""); }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 6b7ea72e076..7978b354fcd 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -276,7 +276,6 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParserModeTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("ParserModeTest").trimEnd()); }); - return; wiki.addTiddler({ title: "PrettyExtLinkTest", @@ -316,12 +315,19 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "StyleBlockTest", - text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
      ` around this list will also have the class `myClass`\n* List item 2\n@@", + text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
        ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text\n@@.coloured-bg\n* Block content\n* With custom style and classes\n@@", + }); + wiki.addTiddler({ + title: "StyleBlockTest2", + text: "@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", }); it("should serialize style blocks correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd()); + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").trimEnd()); }); + return; wiki.addTiddler({ title: "StyleInlineTest", From 7c73f1f9228dd95247474731b24a9967bf7296c4 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 8 Aug 2024 23:52:48 +0800 Subject: [PATCH 41/52] feat: styleblock --- .../parsers/wikiparser/rules/styleblock.js | 54 +++++++++---------- .../tiddlers/tests/test-wikitext-serialize.js | 4 +- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index e054b09160a..089c5f39591 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -75,54 +75,52 @@ exports.parse = function() { exports.serialize = function(tree, serialize) { // serialize: function that serializes an array of nodes or a single node to a string - var result = []; + var lines = []; var classes = []; var styles = []; - // Collect all unique classes and styles from child nodes - for(var i = 0; i < tree.children.length; i++) { - var node = tree.children[i]; - if(node.attributes && node.attributes.class) { - var nodeClasses = node.attributes.class.value.split(" "); - for(var j = 0; j < nodeClasses.length; j++) { - if(classes.indexOf(nodeClasses[j]) === -1) { - classes.push(nodeClasses[j]); - } + // Same classes are set to each children. So only collect from first child. + var node = tree.children[0]; + if(node && node.attributes && node.attributes.class) { + var nodeClasses = node.attributes.class.value.split(" "); + for(var j = 0; j < nodeClasses.length; j++) { + if(classes.indexOf(nodeClasses[j]) === -1) { + classes.push(nodeClasses[j]); } } - if(node.attributes && node.attributes.style) { - var nodeStyles = node.attributes.style.value.split(";"); - for(var k = 0; k < nodeStyles.length; k++) { - var style = nodeStyles[k].trim(); - if(style && styles.indexOf(style) === -1) { - styles.push(style); - } + } + if(node && node.attributes && node.attributes.style) { + var nodeStyles = node.attributes.style.value.split(";"); + for(var k = 0; k < nodeStyles.length; k++) { + var style = nodeStyles[k].trim(); + if(style && styles.indexOf(style) === -1) { + styles.push(style); } } } - // Add the style block header if there are any classes or styles + // Add the style block header, sort styles first, and classes later. Original order is not preserved intentionally for simplicity. if(classes.length > 0 || styles.length > 0) { if(styles.length > 0) { - result.push("@@"); - result.push(styles.join(";")); - result.push(";\n"); + lines.push("@@"); + lines.push(styles.join(";")); + lines.push(";\n"); } if(classes.length > 0) { - result.push("@@."); - result.push(classes.join(".")); - result.push("\n"); + lines.push("@@."); + lines.push(classes.join(".")); + lines.push("\n"); } } // Serialize each child node and add to result for(var i = 0; i < tree.children.length; i++) { - result.push(serialize(tree.children[i])); + lines.push(serialize(tree.children[i])); } - + var result = lines.join("").trimEnd(); // Add the closing @@ for the style block - result.push("@@"); - return result.join(""); + result += "\n@@\n\n" + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 7978b354fcd..7ee728cf6d1 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -315,11 +315,11 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "StyleBlockTest", - text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
          ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text\n@@.coloured-bg\n* Block content\n* With custom style and classes\n@@", + text: "@@background-color:red;\n@@.myClass\nThis paragraph will have the CSS class `myClass`.\n\n* The `
            ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text.coloured-bg\n* Block content\n* With custom style and classes\n@@", }); wiki.addTiddler({ title: "StyleBlockTest2", - text: "@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", + text: "@@width:100px;\n@@.myFirstClass.mySecondClass.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", }); it("should serialize style blocks correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); From 43f3f8b5ed5e39d116df225116e38da64a030384 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 19:50:07 +0800 Subject: [PATCH 42/52] feat: styleinline --- .../parsers/wikiparser/rules/styleinline.js | 31 ++++++++----------- .../tiddlers/tests/test-wikitext-serialize.js | 4 +-- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/styleinline.js b/core/modules/parsers/wikiparser/rules/styleinline.js index 281c2bc8dc8..873226f033e 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -25,7 +25,7 @@ exports.types = {inline: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?(\.(?:[^\r\n\s]+)\s+)?/mg; + this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?\s*(\.(?:[^\r\n\s]+)\s+)?/mg; }; exports.parse = function() { @@ -56,25 +56,20 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'span', attributes: { class: { type: 'string', value: 'myClass' }, style: { type: 'string', value: 'background-color:red;' } }, children: [{ type: 'text', text: 'This is some text with a class and a background colour' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter - var serialized = "@@"; - // Check for styles and append them to the serialized string - if(tree.attributes.style) { - serialized += tree.attributes.style.value; + // tree: {type: "element", tag: "span", children: [...], attributes: {class: {name: "class", type: "string", value: " myClass "}, style: {name: "style", type: "string", value: "background-color:red;"}}, orderedAttributes: [...], start: 0, end: 43, rule: "styleinline"} + // serialize: function that accepts an array of nodes or a single node and returns a string + var result = "@@"; + // Add styles if present + if(tree.attributes && tree.attributes.style) { + result += tree.attributes.style.value.trim(); } - // Check for classes and append them to the serialized string - if(tree.attributes.class) { - var classes = tree.attributes.class.value.split(" "); - for(var i = 0; i < classes.length; i++) { - serialized += "." + classes[i] + " "; - } + // Add classes if present + if(tree.attributes && tree.attributes.class) { + result += "." + tree.attributes.class.value.trim().split(" ").join("."); } - // Append the serialized children and the closing delimiter - serialized += serialize(tree.children) + "@@"; - // Return the complete serialized string - return serialized; + // Serialize children and append to result + result += " " + serialize(tree.children) + "@@"; + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 7ee728cf6d1..bfc4523adb2 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -327,11 +327,10 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").trimEnd()); }); - return; wiki.addTiddler({ title: "StyleInlineTest", - text: "@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", + text: "@@.myClass This is some text with a class@@\n@@background-color:red; This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", }); it("should serialize style inlines correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleInlineTest").tree).trimEnd(); @@ -355,6 +354,7 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); + return; wiki.addTiddler({ title: "TranscludeBlockTest", From 856cb42039382e1432239719fff2352e3156d300 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 22:33:05 +0800 Subject: [PATCH 43/52] Update table.js --- core/modules/parsers/wikiparser/rules/table.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index ed4c7c88930..9b730922d9e 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -186,9 +186,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'table', children: [{ type: 'element', tag: 'thead', children: [{ type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Alpha' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Beta' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Gamma' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Delta' }] }] }] }, { type: 'element', tag: 'tbody', children: [{ type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'One' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }, { type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Two' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }, { type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Three' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }] }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = ""; // Iterate over the table rows for(var i = 0; i < tree.children.length; i++) { @@ -201,10 +198,14 @@ exports.serialize = function(tree, serialize) { // Iterate over the cells in the row for(var k = 0; k < row.children.length; k++) { var cell = row.children[k]; + // if is th, append additional `!` + if(cell.tag === "th") { + serialized += "!"; + } // Serialize the cell content serialized += serialize(cell.children); - // End the cell - serialized += "|"; + // End the cell with a tailing space + serialized += " |"; } // End the row serialized += "\n"; From 3cf93d08e514959401992a696bc3f7572325362a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 22:45:14 +0800 Subject: [PATCH 44/52] lint: useless comments --- core/modules/parsers/wikiparser/rules/emphasis/bold.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/italic.js | 3 --- .../parsers/wikiparser/rules/emphasis/strikethrough.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/subscript.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/superscript.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/underscore.js | 3 --- core/modules/parsers/wikiparser/rules/quoteblock.js | 1 - core/modules/parsers/wikiparser/rules/rules.js | 1 - core/modules/parsers/wikiparser/rules/styleblock.js | 1 - core/modules/parsers/wikiparser/rules/styleinline.js | 2 -- core/modules/parsers/wikiparser/rules/syslink.js | 4 +--- core/modules/parsers/wikiparser/rules/transcludeblock.js | 3 --- core/modules/parsers/wikiparser/rules/transcludeinline.js | 3 --- core/modules/parsers/wikiparser/rules/typedblock.js | 3 --- core/modules/parsers/wikiparser/rules/wikilink.js | 4 +--- core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 3 --- 16 files changed, 2 insertions(+), 41 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index 946fff7cfc7..6294094ec5f 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'strong', children: [{ type: 'text', text: 'bold' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "''"; // Serialize the children of the bold element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 798429ed2a8..f1070ddfb87 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'em', children: [{ type: 'text', text: 'italic' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "//"; // Serialize the children of the italic element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index 57221705225..ccd511c4209 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'strike', children: [{ type: 'text', text: 'strikethrough' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "~~"; // Serialize the children of the strikethrough element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js index f4d9ecc5dd9..d38d5122253 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'sub', children: [{ type: 'text', text: 'subscript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = ",,"; // Serialize the children of the subscript element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js index e33e75ac406..82a4b78d624 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'sup', children: [{ type: 'text', text: 'superscript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "^^"; // Serialize the children of the superscript element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index 640b36e02d1..b07f32fc243 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'u', children: [{ type: 'text', text: 'underscore' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "__"; // Serialize the children of the underscore element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index 329d881b073..be705279570 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -74,7 +74,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: "element", tag: "blockquote", attributes: { class: { type: "string", value: "tc-quote" } }, children: [{ type: "element", tag: "cite", children: [{ type: "text", text: "tc-quote" }] }, { type: "element", tag: "p", children: [{ type: "text", text: "Quote text\n" }] }] } var result = []; if(tree.type === "element" && tree.tag === "blockquote") { // tree.attributes.class.value: "tc-quote" diff --git a/core/modules/parsers/wikiparser/rules/rules.js b/core/modules/parsers/wikiparser/rules/rules.js index 28af31abcf1..a5958d67cab 100644 --- a/core/modules/parsers/wikiparser/rules/rules.js +++ b/core/modules/parsers/wikiparser/rules/rules.js @@ -69,7 +69,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: "void", attributes: { action: { type: "string", value: "except" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [{ type: "void", attributes: { action: { type: "string", value: "only" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [] }] } var result = []; if(tree.attributes.action && tree.attributes.rules) { // tree.attributes.action.value: "except" diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index 089c5f39591..a5e19cfcce1 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -74,7 +74,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // serialize: function that serializes an array of nodes or a single node to a string var lines = []; var classes = []; var styles = []; diff --git a/core/modules/parsers/wikiparser/rules/styleinline.js b/core/modules/parsers/wikiparser/rules/styleinline.js index 873226f033e..01c047856fa 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -56,8 +56,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: {type: "element", tag: "span", children: [...], attributes: {class: {name: "class", type: "string", value: " myClass "}, style: {name: "style", type: "string", value: "background-color:red;"}}, orderedAttributes: [...], start: 0, end: 43, rule: "styleinline"} - // serialize: function that accepts an array of nodes or a single node and returns a string var result = "@@"; // Add styles if present if(tree.attributes && tree.attributes.style) { diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js index 8eed845aefd..0839e9087d7 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -51,11 +51,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'link', attributes: { to: { type: 'string', value: '$:TiddlerTitle' } }, children: [{ type: 'text', text: '$:TiddlerTitle' }] } - // serialize: function that accepts array of nodes or a node and returns a string // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === "~"; - // Initialize the serialized string + var serialized = isSuppressed ? "~" : ""; // Append the link value serialized += tree.attributes.to.value; diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index a4b1b8a55ee..9add8f6adc4 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -87,9 +87,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } }, isBlock: true } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = "{{"; // Check for tiddler attribute if(tree.attributes.$tiddler) { diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 78839f92549..346a9867166 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -85,9 +85,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } } } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = "{{"; // Check for tiddler attribute if(tree.attributes.$tiddler) { diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index daaefb7b77d..e428e85d8aa 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -84,9 +84,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: 'element', tag: 'pre', children: [{ type: 'text', text: 'This will be rendered as JavaScript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter and type var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute) if(tree.attributes && tree.attributes.type) { serialized += tree.attributes.type.value; diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 5762aeee40d..dc146a047e6 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -66,11 +66,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'link', attributes: { to: { type: 'string', value: 'AWikiLink' } }, children: [{ type: 'text', text: 'AWikiLink' }] } - // serialize: function that accepts array of nodes or a node and returns a string // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; - // Initialize the serialized string + var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; // Append the link text serialized += tree.attributes.to.value; diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index be902edc860..36aebf06376 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -38,9 +38,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'text', text: 'SuppressedLink' } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the unwikilink character var serialized = $tw.config.textPrimitives.unWikiLink; // Append the text serialized += tree.text; From 589241a406b7cfae935e6b61e4fb17d7bf8219ba Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 01:31:43 +0800 Subject: [PATCH 45/52] feat: transcludeblock --- .../wikiparser/rules/transcludeblock.js | 64 ++++++++++++------- .../tiddlers/tests/test-wikitext-serialize.js | 6 +- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 9add8f6adc4..88519e84dc2 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -87,37 +87,53 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - var serialized = "{{"; - // Check for tiddler attribute - if(tree.attributes.$tiddler) { - serialized += tree.attributes.$tiddler.value; - // Check for field attribute - if(tree.attributes.$field) { - serialized += "##" + tree.attributes.$field.value; + var result = "{{"; + function handleTransclude(transcludeNode) { + // Handle field + if(transcludeNode.attributes.$field) { + result += "!!" + transcludeNode.attributes.$field.value; } // Check for index attribute - if(tree.attributes.$index) { - serialized += "!!" + tree.attributes.$index.value; + if(transcludeNode.attributes.$index) { + result += "##" + transcludeNode.attributes.$index.value; + } + // Handle template + var tiddlerTitle = tree.attributes.tiddler ? tree.attributes.tiddler.value : undefined; + if(transcludeNode.attributes.$tiddler && transcludeNode.attributes.$tiddler.value !== tiddlerTitle) { + result += "||" + transcludeNode.attributes.$tiddler.value; + } + // Check for parameters + var params = []; + var excludedAttributes = ["tiddler", "$tiddler", "$field", "$index", "$template"]; + for(var key in transcludeNode.attributes) { + if(excludedAttributes.indexOf(key) === -1) { + params.push(transcludeNode.attributes[key].value); + } + } + if(params.length > 0) { + result += "|" + params.join("|"); } } - // Check for template attribute - if(tree.attributes.$template) { - serialized += "||" + tree.attributes.$template.value; - } - // Check for parameters - var params = []; - for(var key in tree.attributes) { - if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { - params.push(tree.attributes[key].value); + function handleTiddler(tiddlerNode) { + // Check for tiddler attribute + if(tree.attributes.tiddler.value) { + result += tree.attributes.tiddler.value; } + $tw.utils.each(tree.children, function(child) { + if(child.type === "transclude") { + handleTransclude(child); + } + }); } - if(params.length > 0) { - serialized += "|" + params.join("|"); + if(tree.type === "tiddler") { + handleTiddler(tree); + } else if(tree.type === "transclude") { + handleTransclude(tree); } - // Close the serialized string - serialized += "}}"; - // Return the complete serialized string - return serialized; + // Close the result string + result += "}}\n\n"; + // Return the complete result string + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index bfc4523adb2..b2a35e8bca6 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -354,11 +354,10 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); - return; wiki.addTiddler({ title: "TranscludeBlockTest", - text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", + text: "{{MyTiddler}}\n\n{{MyTiddler||TemplateTitle}}\n\n{{||TemplateTitle}}\n\n{{MyTiddler|Parameter}}\n\n{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}\n\n{{MyTiddler!!field}}\n\n{{!!field}}\n\n{{MyTiddler##index}}\n\n{{##index}}", }); it("should serialize block-level transclusions correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeBlockTest").tree).trimEnd(); @@ -367,12 +366,13 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "TranscludeInlineTest", - text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", + text: "{{MyTiddler}} {{MyTiddler||TemplateTitle}}", }); it("should serialize inline-level transclusions correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd()); }); + return; wiki.addTiddler({ title: "TypedBlockTest", From 0adf638c1a24d60868b5179270cfaddedf61f8ea Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 01:31:55 +0800 Subject: [PATCH 46/52] refactor: reuse block on inline when possible --- .../rules/filteredtranscludeblock.js | 3 +- .../rules/filteredtranscludeinline.js | 18 +++------- .../wikiparser/rules/macrocallinline.js | 20 +++-------- .../wikiparser/rules/transcludeinline.js | 34 ++----------------- 4 files changed, 12 insertions(+), 63 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 0e43ec74875..99459685522 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,8 +71,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree) { - // Filter expression +exports.serialize = function(tree, serialize) { var serialized = "{{{" + tree.attributes.filter.value; // Tooltip text if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index 726ceac9e72..8ab8887d734 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,20 +70,10 @@ 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; - serialized += "}" - // CSS classes - if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); - return serialized; +exports.serialize = function(tree, serialize) { + var filteredtranscludeblock = require("$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js"); + var result = filteredtranscludeblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index bc0ac7f2257..132eabef9f2 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -49,22 +49,10 @@ exports.parse = function() { /* Same as macrocallblock but without \n\n */ -exports.serialize = function (node) { - // Start with macro opener - var result = "<<"; - if(node.attributes && node.attributes["$variable"]) { - result += node.attributes["$variable"].value; // Add macro name - } - // Append ordered arguments if any - if(node.orderedAttributes) { - node.orderedAttributes.forEach(function (attr) { - if(attr.name !== "$variable") { - result += " " + '"' + attr.value + '"'; // Add each additional value - } - }); - } - result += ">>"; - return result; +exports.serialize = function (tree, serialize) { + var macrocallblock = require("$:/core/modules/parsers/wikiparser/rules/macrocallblock.js"); + var result = macrocallblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 346a9867166..af525b78a66 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -85,37 +85,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - var serialized = "{{"; - // Check for tiddler attribute - if(tree.attributes.$tiddler) { - serialized += tree.attributes.$tiddler.value; - // Check for field attribute - if(tree.attributes.$field) { - serialized += "##" + tree.attributes.$field.value; - } - // Check for index attribute - if(tree.attributes.$index) { - serialized += "!!" + tree.attributes.$index.value; - } - } - // Check for template attribute - if(tree.attributes.$template) { - serialized += "||" + tree.attributes.$template.value; - } - // Check for parameters - var params = []; - for(var key in tree.attributes) { - if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { - params.push(tree.attributes[key].value); - } - } - if(params.length > 0) { - serialized += "|" + params.join("|"); - } - // Close the serialized string - serialized += "}}"; - // Return the complete serialized string - return serialized; + var transcludeblock = require("$:/core/modules/parsers/wikiparser/rules/transcludeblock.js"); + var result = transcludeblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); From c4f6136fa7e7a829f07a1daedf74a7b79484a546 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 02:33:50 +0800 Subject: [PATCH 47/52] feat: use void node to carry important info for typedblock --- .../parsers/wikiparser/rules/typedblock.js | 44 ++++++++++++------- .../tiddlers/tests/test-wikitext-serialize.js | 17 ++++--- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index e428e85d8aa..68d534830c3 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -63,36 +63,46 @@ exports.parse = function() { var parser = this.parser.wiki.parseText(parseType,text,{defaultType: "text/plain"}); // If there's no render type, just return the parse tree if(!renderType) { - return parser.tree; + return [{ + type: "void", + children: $tw.utils.isArray(parser.tree) ? parser.tree : [parser.tree], + parseType: parseType, + renderType: renderType, + text: text, + start: start, + end: this.parser.pos + }]; } else { // Otherwise, render to the rendertype and return in a
             tag
             		var widgetNode = this.parser.wiki.makeWidget(parser),
             			container = $tw.fakeDocument.createElement("div");
             		widgetNode.render(container,null);
            -		text = renderType === "text/html" ? container.innerHTML : container.textContent;
            +		var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
             		return [{
            -			type: "element",
            -			tag: "pre",
            +			type: "void",
             			children: [{
            -				type: "text",
            -				text: text,
            -				start: start,
            -				end: this.parser.pos
            -			}]
            +				type: "element",
            +				tag: "pre",
            +				children: [{
            +					type: "text",
            +					text: renderResult,
            +				}]
            +			}],
            +			parseType: parseType,
            +			renderType: renderType,
            +			text: text,
            +			start: start,
            +			end: this.parser.pos
             		}];
             	}
             };
             
             exports.serialize = function (tree, serialize) {
            -	var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute)
            -	if(tree.attributes && tree.attributes.type) {
            -		serialized += tree.attributes.type.value;
            +	if(tree.type === "void") {
            +		// Directly process the tree's text content
            +		return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n";
             	}
            -	serialized += '\n'; // Serialize the children of the block
            -	serialized += serialize(tree.children); 	// Close the serialized string
            -	serialized += "\n$$$";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "";
             };
             
             })();
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index b2a35e8bca6..6e881ac1271 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -372,16 +372,23 @@ describe("WikiAST serialization unit tests", function () {
                 var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd();
                 expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd());
               });
            -  return;
             
               wiki.addTiddler({
            -    title: "TypedBlockTest",
            -    text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n  \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$',
            +    title: "TypedBlockTest1",
            +    text: "$$$text/vnd.tiddlywiki > text/plain\nThis is ''some'' wikitext\n$$$\n\n$$$text/unknown\nSome plain text, which will not be //formatted//.\n\n$$$text/vnd.tiddlywiki > text/html\nThis is ''some'' wikitext\n$$$\n\n",
            +  });
            +  wiki.addTiddler({
            +    title: "TypedBlockTest2",
            +    text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n\n  \n\n$$$\n\n$$$image/svg+xml\n\n  \n\n$$$',
               });
            +  
               it("should serialize typed blocks correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest").trimEnd());
            +    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest1").tree).trimEnd();
            +    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest1").trimEnd());
            +    serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest2").tree).trimEnd();
            +    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest2").trimEnd());
               });
            +  return;
             
               wiki.addTiddler({
                 title: "WikiLinkTest",
            
            From 08e9312295d4d818d71e6c706cbc0e5677b1ff8b Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Sat, 10 Aug 2024 02:35:07 +0800
            Subject: [PATCH 48/52] feat: run all tests
            
            ---
             core/modules/parsers/wikiparser/rules/wikilink.js       | 2 --
             core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 2 --
             editions/test/tiddlers/tests/test-wikitext-serialize.js | 1 -
             3 files changed, 5 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js
            index dc146a047e6..6a59d395f2a 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilink.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilink.js
            @@ -70,9 +70,7 @@ exports.serialize = function(tree, serialize) {
             	var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink;
             
             	var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : "";
            -	// Append the link text
             	serialized += tree.attributes.to.value;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            index 36aebf06376..1de26d25c34 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            @@ -39,9 +39,7 @@ exports.parse = function() {
             
             exports.serialize = function(tree, serialize) {
             	var serialized = $tw.config.textPrimitives.unWikiLink;
            -	// Append the text
             	serialized += tree.text;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 6e881ac1271..2871343cc32 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -388,7 +388,6 @@ describe("WikiAST serialization unit tests", function () {
                 serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest2").tree).trimEnd();
                 expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest2").trimEnd());
               });
            -  return;
             
               wiki.addTiddler({
                 title: "WikiLinkTest",
            
            From 398d7f7fe706b3b2680afa9907a7ab6623f6a3f5 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Sat, 10 Aug 2024 12:43:26 +0800
            Subject: [PATCH 49/52] lint: useless ai generated comments
            
            ---
             core/modules/parsers/wikiparser/rules/dash.js          |  3 +--
             core/modules/parsers/wikiparser/rules/emphasis/bold.js |  8 +-------
             .../parsers/wikiparser/rules/emphasis/italic.js        |  8 +-------
             .../parsers/wikiparser/rules/emphasis/strikethrough.js |  8 +-------
             .../parsers/wikiparser/rules/emphasis/subscript.js     |  8 +-------
             .../parsers/wikiparser/rules/emphasis/superscript.js   |  8 +-------
             .../parsers/wikiparser/rules/emphasis/underscore.js    |  8 +-------
             core/modules/parsers/wikiparser/rules/entity.js        |  1 -
             .../modules/parsers/wikiparser/rules/hardlinebreaks.js |  5 ++---
             core/modules/parsers/wikiparser/rules/html.js          | 10 +++++-----
             core/modules/parsers/wikiparser/rules/import.js        |  3 +--
             .../modules/parsers/wikiparser/rules/macrocallblock.js |  6 +++---
             core/modules/parsers/wikiparser/rules/macrodef.js      |  4 ----
             core/modules/parsers/wikiparser/rules/parameters.js    |  2 --
             core/modules/parsers/wikiparser/rules/prettyextlink.js |  3 ---
             core/modules/parsers/wikiparser/rules/prettylink.js    |  3 ---
             core/modules/parsers/wikiparser/rules/syslink.js       |  4 +---
             .../parsers/wikiparser/rules/transcludeblock.js        |  2 --
             core/modules/parsers/wikiparser/rules/typedblock.js    |  2 +-
             core/modules/parsers/wikiparser/rules/wikilink.js      |  1 -
             20 files changed, 20 insertions(+), 77 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js
            index 60c82f0a72a..4d06a54cd81 100644
            --- a/core/modules/parsers/wikiparser/rules/dash.js
            +++ b/core/modules/parsers/wikiparser/rules/dash.js
            @@ -38,8 +38,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree) {
            -	var dash = tree.entity === "–" ? "--" : "---";
            -	return dash;
            +	return tree.entity === "–" ? "--" : "---";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            index 6294094ec5f..bcd55f556a3 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "''";
            -	// Serialize the children of the bold element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "''";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "''" + serialize(tree.children) + "''";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            index f1070ddfb87..88be5617a7f 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "//";
            -	// Serialize the children of the italic element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "//";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "//" + serialize(tree.children) + "//";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            index ccd511c4209..d42ac62b320 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "~~";
            -	// Serialize the children of the strikethrough element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "~~";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "~~" + serialize(tree.children) + "~~";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            index d38d5122253..b4959893490 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = ",,";
            -	// Serialize the children of the subscript element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += ",,";
            -	// Return the complete serialized string
            -	return serialized;
            +	return ",," + serialize(tree.children) + ",,";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            index 82a4b78d624..a843aec5d04 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "^^";
            -	// Serialize the children of the superscript element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "^^";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "^^" + serialize(tree.children) + "^^";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            index b07f32fc243..4d223185a72 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "__";
            -	// Serialize the children of the underscore element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "__";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "__" + serialize(tree.children) + "__";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js
            index 7f15c8a95ca..10e288990bc 100644
            --- a/core/modules/parsers/wikiparser/rules/entity.js
            +++ b/core/modules/parsers/wikiparser/rules/entity.js
            @@ -37,7 +37,6 @@ 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/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            index 9f26c3d956e..ae290ef2946 100644
            --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            @@ -60,15 +60,14 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// we get each of element on tree from `parse` one by one here.
            -	var text = tree.tag === 'br' ? '\n' : tree.text;
            +	var text = tree.tag === "br" ? "\n" : (tree.text || "");
             	if(tree.isRuleStart) {
             		return '"""\n' + text;
             	}
             	if(tree.isRuleEnd) {
             		return text + '"""';
             	}
            -	return text;
            +	return text + serialize(tree.children);
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js
            index 1e3f9865bd1..df52819e233 100644
            --- a/core/modules/parsers/wikiparser/rules/html.js
            +++ b/core/modules/parsers/wikiparser/rules/html.js
            @@ -66,7 +66,7 @@ exports.parse = function() {
             		}
             		tag.end = this.parser.pos;
             		tag.closeTagEnd = tag.end;
            -		if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') {
            +		if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== ">") {
             			tag.closeTagStart = tag.end;
             		} else {
             			tag.closeTagStart = tag.closeTagEnd - 2;
            @@ -74,11 +74,11 @@ exports.parse = function() {
             			if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
             			while(tag.closeTagStart >= closeTagMinPos) {
             				var char = this.parser.source[tag.closeTagStart];
            -				if(char === '>') {
            +				if(char === ">") {
             					tag.closeTagStart = -1;
             					break;
             				}
            -				if(char === '<') break;
            +				if(char === "<") break;
             				tag.closeTagStart -= 1;
             			}
             			if(tag.closeTagStart < closeTagMinPos) {
            @@ -199,9 +199,9 @@ 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('');
            +	}).join("");
             	// Children
            -	var children = tree.children ? serialize(tree.children) : '';
            +	var children = tree.children ? serialize(tree.children) : "";
             	// Self-closing tag
             	if(tree.isSelfClosing) {
             			return "<" + tag + (attributes ? " " + attributes : "") + " />";
            diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js
            index 2142f7a583f..3cfcad5d735 100644
            --- a/core/modules/parsers/wikiparser/rules/import.js
            +++ b/core/modules/parsers/wikiparser/rules/import.js
            @@ -52,9 +52,8 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// Filter attribute
             	var filter = tree.attributes.filter.value;
            -	// Construct the serialized string with children that is actually the sibling below the pragma.
            +	// Sibling below the pragma become children, so we append the serialized children to the end..
             	return "\\import " + filter + "\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js
            index 923484baec2..1572cce6309 100644
            --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js
            +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js
            @@ -57,16 +57,16 @@ exports.parse = function() {
             Serialize a macro call node to wikitext
             */
             exports.serialize = function (node) {
            -	// Start with macro opener
             	var result = "<<";
            +	// Macro name
             	if(node.attributes && node.attributes["$variable"]) {
            -		result += node.attributes["$variable"].value; // Add macro name
            +		result += node.attributes["$variable"].value;
             	}
             	// Append ordered arguments if any
             	if(node.orderedAttributes) {
             		node.orderedAttributes.forEach(function (attr) {
             			if(attr.name !== "$variable") {
            -				result += " " + '"' + attr.value + '"'; // Add each additional value
            +				result += " " + '"' + attr.value + '"';
             			}
             		});
             	}
            diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js
            index 9dec0768250..be000eab09e 100644
            --- a/core/modules/parsers/wikiparser/rules/macrodef.js
            +++ b/core/modules/parsers/wikiparser/rules/macrodef.js
            @@ -90,15 +90,11 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// 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\n\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js
            index 6be51c24b48..a214164ca9b 100644
            --- a/core/modules/parsers/wikiparser/rules/parameters.js
            +++ b/core/modules/parsers/wikiparser/rules/parameters.js
            @@ -58,11 +58,9 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// Parameters
             	var params = tree.orderedAttributes.map(function(param) {
             			return param.name + (param.value ? ":" + param.value : "");
             	}).join(",");
            -	// Construct the serialized string
             	return "\\parameters(" + params + ")\n\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js
            index e2cc48a7ea7..f56ee8fe078 100644
            --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js
            +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js
            @@ -118,11 +118,8 @@ exports.parseLink = function(source,pos) {
             };
             
             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 74a275e42d9..0b798a5dc3a 100644
            --- a/core/modules/parsers/wikiparser/rules/prettylink.js
            +++ b/core/modules/parsers/wikiparser/rules/prettylink.js
            @@ -68,11 +68,8 @@ 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/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js
            index 0839e9087d7..e5387e5ee94 100644
            --- a/core/modules/parsers/wikiparser/rules/syslink.js
            +++ b/core/modules/parsers/wikiparser/rules/syslink.js
            @@ -53,11 +53,9 @@ exports.parse = function() {
             exports.serialize = function(tree, serialize) {
             	// Check if the link is suppressed
             	var isSuppressed = tree.children[0].text.substr(0,1) === "~";
            -
             	var serialized = isSuppressed ? "~" : "";
            -	// Append the link value
            +	// Append the link text
             	serialized += tree.attributes.to.value;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js
            index 88519e84dc2..319726f0a1c 100644
            --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js
            +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js
            @@ -130,9 +130,7 @@ exports.serialize = function(tree, serialize) {
             	} else if(tree.type === "transclude") {
             		handleTransclude(tree);
             	}
            -	// Close the result string
             	result += "}}\n\n";
            -	// Return the complete result string
             	return result;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js
            index 68d534830c3..38985daaa5f 100644
            --- a/core/modules/parsers/wikiparser/rules/typedblock.js
            +++ b/core/modules/parsers/wikiparser/rules/typedblock.js
            @@ -78,6 +78,7 @@ exports.parse = function() {
             			container = $tw.fakeDocument.createElement("div");
             		widgetNode.render(container,null);
             		var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
            +		// Use void node to carry important info for typedblock
             		return [{
             			type: "void",
             			children: [{
            @@ -99,7 +100,6 @@ exports.parse = function() {
             
             exports.serialize = function (tree, serialize) {
             	if(tree.type === "void") {
            -		// Directly process the tree's text content
             		return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n";
             	}
             	return "";
            diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js
            index 6a59d395f2a..d5e1a48ec04 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilink.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilink.js
            @@ -66,7 +66,6 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	// Check if the link is suppressed
             	var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink;
             
             	var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : "";
            
            From f5fca2a4d484cc5c4e3b12a287b24d70985a03a0 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 4 Sep 2024 16:43:05 +0800
            Subject: [PATCH 50/52] Update conditional.js to not include space
            
            ---
             core/modules/parsers/wikiparser/rules/conditional.js | 10 +++++-----
             1 file changed, 5 insertions(+), 5 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js
            index 3a4486cf2ab..8e11c7cdb7f 100644
            --- a/core/modules/parsers/wikiparser/rules/conditional.js
            +++ b/core/modules/parsers/wikiparser/rules/conditional.js
            @@ -6,7 +6,7 @@ module-type: wikirule
             Conditional shortcut syntax
             
             ```
            -This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>
            +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>
             ```
             
             \*/
            @@ -27,7 +27,7 @@ exports.init = function(parser) {
             };
             
             exports.findNextMatch = function(startPos) {
            -	// Look for the next <% if shortcut
            +	// Look for the next <%if shortcut
             	this.matchRegExp.lastIndex = startPos;
             	this.match = this.matchRegExp.exec(this.parser.source);
             	// If not found then return no match
            @@ -121,7 +121,7 @@ exports.serialize = function(tree, serialize) {
             	var filterCondition = tree.attributes.filter.value;
             	var ifClause = serialize(tree.children[0].children);
             	var elseClause = tree.children[1].children;
            -	var serialized = "<% if " + filterCondition + "%>" + ifClause;
            +	var serialized = "<%if " + filterCondition + "%>" + ifClause;
             
             	if(elseClause && elseClause.length > 0) {
             		for(var i = 0; i < elseClause.length; i++) {
            @@ -129,11 +129,11 @@ exports.serialize = function(tree, serialize) {
             				// Handle elseif clause
             				var elseifCondition = elseClause[i].attributes.filter.value;
             				var elseifClause = serialize(elseClause[i].children[0]);
            -				serialized += "<% elseif " + elseifCondition + "%>" + elseifClause;
            +				serialized += "<%elseif " + elseifCondition + "%>" + elseifClause;
             			}
             			if(elseClause[i].children[1]) {
             				var elseClauseText = serialize(elseClause[i].children[1]);
            -				serialized += "<% else %>" + elseClauseText;
            +				serialized += "<%else%>" + elseClauseText;
             			}
             		}
             	}
            
            From 043f60b299e7f2cc4661d2f79440da50e0eeeb28 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 4 Sep 2024 16:44:03 +0800
            Subject: [PATCH 51/52] Update test-wikitext-serialize.js
            
            ---
             editions/test/tiddlers/tests/test-wikitext-serialize.js | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 2871343cc32..a8431694a35 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -116,7 +116,7 @@ describe("WikiAST serialization unit tests", function () {
             
               wiki.addTiddler({
                 title: "ConditionalTest",
            -    text: "This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>",
            +    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();
            
            From 03798d7fef6a47e7bada5582df1b9ec3d80f5aff Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Wed, 4 Sep 2024 16:46:32 +0800
            Subject: [PATCH 52/52] Update conditional.js
            
            ---
             core/modules/parsers/wikiparser/rules/conditional.js | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js
            index 8e11c7cdb7f..84ac3cef8c4 100644
            --- a/core/modules/parsers/wikiparser/rules/conditional.js
            +++ b/core/modules/parsers/wikiparser/rules/conditional.js
            @@ -138,7 +138,7 @@ exports.serialize = function(tree, serialize) {
             		}
             	}
             
            -	serialized += "<% endif %>";
            +	serialized += "<%endif%>";
             	return serialized;
             };