From 37338b13e4392cc053e3670a2dbb5f09bc2db901 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:23:31 +0800 Subject: [PATCH 01/76] 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 2850dec5f..e53b0d387 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/76] 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 a74b8f3f8..7e7542d34 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/76] 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 6c3480566..71efe2dfd 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 bacad06ed..2e69e1986 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/76] 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 7e7542d34..a74b8f3f8 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/76] 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 a74b8f3f8..d553ec4f0 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/76] 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 71efe2dfd..11681261b 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 2e69e1986..697bd65a5 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 d553ec4f0..ae548de0e 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/76] 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 0baf1bdcf..516751a1a 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/76] 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 048fc051c..015c325c5 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/76] 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 000000000..d8747ef48 --- /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/76] 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 8dbf6568e..488377b44 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/76] 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 854171d19..09866b064 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/76] 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 09866b064..10acf91ec 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 ae548de0e..f5b2c12d0 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/76] 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 015c325c5..a78b56e6b 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 697bd65a5..e9279a4d7 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 d8747ef48..03e330b43 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/76] 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 11681261b..99e25af55 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 a78b56e6b..4d32089ab 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 e9279a4d7..4fd66de41 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 f5b2c12d0..e825cd747 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/76] 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 | 279 ++++++++++++++++-- 23 files changed, 512 insertions(+), 33 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1c303f38f..62bbd4088 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -46,11 +46,24 @@ exports.findNextMatch = function(startPos) { return undefined; }; + exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the comment that is not rendered + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentblock", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 671bd79d6..50e861fe4 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -43,8 +43,20 @@ exports.findNextMatch = function(startPos) { exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the inline comment + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentinline", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 23940fd88..ead7fc0af 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -117,4 +117,16 @@ exports.parseIfClause = function(filterCondition) { return [listWidget]; }; +exports.serialize = function(tree, serialize) { + var filterCondition = tree.attributes.filter.value; + var ifClause = serialize(tree.children[0].children); + var elseClause = serialize(tree.children[1].children); + var serialized = '<% if ' + filterCondition + ' %>' + ifClause; + if(elseClause) { + serialized += '<% else %>' + elseClause; + } + serialized += '<% endif %>'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js index 45481bf07..60c82f0a7 100644 --- a/core/modules/parsers/wikiparser/rules/dash.js +++ b/core/modules/parsers/wikiparser/rules/dash.js @@ -37,4 +37,9 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + var dash = tree.entity === "–" ? "--" : "---"; + return dash; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js index dc3917daf..7f15c8a95 100644 --- a/core/modules/parsers/wikiparser/rules/entity.js +++ b/core/modules/parsers/wikiparser/rules/entity.js @@ -37,4 +37,9 @@ exports.parse = function() { return [{type: "entity", entity: this.match[0]}]; }; +// Serialize method for the entity rule +exports.serialize = function(tree, serialize) { + return tree.entity; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/extlink.js b/core/modules/parsers/wikiparser/rules/extlink.js index 5b9f57adf..58b7e772e 100644 --- a/core/modules/parsers/wikiparser/rules/extlink.js +++ b/core/modules/parsers/wikiparser/rules/extlink.js @@ -53,4 +53,13 @@ exports.parse = function() { } }; +// Serialize method for the extlink rule +exports.serialize = function(tree, serialize) { + if(tree.type === "text") { + return tree.text; + } else if(tree.type === "element" && tree.tag === "a") { + return tree.attributes.href.value; + } +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 73bdff813..c66009f85 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,4 +71,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index c0b19a941..cb992dbed 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,4 +70,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index 85bd14d5c..a4259e574 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -93,5 +93,20 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree, serialize) { + // Type of definition: "function", "procedure", or "widget" + var type = tree.isFunctionDefinition ? "function" : (tree.isProcedureDefinition ? "procedure" : "widget"); + // Name of the function, procedure, or widget + var name = tree.attributes.name.value; + // Parameters with default values + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js index 94f517cd4..39ef6fc5c 100644 --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js @@ -57,4 +57,19 @@ exports.parse = function() { return tree; }; +exports.serialize = function(tree,serialize) { + // Serialized text with hard line breaks + var serialized = '"""\n'; + // Serialize each node in the tree + tree.forEach(function(node) { + if(node.type === "element" && node.tag === "br") { + serialized += "\n"; + } else { + serialized += serialize([node]).join(''); + } + }); + serialized += '\n"""'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 7a0ecb9db..79df971e5 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -45,4 +45,16 @@ exports.parse = function() { children: tree }]; }; + +exports.serialize = function(tree, serialize) { + // Heading level + var headingLevel = tree.tag.length - 1; + // Classes + var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; + // Serialized heading text + var headingText = serialize(tree.children).join(''); + // Construct the serialized string + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 61c4ad9e1..911099b37 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -195,4 +195,19 @@ exports.isLegalTag = function(tag) { } }; +exports.serialize = function(tree, serialize) { + var tag = tree.tag; + var attributes = Object.keys(tree.attributes).map(function(key) { + return key + '="' + tree.attributes[key].value + '"'; + }).join(" "); + // Children + var children = tree.children ? serialize(tree.children).join('') : ''; + // Self-closing tag + if(tree.isSelfClosing) { + return "<" + tag + (attributes ? " " + attributes : "") + " />"; + } + // Opening and closing tags + return "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 6f58225e0..8591e544e 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -130,4 +130,17 @@ exports.parseImage = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Width attribute + var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; + // Height attribute + var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; + // Tooltip attribute + var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; + // Source attribute + var source = tree.attributes.source.value; + // Construct the serialized string + return "[img" + width + height + " [" + tooltip + source + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index bb1832255..7025d20f2 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -51,4 +51,11 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Filter attribute + var filter = tree.attributes.filter.value; + // Construct the serialized string + return "\\import " + filter; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index d89c201b9..8dc8411aa 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -153,4 +153,28 @@ exports.parse = function() { return [listStack[0]]; }; +exports.serialize = function(tree, serialize) { + // Serialize the list recursively + return serializeList(tree, serialize, 0); +}; + +// utility to handle recursion of list +function serializeList(node, serialize, depth) { + // List tag + var listTag = node.tag; + // List item tag + var itemTag = listTypes[listTag[0]].itemTag; + // Serialized list items + var items = node.children.map(function(child) { + // Classes + var classes = child.attributes && child.attributes.class ? child.attributes.class.value.split(" ").join(".") : ""; + // Serialized children + var children = serialize(child.children).join(''); + // Construct the serialized list item + return Array(depth + 1).join(listTag[0]) + (classes ? "." + classes : "") + " " + children; + }).join("\n"); + // Return the serialized list + return items; +} + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index a2c10e04a..c3b0e92e9 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -53,4 +53,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index e9f79f09e..a62596414 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -46,4 +46,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 2001f70d5..31a93f27b 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -89,4 +89,17 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.attributes.name.value; + // Parameters + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index 60bbd8901..692f03ea7 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -57,4 +57,13 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Parameters + var params = tree.orderedAttributes.map(function(param) { + return param.name + (param.value ? ":" + param.value : ""); + }).join(","); + // Construct the serialized string + return "\\parameters(" + params + ")"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 72a6de067..4814a4ba1 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -65,4 +65,11 @@ exports.parse = function() { return []; }; +exports.serialize = function(tree) { + // Parser mode + var mode = tree.parser.parseAsInline ? "inline" : "block"; + // Construct the serialized string + return "\\parsermode " + mode; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js index 4707fa0d0..e2cc48a7e 100644 --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js @@ -117,4 +117,13 @@ exports.parseLink = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Tooltip text + var tooltip = tree.children[0].text; + // URL + var url = tree.attributes.href.value; + // Construct the serialized string + return "[ext[" + (tooltip !== url ? tooltip + "|" : "") + url + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js index 66c19dc88..74a275e42 100644 --- a/core/modules/parsers/wikiparser/rules/prettylink.js +++ b/core/modules/parsers/wikiparser/rules/prettylink.js @@ -35,7 +35,7 @@ exports.parse = function() { var text = this.match[1], link = this.match[2] || text, textEndPos = this.parser.source.indexOf("|", start); - if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { + if(textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { textEndPos = this.matchRegExp.lastIndex - 2; } var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start; @@ -67,4 +67,13 @@ exports.parse = function() { } }; +exports.serialize = function(tree) { + // Link text + var text = tree.children[0].text; + // Link target + var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value; + // Construct the serialized string + return "[[" + text + (text !== target ? "|" + target : "") + "]]"; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 03e330b43..b21627564 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -6,36 +6,259 @@ tags: [[$:/tags/test-spec]] Tests the wikitext inverse-rendering from Wiki AST. \*/ -(function(){ -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; +describe('WikiAST serialization tests', function () { + var wiki = new $tw.Wiki(); -describe("WikiAST serialization tests", function() { + wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); + it('should render tiddlers with no special markup as-is', function () { + // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerOne') + ); + }); - // Create a wiki - var wiki = new $tw.Wiki(); - // Add a couple of tiddlers - wiki.addTiddler({title: "TiddlerOne", text: "The quick brown fox"}); - wiki.addTiddler({title: "TiddlerTwo", text: "The rain in Spain\nfalls mainly on the plain"}); - wiki.addTiddler({title: "TiddlerThree", text: "The speed of sound\n\nThe light of speed"}); - wiki.addTiddler({title: "TiddlerFour", text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend"}); + wiki.addTiddler({ title: 'TiddlerTwo', text: 'The rain in Spain\nfalls mainly on the plain' }); + it('should preserve single new lines', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerTwo') + ); + }); - it("should render tiddlers with no special markup as-is", function() { - // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerOne')); - }); - it("should preserve single new lines", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerTwo')); - }); - it("should preserve double new lines to create paragraphs", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerThree')); - }); - - it("should render inline code and block code", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerFour')); - }); + wiki.addTiddler({ title: 'TiddlerThree', text: 'The speed of sound\n\nThe light of speed' }); + it('should preserve double new lines to create paragraphs', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerThree') + ); + }); + + wiki.addTiddler({ + title: 'TiddlerFour', + text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', + }); + it('should render inline code and block code', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerFour') + ); + }); + + // Test case for commentblock rule + wiki.addTiddler({ + title: 'CommentBlockTest', + text: '\n\nSome text\n\n\n\nMore text', + }); + it('should serialize block comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentBlockTest').trimEnd()); + }); + + // Test case for commentinline rule + wiki.addTiddler({ + title: 'CommentInlineTest', + text: 'This is some text with an inline comment and some more text.', + }); + it('should serialize inline comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentInlineTest').trimEnd()); + }); + + // Test case for conditional rule + wiki.addTiddler({ + title: 'ConditionalTest', + text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', + }); + it('should serialize conditional statements correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ConditionalTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ConditionalTest').trimEnd()); + }); + + // Test case for dash rule + wiki.addTiddler({ + title: 'DashTest', + text: 'This is an en-dash: --\n\nThis is an em-dash: ---', + }); + it('should serialize dashes correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('DashTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); + }); + + // Test case for entity rule + wiki.addTiddler({ + title: 'EntityTest', + text: 'This is a copyright symbol: ©', + }); + it('should serialize HTML entities correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('EntityTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('EntityTest').trimEnd()); + }); + + // Test case for extlink rule + wiki.addTiddler({ + title: 'ExtLinkTest', + text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', + }); + it('should serialize external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ExtLinkTest').trimEnd()); + }); + + // Test case for filteredtranscludeblock rule + wiki.addTiddler({ + title: 'FilteredTranscludeBlockTest', + text: '{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize block-level filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeBlockTest').trimEnd()); + }); + + // Test case for filteredtranscludeinline rule + wiki.addTiddler({ + title: 'FilteredTranscludeInlineTest', + text: '{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize inline filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeInlineTest').trimEnd()); + }); + + // Test case based on the rule code's comment + wiki.addTiddler({ + title: 'FunctionDefinition', + text: '\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end', + }); + it('should serialize function, procedure, and widget definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); + }); + + // Test case for hardlinebreaks rule + wiki.addTiddler({ + title: 'HardLineBreaksTest', + text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n', + }); + it('should serialize hard line breaks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HardLineBreaksTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HardLineBreaksTest').trimEnd()); + }); + + // Test case for heading rule + wiki.addTiddler({ + title: 'HeadingTest', + text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', + }); + it('should serialize headings correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HeadingTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HeadingTest').trimEnd()); + }); + + // Test case for html rule + wiki.addTiddler({ + title: 'HtmlTest', + text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n', + }); + it('should serialize HTML elements and widgets correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HtmlTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HtmlTest').trimEnd()); + }); + + // Test case for image rule + wiki.addTiddler({ + title: 'ImageTest', + text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', + }); + it('should serialize image tags correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); + }); + + // Test case for import rule + wiki.addTiddler({ + title: 'ImportTest', + text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', + }); + it('should serialize import pragma correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); + }); + + // Test case for list rule + wiki.addTiddler({ + title: 'ListTest', + text: '* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three', + }); + it('should serialize lists correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); + }); + + // Test case for macrocallblock rule + wiki.addTiddler({ + title: 'MacroCallBlockTest', + text: '<>', + }); + it('should serialize block macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); + }); + + // Test case for macrocallinline rule + wiki.addTiddler({ + title: 'MacroCallInlineTest', + text: 'This is a macro call: <>', + }); + it('should serialize inline macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallInlineTest').trimEnd()); + }); + + // Test case for macrodef rule + wiki.addTiddler({ + title: 'MacroDefTest', + text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', + }); + it('should serialize macro definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroDefTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); + }); + + // Test case for parameters rule + wiki.addTiddler({ + title: 'ParametersTest', + text: '\\parameters(param:defaultvalue,param2:defaultvalue)', + }); + it('should serialize parameter definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParametersTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); + }); + + // Test case for parsermode rule + wiki.addTiddler({ + title: 'ParserModeTest', + text: '\\parsermode block\n\\parsermode inline', + }); + it('should serialize parser mode specifications correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParserModeTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); + }); + + // Test case for prettyextlink rule + wiki.addTiddler({ + title: 'PrettyExtLinkTest', + text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', + }); + it('should serialize pretty external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); + }); + + // Test case for prettylink rule + wiki.addTiddler({ + title: 'PrettyLinkTest', + text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', + }); + it('should serialize pretty links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); + }); }); - -})(); From bfd116a438a61f790928e77a4cbb8a079c75ccfa Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 2 Aug 2024 22:54:45 +0800 Subject: [PATCH 16/76] 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 3799feeb5..946fff7cf 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 3e0744c4d..798429ed2 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 0fb34fc52..572217052 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 12be0fbbc..f4d9ecc5d 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 5a5330d8c..e33e75ac4 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 d36bd242d..640b36e02 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 911099b37..305f037de 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 fdd6c860b..3f946cf13 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 3ce9dc78e..78839f925 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 07c88be15..daaefb7b7 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 6b195f9ff..5762aeee4 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 60cb3d992..be902edc8 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 b21627564..1ab851226 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/76] 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 62bbd4088..0fc3c0422 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/76] 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 a4259e574..82c4b6217 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 39ef6fc5c..9f26c3d95 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 79df971e5..67470c9c5 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 656759ed8..1e3f9865b 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 8591e544e..33454f46e 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 d3ab4dc04..69800a81f 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/76] 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 2a2e36309..b11300bfe 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 d2266ca5e..4d07bc4f9 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 488377b44..73d5b55d5 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/76] 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 33454f46e..f046c59f1 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 69800a81f..8e73c8ef9 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/76] 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 7025d20f2..2142f7a58 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 fbda16711..704ad60ae 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'); + } + + // Begin serialization from the root node, with an empty string as the initial marker prefix + return serializeList(tree, '') + '\n\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; -} - })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 8e73c8ef9..e19a2d922 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/76] 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 88d243d0e..3a4486cf2 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 704ad60ae..71a7cab5e 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 c3b0e92e9..923484bae 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 a62596414..bc0ac7f22 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 31a93f27b..735c7958a 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 692f03ea7..ddb3a65ab 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 e19a2d922..032417549 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 73d5b55d5..488377b44 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/76] 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 4814a4ba1..c5ec0fdd1 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/76] 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 0fc3c0422..56a0857dd 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 50e861fe4..5ddcd8c82 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 735c7958a..9dec07682 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 ddb3a65ab..6be51c24b 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 c5ec0fdd1..713bb36ed 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 76ff385f0..670d6307b 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/76] 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 56a0857dd..1e9b2c622 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 5ddcd8c82..01f76c1c6 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 713bb36ed..9aea958d2 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 eb84fab4a..73c299d69 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 488377b44..8dbf6568e 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/76] 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 000000000..e7b982a35 --- /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 73c299d69..6f2842d19 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/76] 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 1e9b2c622..a1510b8bc 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 01f76c1c6..183eea447 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 9aea958d2..ba165a283 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/76] 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 916e2abfb..6db3f8be2 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 04d041ec9..0cb1a9f55 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/76] 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 032417549..6b7ea72e0 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/76] 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 6f2842d19..eb84fab4a 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/76] 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 a1510b8bc..7d9a68f14 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/76] 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 a0cb99c95..8a38ccc53 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/76] 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 cc8e803c0..d2b6445a7 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/76] 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 8a38ccc53..9c3ae78ce 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/76] 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 3e1ac3fc6..1ccd04003 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/76] 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 4d07bc4f9..36eeea321 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/76] feat: add to styleblock --- .../parsers/wikiparser/rules/quoteblock.js | 25 ++++--- .../modules/parsers/wikiparser/rules/rules.js | 36 ++++++---- .../parsers/wikiparser/rules/styleblock.js | 69 ++++++++++++++----- .../tiddlers/tests/test-wikitext-serialize.js | 10 ++- 4 files changed, 97 insertions(+), 43 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index 3f946cf13..329d881b0 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 6ea89b5df..e054b0916 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; - } - // 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]; + // 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); + } + } } } - // Append the serialized children and the closing delimiter - serialized += "\n" + serialize(tree) + "\n@@"; - // Return the complete serialized string - return serialized; + + // 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"); + } + } + + // 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 6b7ea72e0..7978b354f 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/76] 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 e054b0916..089c5f395 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 7978b354f..7ee728cf6 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/76] 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 281c2bc8d..873226f03 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 7ee728cf6..bfc4523ad 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/76] 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 ed4c7c889..9b730922d 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/76] 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 946fff7cf..6294094ec 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 798429ed2..f1070ddfb 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 572217052..ccd511c42 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 f4d9ecc5d..d38d51222 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 e33e75ac4..82a4b78d6 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 640b36e02..b07f32fc2 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 329d881b0..be7052795 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 28af31abc..a5958d67c 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 089c5f395..a5e19cfcc 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 873226f03..01c047856 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 8eed845ae..0839e9087 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 a4b1b8a55..9add8f6ad 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 78839f925..346a98671 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 daaefb7b7..e428e85d8 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 5762aeee4..dc146a047 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 be902edc8..36aebf063 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/76] 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 9add8f6ad..88519e84d 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 bfc4523ad..b2a35e8bc 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/76] 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 0e43ec748..994596855 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 726ceac9e..8ab8887d7 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 bc0ac7f22..132eabef9 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 346a98671..af525b78a 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/76] 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 e428e85d8..68d534830 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 b2a35e8bc..6e881ac12 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/76] 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 dc146a047..6a59d395f 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 36aebf063..1de26d25c 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 6e881ac12..2871343cc 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/76] 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 60c82f0a7..4d06a54cd 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 6294094ec..bcd55f556 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 f1070ddfb..88be5617a 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 ccd511c42..d42ac62b3 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 d38d51222..b49598934 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 82a4b78d6..a843aec5d 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 b07f32fc2..4d223185a 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 7f15c8a95..10e288990 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 9f26c3d95..ae290ef29 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 1e3f9865b..df52819e2 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 2142f7a58..3cfcad5d7 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 923484bae..1572cce63 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 9dec07682..be000eab0 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 6be51c24b..a214164ca 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 e2cc48a7e..f56ee8fe0 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 74a275e42..0b798a5dc 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 0839e9087..e5387e5ee 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 88519e84d..319726f0a 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 68d534830..38985daaa 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 6a59d395f..d5e1a48ec 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/76] 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 3a4486cf2..8e11c7cdb 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/76] 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 2871343cc..a8431694a 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/76] 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 8e11c7cdb..84ac3cef8 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;
             };
             
            
            From 58507c06b4dad7d4e594fe07ea48f9f3e4311125 Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Mon, 30 Sep 2024 18:11:22 +0800
            Subject: [PATCH 53/76] refactor: move tiddlers to /data
            
            ---
             .../tests/data/serialize/BlockRule.tid        |   7 +
             .../tests/data/serialize/BoldEmphasis.tid     |   5 +
             .../tests/data/serialize/CodeBlock.tid        |  12 +
             .../tests/data/serialize/CommentBlock.tid     |  11 +
             .../tests/data/serialize/CommentInline.tid    |   5 +
             .../tests/data/serialize/Conditional.tid      |   5 +
             .../tiddlers/tests/data/serialize/Dash.tid    |   7 +
             .../tiddlers/tests/data/serialize/Entity.tid  |   5 +
             .../tiddlers/tests/data/serialize/ExtLink.tid |   7 +
             .../serialize/FilteredTranscludeBlock.tid     |   9 +
             .../serialize/FilteredTranscludeInline.tid    |   5 +
             .../data/serialize/FunctionDefinition.tid     |  15 +
             .../tests/data/serialize/HardLineBreaks.tid   |  12 +
             .../tiddlers/tests/data/serialize/Heading.tid |  10 +
             .../tiddlers/tests/data/serialize/Html.tid    |  11 +
             .../tiddlers/tests/data/serialize/Image.tid   |  10 +
             .../tiddlers/tests/data/serialize/Import.tid  |   6 +
             .../tests/data/serialize/ItalicEmphasis.tid   |   5 +
             .../tiddlers/tests/data/serialize/List.tid    |  27 ++
             .../tests/data/serialize/MacroCallBlock.tid   |   7 +
             .../tests/data/serialize/MacroCallInline.tid  |   5 +
             .../tests/data/serialize/MacroDef.tid         |   7 +
             .../tests/data/serialize/Parameters.tid       |   5 +
             .../tests/data/serialize/ParserMode.tid       |   9 +
             .../tests/data/serialize/PrettyExtLink.tid    |   6 +
             .../tests/data/serialize/PrettyLink.tid       |   6 +
             .../tests/data/serialize/QuoteBlock.tid       |   7 +
             .../tests/data/serialize/RulesPragma.tid      |   6 +
             .../tests/data/serialize/SimpleText.tid       |   5 +
             .../tests/data/serialize/SoftLineBreak.tid    |   6 +
             .../data/serialize/StrikethroughEmphasis.tid  |   5 +
             .../tests/data/serialize/StyleBlock.tid       |  17 +
             .../tests/data/serialize/StyleBlock2.tid      |  13 +
             .../tests/data/serialize/StyleInline.tid      |   7 +
             .../data/serialize/SubscriptEmphasis.tid      |   5 +
             .../data/serialize/SuperscriptEmphasis.tid    |   5 +
             .../tiddlers/tests/data/serialize/SysLink.tid |   6 +
             .../tiddlers/tests/data/serialize/Table.tid   |   8 +
             .../tests/data/serialize/TranscludeBlock.tid  |  21 +
             .../tests/data/serialize/TranscludeInline.tid |   5 +
             .../tests/data/serialize/TypedBlock1.tid      |  15 +
             .../tests/data/serialize/TypedBlock2.tid      |  19 +
             .../data/serialize/UnderscoreEmphasis.tid     |   5 +
             .../tests/data/serialize/WikiLink.tid         |   7 +
             .../tests/data/serialize/WikiLinkPrefix.tid   |   5 +
             .../tiddlers/tests/test-wikitext-serialize.js | 405 +-----------------
             46 files changed, 396 insertions(+), 395 deletions(-)
             create mode 100644 editions/test/tiddlers/tests/data/serialize/BlockRule.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CommentInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Conditional.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Dash.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Entity.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ExtLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Heading.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Html.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Image.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Import.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/List.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroDef.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Parameters.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ParserMode.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/RulesPragma.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SimpleText.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SoftLineBreak.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StrikethroughEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SysLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Table.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/WikiLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            
            diff --git a/editions/test/tiddlers/tests/data/serialize/BlockRule.tid b/editions/test/tiddlers/tests/data/serialize/BlockRule.tid
            new file mode 100644
            index 000000000..316f745c6
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/BlockRule.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/BlockRule
            +type: text/vnd.tiddlywiki
            +
            +The speed of sound
            +
            +The light of speed
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
            new file mode 100644
            index 000000000..2caac9172
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/BoldEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ''bold'' text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
            new file mode 100644
            index 000000000..8b1499970
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
            @@ -0,0 +1,12 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CodeBlock
            +type: text/vnd.tiddlywiki
            +
            +Simple `JS` and complex
            +
            +---
            +
            +```js
            +var match = reEnd.exec(this.parser.source)
            +```
            +end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid b/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
            new file mode 100644
            index 000000000..c90b67c25
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
            @@ -0,0 +1,11 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CommentBlock
            +type: text/vnd.tiddlywiki
            +
            +
            +
            +Some text
            +
            +
            +
            +More text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CommentInline.tid b/editions/test/tiddlers/tests/data/serialize/CommentInline.tid
            new file mode 100644
            index 000000000..2d0e98513
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CommentInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CommentInline
            +type: text/vnd.tiddlywiki
            +
            +This is some text with an inline comment  and some more text.
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Conditional.tid b/editions/test/tiddlers/tests/data/serialize/Conditional.tid
            new file mode 100644
            index 000000000..4e96726f7
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Conditional.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Conditional
            +type: text/vnd.tiddlywiki
            +
            +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Dash.tid b/editions/test/tiddlers/tests/data/serialize/Dash.tid
            new file mode 100644
            index 000000000..b0a7ddc55
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Dash.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Dash
            +type: text/vnd.tiddlywiki
            +
            +This is an en-dash: --
            +
            +This is an em-dash: ---
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Entity.tid b/editions/test/tiddlers/tests/data/serialize/Entity.tid
            new file mode 100644
            index 000000000..d8891e4ed
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Entity.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Entity
            +type: text/vnd.tiddlywiki
            +
            +This is a copyright symbol: ©
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ExtLink.tid b/editions/test/tiddlers/tests/data/serialize/ExtLink.tid
            new file mode 100644
            index 000000000..de966452f
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ExtLink.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ExtLink
            +type: text/vnd.tiddlywiki
            +
            +An external link: https://www.tiddlywiki.com/
            +
            +A suppressed external link: ~http://www.tiddlyspace.com/
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
            new file mode 100644
            index 000000000..cbfc442c5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
            @@ -0,0 +1,9 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FilteredTranscludeBlock
            +type: text/vnd.tiddlywiki
            +
            +{{{ [tag[docs]] }}}
            +{{{ [tag[docs]] |tooltip}}}
            +{{{ [tag[docs]] ||TemplateTitle}}}
            +{{{ [tag[docs]] |tooltip||TemplateTitle}}}
            +{{{ [tag[docs]] }}width:40;height:50;}.class.class
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
            new file mode 100644
            index 000000000..8b3155882
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FilteredTranscludeInline
            +type: text/vnd.tiddlywiki
            +
            +{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
            new file mode 100644
            index 000000000..ebd4119a5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
            @@ -0,0 +1,15 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FunctionDefinition
            +type: text/vnd.tiddlywiki
            +
            +\function name(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            +
            +\procedure name(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            +
            +\widget $mywidget(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid b/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
            new file mode 100644
            index 000000000..b6ea0b985
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
            @@ -0,0 +1,12 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/HardLineBreaks
            +type: text/vnd.tiddlywiki
            +
            +"""
            +This is some text
            +That is set like
            +It is a Poem
            +When it is
            +Clearly
            +Not
            +"""
            diff --git a/editions/test/tiddlers/tests/data/serialize/Heading.tid b/editions/test/tiddlers/tests/data/serialize/Heading.tid
            new file mode 100644
            index 000000000..8f90e379a
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Heading.tid
            @@ -0,0 +1,10 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Heading
            +type: text/vnd.tiddlywiki
            +
            +! Heading 1
            +!! Heading 2
            +!!! Heading 3
            +!!!! Heading 4
            +!!!!! Heading 5
            +!!!!!! Heading 6
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid
            new file mode 100644
            index 000000000..05507eb56
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid
            @@ -0,0 +1,11 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Html
            +type: text/vnd.tiddlywiki
            +
            +
            +
            +<$slider target="MyTiddler">
            +This is a widget invocation
            +
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Image.tid b/editions/test/tiddlers/tests/data/serialize/Image.tid
            new file mode 100644
            index 000000000..8641df4cb
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Image.tid
            @@ -0,0 +1,10 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Image
            +type: text/vnd.tiddlywiki
            +
            +[img[https://tiddlywiki.com/fractalveg.jpg]]
            +[img width="23" height="24" [https://tiddlywiki.com/fractalveg.jpg]]
            +[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]
            +[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]
            +[img[TiddlerTitle]]
            +[img[Description of image|TiddlerTitle]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Import.tid b/editions/test/tiddlers/tests/data/serialize/Import.tid
            new file mode 100644
            index 000000000..e467de534
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Import.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Import
            +type: text/vnd.tiddlywiki
            +
            +\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
            +\import [[$:/core/ui/PageMacros]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
            new file mode 100644
            index 000000000..a06ca62ce
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ItalicEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is //italic// text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/List.tid b/editions/test/tiddlers/tests/data/serialize/List.tid
            new file mode 100644
            index 000000000..d4088bcce
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/List.tid
            @@ -0,0 +1,27 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/List
            +type: text/vnd.tiddlywiki
            +
            +* This is an unordered list
            +* It has two items
            +
            +# This is a numbered list
            +## With a subitem
            +# And a third item
            +
            +; This is a term that is being defined
            +: This is the definition of that term
            +
            +#** One
            +#* Two
            +#** Three
            +#**** Four
            +#**# Five
            +#**## Six
            +## Seven
            +### Eight
            +## Nine
            +
            +* List item one
            +*.active List item two has the class `active`
            +* List item three
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
            new file mode 100644
            index 000000000..723e23edd
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroCallBlock
            +type: text/vnd.tiddlywiki
            +
            +<>
            +
            +<<.def "macro calls">>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
            new file mode 100644
            index 000000000..0b6b4fc50
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroCallInline
            +type: text/vnd.tiddlywiki
            +
            +These are macro calls in a line: <> and <<.def "macro calls">>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid
            new file mode 100644
            index 000000000..dcbc02e9d
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroDef
            +type: text/vnd.tiddlywiki
            +
            +\define name(param:defaultvalue,param2:defaultvalue)
            +definition text, including $param$ markers
            +\end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Parameters.tid b/editions/test/tiddlers/tests/data/serialize/Parameters.tid
            new file mode 100644
            index 000000000..5b107a73d
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Parameters.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Parameters
            +type: text/vnd.tiddlywiki
            +
            +\parameters(param:defaultvalue,param2:defaultvalue)
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ParserMode.tid b/editions/test/tiddlers/tests/data/serialize/ParserMode.tid
            new file mode 100644
            index 000000000..b4c31b66b
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ParserMode.tid
            @@ -0,0 +1,9 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ParserMode
            +type: text/vnd.tiddlywiki
            +
            +\parsermode block
            +
            +\parsermode inline
            +
            +Test.
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid b/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
            new file mode 100644
            index 000000000..1b4002b94
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/PrettyExtLink
            +type: text/vnd.tiddlywiki
            +
            +[ext[https://tiddlywiki.com/fractalveg.jpg]]
            +[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid b/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
            new file mode 100644
            index 000000000..8c7afbc7f
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/PrettyLink
            +type: text/vnd.tiddlywiki
            +
            +[[Introduction]]
            +[[Link description|TiddlerTitle]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid b/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
            new file mode 100644
            index 000000000..a2f698846
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/QuoteBlock
            +type: text/vnd.tiddlywiki
            +
            +<<` around this list will also have the class `myClass`
            +* List item 2
            +@@
            +
            +@@font-size:1.5em;
            +@@.coloured-text.coloured-bg
            +* Block content
            +* With custom style and classes
            +@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid b/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
            new file mode 100644
            index 000000000..cdd31254e
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
            @@ -0,0 +1,13 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/StyleBlock2
            +type: text/vnd.tiddlywiki
            +
            +@@width:100px;
            +@@.myFirstClass.mySecondClass.myThirdClass
            +This is a paragraph
            +@@
            +
            +@@background-color:lightcyan;
            +* Item one
            +* Item two
            +@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/StyleInline.tid b/editions/test/tiddlers/tests/data/serialize/StyleInline.tid
            new file mode 100644
            index 000000000..c491767f5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/StyleInline.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/StyleInline
            +type: text/vnd.tiddlywiki
            +
            +@@.myClass This is some text with a class@@
            +@@background-color:red; This is some text with a background colour@@
            +@@width:100px;.myClass This is some text with a class and a width@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
            new file mode 100644
            index 000000000..b39d7f6d5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SubscriptEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ,,subscript,, text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
            new file mode 100644
            index 000000000..9683f9e54
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SuperscriptEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ^^superscript^^ text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SysLink.tid b/editions/test/tiddlers/tests/data/serialize/SysLink.tid
            new file mode 100644
            index 000000000..fdbc982fe
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SysLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SysLink
            +type: text/vnd.tiddlywiki
            +
            +$:TiddlerTitle
            +~$:TiddlerTitle
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Table.tid b/editions/test/tiddlers/tests/data/serialize/Table.tid
            new file mode 100644
            index 000000000..213ecebff
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Table.tid
            @@ -0,0 +1,8 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Table
            +type: text/vnd.tiddlywiki
            +
            +|! |!Alpha |!Beta |!Gamma |!Delta |
            +|!One | | | | |
            +|!Two | | | | |
            +|!Three | | | | |
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
            new file mode 100644
            index 000000000..344171af0
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
            @@ -0,0 +1,21 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TranscludeBlock
            +type: text/vnd.tiddlywiki
            +
            +{{MyTiddler}}
            +
            +{{MyTiddler||TemplateTitle}}
            +
            +{{||TemplateTitle}}
            +
            +{{MyTiddler|Parameter}}
            +
            +{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}
            +
            +{{MyTiddler!!field}}
            +
            +{{!!field}}
            +
            +{{MyTiddler##index}}
            +
            +{{##index}}
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid b/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
            new file mode 100644
            index 000000000..df20658cf
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TranscludeInline
            +type: text/vnd.tiddlywiki
            +
            +{{MyTiddler}} {{MyTiddler||TemplateTitle}}
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid b/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
            new file mode 100644
            index 000000000..06362d062
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
            @@ -0,0 +1,15 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TypedBlock1
            +type: text/vnd.tiddlywiki
            +
            +$$$text/vnd.tiddlywiki > text/plain
            +This is ''some'' wikitext
            +$$$
            +
            +$$$text/unknown
            +Some plain text, which will not be //formatted//.
            +
            +$$$text/vnd.tiddlywiki > text/html
            +This is ''some'' wikitext
            +$$$
            +
            diff --git a/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid b/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
            new file mode 100644
            index 000000000..082ca533a
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
            @@ -0,0 +1,19 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TypedBlock2
            +type: text/vnd.tiddlywiki
            +
            +$$$.js
            +This will be rendered as JavaScript
            +$$$
            +
            +$$$.svg
            +
            +  
            +
            +$$$
            +
            +$$$image/svg+xml
            +
            +  
            +
            +$$$
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
            new file mode 100644
            index 000000000..73dc6425c
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/UnderscoreEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is __underscore__ text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/WikiLink.tid b/editions/test/tiddlers/tests/data/serialize/WikiLink.tid
            new file mode 100644
            index 000000000..18b04caf1
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/WikiLink.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/WikiLink
            +type: text/vnd.tiddlywiki
            +
            +AWikiLink
            +AnotherLink
            +~SuppressedLink
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid b/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            new file mode 100644
            index 000000000..982ed9071
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/WikiLinkPrefix
            +type: text/vnd.tiddlywiki
            +
            +~SuppressedLink
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index a8431694a..79d5c8306 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -10,400 +10,15 @@ Tests the wikitext inverse-rendering from Wiki AST.
             describe("WikiAST serialization unit 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: "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")
            -    );
            -  });
            -
            -  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: "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")
            -    );
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  wiki.addTiddler({
            -    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());
            -  });
            -
            -  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());
            -  });
            -
            -  wiki.addTiddler({
            -    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());
            -  });
            -
            -  wiki.addTiddler({
            -    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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  wiki.addTiddler({
            -    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());
            -  });
            -
            -  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());
            -  });
            -
            -  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());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "QuoteBlockTest",
            -    text: "<<` 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: "@@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();
            -    expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd());
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").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\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();
            -    expect(serialized).toBe(wiki.getTiddlerText("TranscludeBlockTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "TranscludeInlineTest",
            -    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());
            -  });
            -
            -  wiki.addTiddler({
            -    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("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());
            -  });
            -
            -  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());
            +  var cases = $tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[$:/tags/wikitext-serialize-test-spec]]");
            +  $tw.utils.each(cases, function (title) {
            +    wiki.addTiddler({
            +      title: title,
            +      text: wiki.getTiddlerText(title),
            +    });
            +    it("should serialize correctly for" + title, function () {
            +      var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler(title).tree).trimEnd();
            +      expect(serialized).toBe(wiki.getTiddlerText(title).trimEnd());
            +    });
               });
             });
            
            From 23489ce83c1a80444fd8e67f0c6792d60aafb06b Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Mon, 30 Sep 2024 18:15:30 +0800
            Subject: [PATCH 54/76] refactor: no need for new $tw.Wiki()
            
            ---
             .../test/tiddlers/tests/test-wikitext-serialize.js   | 12 +++---------
             1 file changed, 3 insertions(+), 9 deletions(-)
            
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 79d5c8306..e9c6f97cf 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -8,17 +8,11 @@ Tests the wikitext inverse-rendering from Wiki AST.
             \*/
             
             describe("WikiAST serialization unit tests", function () {
            -  var wiki = new $tw.Wiki();
            -
               var cases = $tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[$:/tags/wikitext-serialize-test-spec]]");
               $tw.utils.each(cases, function (title) {
            -    wiki.addTiddler({
            -      title: title,
            -      text: wiki.getTiddlerText(title),
            -    });
            -    it("should serialize correctly for" + title, function () {
            -      var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler(title).tree).trimEnd();
            -      expect(serialized).toBe(wiki.getTiddlerText(title).trimEnd());
            +    it("should serialize correctly for " + title, function () {
            +      var serialized = $tw.utils.serializeParseTree($tw.wiki.parseTiddler(title).tree).trimEnd();
            +      expect(serialized).toBe($tw.wiki.getTiddlerText(title).trimEnd());
                 });
               });
             });
            
            From 1a455209098a462e38c462d2028135e818709378 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 2 Oct 2024 13:47:41 +0800
            Subject: [PATCH 55/76] lint: double quote
            
            ---
             core/modules/parsers/parseutils.js            | 40 +++++++++----------
             core/modules/parsers/wikiparser/wikiparser.js |  2 +-
             2 files changed, 20 insertions(+), 22 deletions(-)
            
            diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js
            index b11300bfe..fcc96b2de 100644
            --- a/core/modules/parsers/parseutils.js
            +++ b/core/modules/parsers/parseutils.js
            @@ -386,33 +386,31 @@ exports.parseAttribute = function(source,pos) {
             };
             
             /*
            -Given a parsed attribute node, serialize it back into its source string representation.
            +Serialize a parsed attribute node
             */
             exports.serializeAttribute = function(node) {
            -	if(!node || typeof node !== 'object' || !node.name || !node.type) {
            -			return null;
            +	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();
            +	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
            +		 // Unsupported type
            +		return null;
             	}
            -
             	return attributeString;
             };
             
            diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
            index 10acf91ec..57f4983f9 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, rule: 'parseBlock' }];
            +	return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseBlock" }];
             };
             
             /*
            
            From 1c50996a133b8840690d4ace0e68e73408c2a8ef Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 2 Oct 2024 13:49:44 +0800
            Subject: [PATCH 56/76] refactor: lowercase the parseblock rule name
            
            ---
             core/modules/parsers/wikiparser/wikiparser.js |  2 +-
             core/modules/utils/parsetree.js               |  2 +-
             .../Parameterised-ParseTreeNodes.tid          |  2 +-
             .../tiddlers/tests/test-wikitext-parser.js    | 60 +++++++++----------
             4 files changed, 33 insertions(+), 33 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
            index 57f4983f9..68977c9d8 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, rule: "parseBlock" }];
            +	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 670d6307b..ad3f30150 100644
            --- a/core/modules/utils/parsetree.js
            +++ b/core/modules/utils/parsetree.js
            @@ -143,7 +143,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) {
             				Parser.prototype.pragmaRuleClasses[tree.rule];
             			if(Rule && Rule.prototype.serialize) {
             				output.push(Rule.prototype.serialize(tree,serializeParseTree));
            -			} else if(tree.rule === "parseBlock") {
            +			} else if(tree.rule === "parseblock") {
             				output.push(serializeParseTree(tree.children,tiddlerType),"\n\n");
             			} else {
             				// when no rule is found, just serialize the children
            diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid
            index 6db3f8be2..fc0d785f8 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,"rule":"parseBlock"}]

            [{"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 a3fe0d2d3..cdec74619 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 } ] } ] } ] } ] } ] } ] ); }); @@ -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}] ); @@ -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( @@ -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 f0babe4388377bba53dd1cc14e7bb950dc1fa0ad Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 03:13:51 +0800 Subject: [PATCH 57/76] fix: Wiki parser initialize blockRuleClasses only when first new an instance --- core/modules/utils/parsetree.js | 25 +++++++++++++++++++++++-- core/modules/wiki.js | 18 +----------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index ad3f30150..9940b1c17 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -123,11 +123,28 @@ exports.getParseTreeText = function getParseTreeText(tree) { return output.join(""); }; +exports.getParser = function(type,options) { + options = options || {}; + // Select a parser + var Parser = $tw.Wiki.parsers[type]; + if(!Parser && $tw.utils.getFileExtensionInfo(type)) { + Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type]; + } + if(!Parser) { + Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"]; + } + if(!Parser) { + return null; + } + return Parser; +}; + /* 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,options) { + options = options || {}; var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -137,7 +154,11 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { if(tree.type === "text" && !tree.rule) { output.push(tree.text); } else { - var Parser = $tw.wiki.getParser(tiddlerType); + var Parser = $tw.utils.getParser(tiddlerType); + if(!Parser.prototype.blockRuleClasses && !Parser.prototype.inlineRuleClasses && !Parser.prototype.pragmaRuleClasses) { + // Wiki parser initialize blockRuleClasses when first new an instance + new Parser(tiddlerType,undefined,{wiki: options.wiki || $tw.wiki}); + } var Rule = Parser.prototype.blockRuleClasses[tree.rule] || Parser.prototype.inlineRuleClasses[tree.rule] || Parser.prototype.pragmaRuleClasses[tree.rule]; diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 516751a1a..588deef2a 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1053,7 +1053,7 @@ Options include: exports.parseText = function(type,text,options) { text = text || ""; options = options || {}; - var Parser = this.getParser(type,options) + var Parser = $tw.utils.getParser(type,options) // Return the parser instance return new Parser(type,text,{ parseAsInline: options.parseAsInline, @@ -1063,22 +1063,6 @@ exports.parseText = function(type,text,options) { }); }; -exports.getParser = function(type,options) { - options = options || {}; - // Select a parser - var Parser = $tw.Wiki.parsers[type]; - if(!Parser && $tw.utils.getFileExtensionInfo(type)) { - Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type]; - } - if(!Parser) { - Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"]; - } - if(!Parser) { - return null; - } - return Parser; -}; - /* Parse a tiddler according to its MIME type */ From 375df47b19a4bf56406854887ee726dcd8432674 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 03:26:35 +0800 Subject: [PATCH 58/76] feat: restore inline macro def --- core/modules/parsers/wikiparser/rules/macrodef.js | 9 +++++++-- editions/test/tiddlers/tests/data/serialize/MacroDef.tid | 4 +++- editions/test/tiddlers/tests/test-wikitext-parser.js | 9 +++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index be000eab0..3fe2195f6 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -55,9 +55,10 @@ exports.parse = function() { } } // Is the remainder of the \define line blank after the parameter close paren? - var reEnd; + var reEnd,inline = true; if(this.match[3]) { // If so, it is a multiline definition and the end of the body is marked with \end + inline = false; reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line @@ -82,7 +83,8 @@ exports.parse = function() { attributes: {}, children: [], params: params, - isMacroDefinition: true + isMacroDefinition: true, + inline: inline && !!endMatch }]; $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); @@ -95,6 +97,9 @@ exports.serialize = function(tree,serialize) { return param.name + (param.default ? ":" + param.default : ""); }).join(","); var definition = tree.attributes.value.value; + if(tree.inline) { + return "\\define " + name + "(" + params + ") " + definition + "\n\n" + serialize(tree.children); + } return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); }; diff --git a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid index dcbc02e9d..132ee7053 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid @@ -4,4 +4,6 @@ type: text/vnd.tiddlywiki \define name(param:defaultvalue,param2:defaultvalue) definition text, including $param$ markers -\end \ No newline at end of file +\end + +\define lingo-base() $:/language/ControlPanel/Basics/ diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index cdec74619..72136475f 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -114,7 +114,12 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + + ); + expect(parse("\\define myMacro() nothing\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] ); }); @@ -185,7 +190,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":32,"end":61,"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,"inline":false,"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 53296a484ce92a4b48cf52f3089e63a81a422067 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 20:55:03 +0800 Subject: [PATCH 59/76] fix: macro in widget param --- core/modules/parsers/parseutils.js | 11 +++++++++-- core/modules/parsers/wikiparser/rules/html.js | 6 +++--- .../test/tiddlers/tests/data/serialize/Attribute.tid | 5 +++++ 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/serialize/Attribute.tid diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index fcc96b2de..e2e95c684 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -405,8 +405,15 @@ exports.serializeAttribute = function(node) { } 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(); + if(node.value && typeof node.value === "object" && node.value.type === "macrocall") { + var params = node.value.params.map(function(param) { + return param.value; + }).join(" "); + attributeString += "=<<" + node.value.name + " " + params + ">>"; + } else { + // Unsupported macro structure + return null; + } } else { // Unsupported type return null; diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index df52819e2..e27089086 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -197,9 +197,9 @@ 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(""); + var attributes = tree.orderedAttributes.map(function(attribute) { + return $tw.utils.serializeAttribute(attribute); + }).join(" "); // Children var children = tree.children ? serialize(tree.children) : ""; // Self-closing tag diff --git a/editions/test/tiddlers/tests/data/serialize/Attribute.tid b/editions/test/tiddlers/tests/data/serialize/Attribute.tid new file mode 100644 index 000000000..6ecda2c01 --- /dev/null +++ b/editions/test/tiddlers/tests/data/serialize/Attribute.tid @@ -0,0 +1,5 @@ +tags: $:/tags/wikitext-serialize-test-spec +title: Serialize/Attribute +type: text/vnd.tiddlywiki + +<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4" /> From 72dd18dfa539d1773231377d7dc7ca703a6e32ec Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:31:29 +0800 Subject: [PATCH 60/76] fix: positional attribute in macro call --- core/modules/parsers/parseutils.js | 19 ++++++++++++------- .../wikiparser/rules/macrocallblock.js | 6 +++--- .../tests/data/serialize/MacroCallBlock.tid | 4 +++- .../tests/data/serialize/MacroCallInline.tid | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index e2e95c684..8d143c5e9 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -388,28 +388,33 @@ exports.parseAttribute = function(source,pos) { /* Serialize a parsed attribute node */ -exports.serializeAttribute = function(node) { +exports.serializeAttribute = function(node,options) { + options = options || {}; if(!node || typeof node !== "object" || !node.name || !node.type) { return null; } - var attributeString = node.name; + // If name is number, means it is a positional attribute and name is omitted + var positional = parseInt(node.name) >= 0, + // `=` in a widget and might be `:` in a macro + assign = positional ? "" : (options.assignmentSymbol || "="), + attributeString = positional ? "" : node.name; if(node.type === "string") { if(node.value === "true") { return attributeString; } - attributeString += '="' + node.value + '"'; + attributeString += assign + '"' + node.value + '"'; } else if(node.type === "filtered") { - attributeString += "={{{" + node.filter + "}}}"; + attributeString += assign + "{{{" + node.filter + "}}}"; } else if(node.type === "indirect") { - attributeString += "={{" + node.textReference + "}}"; + attributeString += assign + "{{" + node.textReference + "}}"; } else if(node.type === "substituted") { - attributeString += "=`" + node.rawValue + "`"; + attributeString += assign + "`" + node.rawValue + "`"; } else if(node.type === "macro") { if(node.value && typeof node.value === "object" && node.value.type === "macrocall") { var params = node.value.params.map(function(param) { return param.value; }).join(" "); - attributeString += "=<<" + node.value.name + " " + params + ">>"; + attributeString += assign + "<<" + node.value.name + " " + params + ">>"; } else { // Unsupported macro structure return null; diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index 1572cce63..a684a2d28 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -64,9 +64,9 @@ exports.serialize = function (node) { } // Append ordered arguments if any if(node.orderedAttributes) { - node.orderedAttributes.forEach(function (attr) { - if(attr.name !== "$variable") { - result += " " + '"' + attr.value + '"'; + node.orderedAttributes.forEach(function (attribute) { + if(attribute.name !== "$variable") { + result += " " + $tw.utils.serializeAttribute(attribute,{assignmentSymbol:":"}); } }); } diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid index 723e23edd..4bd30d451 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid @@ -4,4 +4,6 @@ type: text/vnd.tiddlywiki <> -<<.def "macro calls">> \ No newline at end of file +<<.def "macro calls">> + +<> diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid index 0b6b4fc50..09127dce0 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid @@ -2,4 +2,4 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/MacroCallInline type: text/vnd.tiddlywiki -These are macro calls in a line: <> and <<.def "macro calls">> \ No newline at end of file +These are macro calls in a line: <> and <<.def "macro calls">> <> From fb9f7a5ea1c3b413aec25f2e0ddba28d1d398888 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:31:51 +0800 Subject: [PATCH 61/76] fix: table space and horizrule block new line --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- core/modules/parsers/wikiparser/rules/table.js | 10 +++++----- .../test/tiddlers/tests/data/serialize/CodeBlock.tid | 5 +++++ editions/test/tiddlers/tests/data/serialize/Table.tid | 11 +++++++---- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 99e25af55..aae047316 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -58,7 +58,7 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; + return "```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n\n"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 4fd66de41..386a0aaef 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(tree,serialize) { - return "---\n"; + return "---\n\n"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index 68811efc0..2c6f4356a 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -205,17 +205,17 @@ exports.serialize = function(tree, serialize) { if(cell.tag === "th") { serialized += "!"; } - // Serialize the cell content + // Cell content serialized += serialize(cell.children); - // End the cell with a tailing space - serialized += " |"; + // End the cell + serialized += "|"; } // End the row serialized += "\n"; } } - // Return the complete serialized string - return serialized; + // Return the completed block + return serialized + "\n"; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid index 8b1499970..7a03f3aea 100644 --- a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid @@ -9,4 +9,9 @@ Simple `JS` and complex ```js var match = reEnd.exec(this.parser.source) ``` + +```tid +<$list filter="[tag[ExampleTag]sort[title]]"/> +``` + end \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/serialize/Table.tid b/editions/test/tiddlers/tests/data/serialize/Table.tid index 213ecebff..bd92db4bc 100644 --- a/editions/test/tiddlers/tests/data/serialize/Table.tid +++ b/editions/test/tiddlers/tests/data/serialize/Table.tid @@ -2,7 +2,10 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Table type: text/vnd.tiddlywiki -|! |!Alpha |!Beta |!Gamma |!Delta | -|!One | | | | | -|!Two | | | | | -|!Three | | | | | \ No newline at end of file +|!|!Alpha|!Beta|!Gamma|!Delta| +|!One||||| +|!Two||||| +|!Three||||| + +|cell one|cell two| +|cell three|cell four| From 47cc03d05db1c07e124f54347299274c061dc5b9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:36:35 +0800 Subject: [PATCH 62/76] feat: make sure block rule all have \n\n for visiblity --- .../parsers/wikiparser/rules/conditional.js | 2 +- .../rules/filteredtranscludeblock.js | 2 +- .../parsers/wikiparser/rules/heading.js | 2 +- .../parsers/wikiparser/rules/quoteblock.js | 2 +- .../serialize/FilteredTranscludeBlock.tid | 6 +++++- .../tiddlers/tests/data/serialize/Heading.tid | 21 ++++++++++++++++++- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 84ac3cef8..6f884de1c 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -139,7 +139,7 @@ exports.serialize = function(tree, serialize) { } serialized += "<%endif%>"; - return serialized; + return serialized += "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 994596855..553d68c0e 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -83,7 +83,7 @@ exports.serialize = function(tree, serialize) { serialized += "}" // CSS classes if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); - return serialized + "\n"; + return serialized + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 67470c9c5..70b58e71d 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -51,7 +51,7 @@ exports.serialize = function(tree, serialize) { var headingLevel = parseInt(tree.tag.substr(1),10); var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; var headingText = serialize(tree.children); - return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n"; + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index be7052795..a652cdf1b 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -85,7 +85,7 @@ exports.serialize = function (tree, serialize) { }); result.push("<<<"); } - return result.join("\n"); + return result.join("\n") + "\n\n"; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid index cbfc442c5..b1c526d9d 100644 --- a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid @@ -3,7 +3,11 @@ title: Serialize/FilteredTranscludeBlock type: text/vnd.tiddlywiki {{{ [tag[docs]] }}} + {{{ [tag[docs]] |tooltip}}} + {{{ [tag[docs]] ||TemplateTitle}}} + {{{ [tag[docs]] |tooltip||TemplateTitle}}} -{{{ [tag[docs]] }}width:40;height:50;}.class.class \ No newline at end of file + +{{{ [tag[docs]] }}width:40;height:50;}.class.class diff --git a/editions/test/tiddlers/tests/data/serialize/Heading.tid b/editions/test/tiddlers/tests/data/serialize/Heading.tid index 8f90e379a..34152e50a 100644 --- a/editions/test/tiddlers/tests/data/serialize/Heading.tid +++ b/editions/test/tiddlers/tests/data/serialize/Heading.tid @@ -3,8 +3,27 @@ title: Serialize/Heading type: text/vnd.tiddlywiki ! Heading 1 + !! Heading 2 + !!! Heading 3 + !!!! Heading 4 + !!!!! Heading 5 -!!!!!! Heading 6 \ No newline at end of file + +!!!!!! Heading 6 + +! AAA + +!! AAA + +!!! AAA + +!!!! AAA + +!!!!! AAA + +!!!!!! AAA + +AAA From 8056d8c11e570ebf76bcdebd37938ad960fdbe64 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:38:06 +0800 Subject: [PATCH 63/76] lint: function param --- core/modules/parsers/wikiparser/rules/commentblock.js | 2 +- core/modules/parsers/wikiparser/rules/commentinline.js | 2 +- core/modules/parsers/wikiparser/rules/conditional.js | 2 +- core/modules/parsers/wikiparser/rules/dash.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/bold.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/italic.js | 2 +- .../parsers/wikiparser/rules/emphasis/strikethrough.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/subscript.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/superscript.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/underscore.js | 2 +- core/modules/parsers/wikiparser/rules/entity.js | 2 +- core/modules/parsers/wikiparser/rules/extlink.js | 2 +- .../parsers/wikiparser/rules/filteredtranscludeblock.js | 2 +- .../parsers/wikiparser/rules/filteredtranscludeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/fnprocdef.js | 2 +- core/modules/parsers/wikiparser/rules/heading.js | 2 +- core/modules/parsers/wikiparser/rules/html.js | 2 +- core/modules/parsers/wikiparser/rules/image.js | 2 +- core/modules/parsers/wikiparser/rules/list.js | 2 +- core/modules/parsers/wikiparser/rules/macrocallinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/prettyextlink.js | 2 +- core/modules/parsers/wikiparser/rules/prettylink.js | 2 +- core/modules/parsers/wikiparser/rules/quoteblock.js | 2 +- core/modules/parsers/wikiparser/rules/rules.js | 2 +- core/modules/parsers/wikiparser/rules/styleblock.js | 2 +- core/modules/parsers/wikiparser/rules/styleinline.js | 2 +- core/modules/parsers/wikiparser/rules/syslink.js | 2 +- core/modules/parsers/wikiparser/rules/table.js | 2 +- core/modules/parsers/wikiparser/rules/transcludeblock.js | 2 +- core/modules/parsers/wikiparser/rules/transcludeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/typedblock.js | 2 +- core/modules/parsers/wikiparser/rules/wikilink.js | 2 +- core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 2 +- 33 files changed, 36 insertions(+), 36 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 7d9a68f14..997be818c 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -63,7 +63,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { 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 183eea447..f39d9f6ff 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -55,7 +55,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return tree.text; }; diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 6f884de1c..6f30ef3a3 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -117,7 +117,7 @@ exports.parseIfClause = function(filterCondition) { return [listWidget]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var filterCondition = tree.attributes.filter.value; var ifClause = serialize(tree.children[0].children); var elseClause = tree.children[1].children; diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js index 4d06a54cd..84f996cf6 100644 --- a/core/modules/parsers/wikiparser/rules/dash.js +++ b/core/modules/parsers/wikiparser/rules/dash.js @@ -37,7 +37,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return tree.entity === "–" ? "--" : "---"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index bcd55f556..c6758819f 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "''" + serialize(tree.children) + "''"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 88be5617a..12b9a34c9 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "//" + serialize(tree.children) + "//"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index d42ac62b3..44e180a84 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { 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 b49598934..e2d9f766b 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { 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 a843aec5d..df6d0217c 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "^^" + serialize(tree.children) + "^^"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index 4d223185a..2bf57f1bd 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "__" + serialize(tree.children) + "__"; }; diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js index 10e288990..d5d0405f2 100644 --- a/core/modules/parsers/wikiparser/rules/entity.js +++ b/core/modules/parsers/wikiparser/rules/entity.js @@ -37,7 +37,7 @@ exports.parse = function() { return [{type: "entity", entity: this.match[0]}]; }; -exports.serialize = function(tree, serialize) { +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 250c9f226..88dfd3e0a 100644 --- a/core/modules/parsers/wikiparser/rules/extlink.js +++ b/core/modules/parsers/wikiparser/rules/extlink.js @@ -53,7 +53,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { if(tree.type === "text") { return "~" + tree.text; } else if(tree.type === "element" && tree.tag === "a") { diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 553d68c0e..f3a342ee0 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,7 +71,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +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 8ab8887d7..efc596bba 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,9 +70,9 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var filteredtranscludeblock = require("$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js"); - var result = filteredtranscludeblock.serialize(tree, serialize); + var result = filteredtranscludeblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index 82c4b6217..cbc36bae5 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -93,7 +93,7 @@ exports.parse = function() { return parseTreeNodes; }; -exports.serialize = function(tree, serialize) { +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 diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 70b58e71d..3c762fd83 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -46,7 +46,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { // 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(".") : ""; diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index e27089086..53a5139c5 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -195,7 +195,7 @@ exports.isLegalTag = function(tag) { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var tag = tree.tag; var attributes = tree.orderedAttributes.map(function(attribute) { return $tw.utils.serializeAttribute(attribute); diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index f046c59f1..7b612a9c7 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -130,7 +130,7 @@ exports.parseImage = function(source,pos) { return node; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { 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 ? " " : ""; diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index 71a7cab5e..e047bab21 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -160,7 +160,7 @@ exports.parse = function() { return [listStack[0]]; }; -exports.serialize = function (tree, serialize) { +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) { diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index 132eabef9..ff91b7a91 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -49,9 +49,9 @@ exports.parse = function() { /* Same as macrocallblock but without \n\n */ -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { var macrocallblock = require("$:/core/modules/parsers/wikiparser/rules/macrocallblock.js"); - var result = macrocallblock.serialize(tree, serialize); + var result = macrocallblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js index f56ee8fe0..088a981b8 100644 --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js @@ -117,7 +117,7 @@ exports.parseLink = function(source,pos) { return node; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { var tooltip = tree.children[0].text; var url = tree.attributes.href.value; 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 0b798a5dc..7a516a801 100644 --- a/core/modules/parsers/wikiparser/rules/prettylink.js +++ b/core/modules/parsers/wikiparser/rules/prettylink.js @@ -67,7 +67,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { var text = tree.children[0].text; var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value; return "[[" + text + (text !== target ? "|" + target : "") + "]]"; diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index a652cdf1b..05a42f517 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,7 +73,7 @@ exports.parse = function() { }]; }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { 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 a5958d67c..8aca74e16 100644 --- a/core/modules/parsers/wikiparser/rules/rules.js +++ b/core/modules/parsers/wikiparser/rules/rules.js @@ -68,7 +68,7 @@ exports.parse = function() { }]; }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { 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 a5e19cfcc..091ce7f53 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -73,7 +73,7 @@ exports.parse = function() { }] }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { 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 01c047856..77857b006 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -55,7 +55,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { 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 e5387e5ee..aeeb4bdf2 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -50,7 +50,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === "~"; var serialized = isSuppressed ? "~" : ""; diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index 2c6f4356a..992c05b4e 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -188,7 +188,7 @@ exports.parse = function() { return [table]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var serialized = ""; // Iterate over the table rows for(var i = 0; i < tree.children.length; i++) { diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 319726f0a..8aac3ee65 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -86,7 +86,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var result = "{{"; function handleTransclude(transcludeNode) { // Handle field diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index af525b78a..17271bcd5 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -84,9 +84,9 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var transcludeblock = require("$:/core/modules/parsers/wikiparser/rules/transcludeblock.js"); - var result = transcludeblock.serialize(tree, serialize); + var result = transcludeblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index 38985daaa..c0adb1c0c 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -98,7 +98,7 @@ exports.parse = function() { } }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { if(tree.type === "void") { return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n"; } diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index d5e1a48ec..40888315f 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -65,7 +65,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +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 : ""; diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index 1de26d25c..a51544e58 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -37,7 +37,7 @@ exports.parse = function() { return [{type: "text", text: linkText.substr(1)}]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var serialized = $tw.config.textPrimitives.unWikiLink; serialized += tree.text; return serialized; From 0f385675c29b8590d49d22fb38ecdd8e0b27a045 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 22:13:27 +0800 Subject: [PATCH 64/76] fix: empty list item --- core/modules/parsers/wikiparser/rules/list.js | 14 ++++++++++---- .../test/tiddlers/tests/data/serialize/List.tid | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index e047bab21..cf0b1e0d6 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -66,6 +66,12 @@ var listTypes = { var listTags = Object.values(listTypes).map(function(type) { return type.listTag; }); +/* +Check if the child is a nested list or a simple line of list item +*/ +function isListNode(node) { + return node && node.type === "element" && listTags.includes(node.tag); +} var itemTags = Object.values(listTypes).map(function(type) { return type.itemTag; }); @@ -174,7 +180,7 @@ exports.serialize = function (tree,serialize) { // Recursive function to serialize list nodes, handling nested lists and formatting output function serializeList(node, markerPrefix) { var result = []; - if(node.type === "element" && listTags.includes(node.tag)) { + if(node.type === "element" && isListNode(node)) { node.children.forEach(function (child) { if(itemTags.includes(child.tag)) { var currentMarker = findMarker(node.tag, child.tag); @@ -183,8 +189,7 @@ exports.serialize = function (tree,serialize) { // 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(listTags.includes(subNode.tag)) { + if(isListNode(subNode)) { // Recursive call for nested lists if(content.length > 0) { result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); @@ -196,7 +201,8 @@ exports.serialize = function (tree,serialize) { } return ""; // Default return for unhandled node types }); - if(content.length > 0) { + // prepend `#` mark to a new line, if it has content (and has or hasn't nested list), or if it has no content and also no nested list + if(content.length > 0 || child.children.length === 0) { result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } diff --git a/editions/test/tiddlers/tests/data/serialize/List.tid b/editions/test/tiddlers/tests/data/serialize/List.tid index d4088bcce..d25397799 100644 --- a/editions/test/tiddlers/tests/data/serialize/List.tid +++ b/editions/test/tiddlers/tests/data/serialize/List.tid @@ -24,4 +24,17 @@ type: text/vnd.tiddlywiki * List item one *.active List item two has the class `active` -* List item three \ No newline at end of file +* List item three + +# AAA +## [[BBB]] +### CCC +# AAA +## CCC +## DDD +## EEE +# BBB +## FF `/` FFF +## FFF +## GGG +## From f220dacdd80ad0877759169b3dba25b35d620480 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 14 Oct 2024 00:47:13 +0800 Subject: [PATCH 65/76] feat: add \n\n based on isBlock, if could also be inline --- core/modules/parsers/wikiparser/rules/html.js | 12 +++++++++--- editions/test/tiddlers/tests/data/serialize/Html.tid | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 53a5139c5..39ea1e141 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -202,12 +202,18 @@ exports.serialize = function(tree,serialize) { }).join(" "); // Children var children = tree.children ? serialize(tree.children) : ""; + var result = ""; // Self-closing tag if(tree.isSelfClosing) { - return "<" + tag + (attributes ? " " + attributes : "") + " />"; + result += "<" + tag + (attributes ? " " + attributes : "") + " />"; + } else { + // Opening and closing tags + result += "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; } - // Opening and closing tags - return "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; + if(tree.isBlock) { + result += "\n\n"; + } + return result; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid index 05507eb56..d4a8db414 100644 --- a/editions/test/tiddlers/tests/data/serialize/Html.tid +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid @@ -8,4 +8,8 @@ This is an HTML5 aside element <$slider target="MyTiddler"> This is a widget invocation - \ No newline at end of file + + +<$list filter="[tag[ExampleTag]sort[title]]" /> + +Plain text in next paragraph. \ No newline at end of file From 5fdc9f365ef3e4c3597914231040c54279f07744 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 14 Oct 2024 00:47:37 +0800 Subject: [PATCH 66/76] fix: conditional without elseif --- .../parsers/wikiparser/rules/conditional.js | 44 +++++++++++-------- .../tests/data/serialize/Conditional.tid | 18 +++++++- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 6f30ef3a3..6ec8a6ab5 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -118,28 +118,36 @@ exports.parseIfClause = function(filterCondition) { }; exports.serialize = function(tree,serialize) { + // We always have "if" at the beginning var filterCondition = tree.attributes.filter.value; - var ifClause = serialize(tree.children[0].children); - var elseClause = tree.children[1].children; - 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) { - // Handle elseif clause - var elseifCondition = elseClause[i].attributes.filter.value; - var elseifClause = serialize(elseClause[i].children[0]); - serialized += "<%elseif " + elseifCondition + "%>" + elseifClause; - } - if(elseClause[i].children[1]) { - var elseClauseText = serialize(elseClause[i].children[1]); - serialized += "<%else%>" + elseClauseText; + var ifClauseText = serialize(tree.children[0].children); + var result = "<%if " + filterCondition + "%>" + ifClauseText; + function serializeElseIf(listNode) { + // We receive the only list node inside list-template node + if(!listNode || listNode.type !== "list") { + return "<%else%>" + serialize(listNode); + } + var filter = listNode.attributes.filter.value || ""; + var bodyText = serialize(listNode.children[0].children); + var nextConditionResult = ""; + // May has an only any node inside list-empty node + if(listNode.children[1] && listNode.children[1].children[0]) { + if(listNode.children[1].children[0].type === "list") { + nextConditionResult = serializeElseIf(listNode.children[1].children[0]); + } else { + nextConditionResult = "<%else%>" + serialize(listNode.children[1]); } } + return "<%elseif " + filter + "%>" + bodyText + nextConditionResult; } - - serialized += "<%endif%>"; - return serialized += "\n\n"; + if(tree.children[1] && tree.children[1].children) { + result += serializeElseIf(tree.children[1].children[0]); + } + result += "<%endif%>"; + if(tree.isBlock) { + result += "\n\n"; + } + return result; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/Conditional.tid b/editions/test/tiddlers/tests/data/serialize/Conditional.tid index 4e96726f7..4540e6eb4 100644 --- a/editions/test/tiddlers/tests/data/serialize/Conditional.tid +++ b/editions/test/tiddlers/tests/data/serialize/Conditional.tid @@ -2,4 +2,20 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Conditional type: text/vnd.tiddlywiki -This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%> \ No newline at end of file +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%> <%if [{something}] %>Elephant<%else%>Crocodile<%endif%> + +<%if [{$:/info/url/protocol}match[file:]]%> + Loaded from a file URI +<%elseif [{$:/info/url/protocol}match[https:]]%> + Loaded from an HTTPS URI +<%elseif [{$:/info/url/protocol}match[http:]]%> + Loaded from an HTTP URI +<%else%> + Loaded from an unknown protocol +<%endif%> + +Plain text in next paragraph. + +<%if [{$:/info/url/protocol}match[file:]]%> + Hidden. +<%endif%> From 87dc05be9da780b667920d5ded6e521c43fb9f29 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Mon, 14 Oct 2024 16:43:50 +0800 Subject: [PATCH 67/76] refactor: use isBlock in macrodef to know inline or block --- core/modules/parsers/wikiparser/rules/macrodef.js | 8 ++++---- editions/test/tiddlers/tests/test-wikitext-parser.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 3fe2195f6..5c20a0302 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -55,10 +55,10 @@ exports.parse = function() { } } // Is the remainder of the \define line blank after the parameter close paren? - var reEnd,inline = true; + var reEnd,isBlock = true; if(this.match[3]) { // If so, it is a multiline definition and the end of the body is marked with \end - inline = false; + isBlock = false; reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line @@ -84,7 +84,7 @@ exports.parse = function() { children: [], params: params, isMacroDefinition: true, - inline: inline && !!endMatch + isBlock: isBlock && !!endMatch }]; $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); @@ -97,7 +97,7 @@ exports.serialize = function(tree,serialize) { return param.name + (param.default ? ":" + param.default : ""); }).join(","); var definition = tree.attributes.value.value; - if(tree.inline) { + if(tree.isBlock) { return "\\define " + name + "(" + params + ") " + definition + "\n\n" + serialize(tree.children); } return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 72136475f..5fa1c28a3 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -114,12 +114,12 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] ); expect(parse("\\define myMacro() nothing\n\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] ); }); @@ -190,7 +190,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,"inline":false,"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"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":false,"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 2765e995dd0d1da605159cda3eed896cb3687b4d Mon Sep 17 00:00:00 2001 From: linonetwo Date: Wed, 19 Feb 2025 18:58:33 +0800 Subject: [PATCH 68/76] fix: link may not have attribute and children --- core/modules/parsers/wikiparser/rules/syslink.js | 6 +++--- core/modules/parsers/wikiparser/rules/wikilink.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js index aeeb4bdf2..a9a04cc7b 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -51,11 +51,11 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - // Check if the link is suppressed - var isSuppressed = tree.children[0].text.substr(0,1) === "~"; + // Check if the link is suppressed. Tree may only have text, no children and attributes + var isSuppressed = tree.children && tree.children[0].text.substr(0,1) === "~"; var serialized = isSuppressed ? "~" : ""; // Append the link text - serialized += tree.attributes.to.value; + serialized += tree.attributes ? tree.attributes.to.value : tree.text; return serialized; }; diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 40888315f..8628a4f6c 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -66,10 +66,10 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; + var isSuppressed = tree.children && tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; - serialized += tree.attributes.to.value; + serialized += tree.attributes ? tree.attributes.to.value : tree.text; return serialized; }; From 069181d615a391bec4c7ad37b66dfc7ffc3128f2 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 19 Feb 2025 15:38:49 +0800 Subject: [PATCH 69/76] DEBUG: render result and diff below body only on browser DEBUG: render result below body only on browser DEBUG: render result below body DEBUG: fix build DEBUG: show render result as ViewTemplate --- core/modules/filters/serializeparsetree.js | 29 ++++++++++++++++++++++ core/ui/ViewTemplate/body/default.tid | 14 +++++++++++ 2 files changed, 43 insertions(+) create mode 100644 core/modules/filters/serializeparsetree.js diff --git a/core/modules/filters/serializeparsetree.js b/core/modules/filters/serializeparsetree.js new file mode 100644 index 000000000..04796a2c9 --- /dev/null +++ b/core/modules/filters/serializeparsetree.js @@ -0,0 +1,29 @@ +/*\ +title: $:/core/modules/filters/serializeparsetree.js +type: application/javascript +module-type: filteroperator + +Filter operator for serializing JSON string of Abstract Syntax Tree (AST) of Wiki parse tree to a raw WikiText string. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.serializeparsetree = function(source,operator,options) { + var results = []; + source(function(tiddler,title) { + var parseTreeObject = $tw.utils.parseJSONSafe(title); + if(parseTreeObject) { + results.push($tw.utils.serializeParseTree(parseTreeObject)); + } + }); + return results; +}; + +})(); diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index 5416c6e07..cc2453ecf 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,3 +6,17 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> + +<%if [[$:/info/browser]text[yes]] %> + <$wikify text={{!!text}} name=parsetree output=parsetree > + <$let text2={{{[serializeparsetree[]]}}}> + <$wikify name=rendered text=<> output=html > + + <$diff-text source={{!!text}} dest=<>/> + + <> + + + + +<%endif%> \ No newline at end of file From 86ec4cae45ab79e5553aa043435c53e9830e7b07 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 28 Feb 2025 23:11:43 +0800 Subject: [PATCH 70/76] fix: remove pad space in /> --- core/modules/parsers/wikiparser/rules/html.js | 2 +- core/ui/ViewTemplate/body/default.tid | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 39ea1e141..5c128529e 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -205,7 +205,7 @@ exports.serialize = function(tree,serialize) { var result = ""; // Self-closing tag if(tree.isSelfClosing) { - result += "<" + tag + (attributes ? " " + attributes : "") + " />"; + result += "<" + tag + (attributes ? " " + attributes : "") + "/>"; } else { // Opening and closing tags result += "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index cc2453ecf..1b8c3940c 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,12 +6,10 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> - <%if [[$:/info/browser]text[yes]] %> <$wikify text={{!!text}} name=parsetree output=parsetree > <$let text2={{{[serializeparsetree[]]}}}> <$wikify name=rendered text=<> output=html > - <$diff-text source={{!!text}} dest=<>/> <> From 74c9841901d6157db8d675f274e62cc0bdff8b56 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 1 Mar 2025 02:12:09 +0800 Subject: [PATCH 71/76] test: remove pad space in /> --- editions/test/tiddlers/tests/data/serialize/Attribute.tid | 2 +- editions/test/tiddlers/tests/data/serialize/Html.tid | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editions/test/tiddlers/tests/data/serialize/Attribute.tid b/editions/test/tiddlers/tests/data/serialize/Attribute.tid index 6ecda2c01..3f986784a 100644 --- a/editions/test/tiddlers/tests/data/serialize/Attribute.tid +++ b/editions/test/tiddlers/tests/data/serialize/Attribute.tid @@ -2,4 +2,4 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Attribute type: text/vnd.tiddlywiki -<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4" /> +<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4"/> diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid index d4a8db414..76b86d570 100644 --- a/editions/test/tiddlers/tests/data/serialize/Html.tid +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid @@ -10,6 +10,6 @@ This is an HTML5 aside element This is a widget invocation -<$list filter="[tag[ExampleTag]sort[title]]" /> +<$list filter="[tag[ExampleTag]sort[title]]"/> Plain text in next paragraph. \ No newline at end of file From 8ab12738cf446f169609fd1d6c23d50ec10c2310 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 15:46:10 +0800 Subject: [PATCH 72/76] Revert DEBUG: render result and diff below body only on browser --- core/modules/filters/serializeparsetree.js | 29 ---------------------- core/ui/ViewTemplate/body/default.tid | 12 --------- 2 files changed, 41 deletions(-) delete mode 100644 core/modules/filters/serializeparsetree.js diff --git a/core/modules/filters/serializeparsetree.js b/core/modules/filters/serializeparsetree.js deleted file mode 100644 index 04796a2c9..000000000 --- a/core/modules/filters/serializeparsetree.js +++ /dev/null @@ -1,29 +0,0 @@ -/*\ -title: $:/core/modules/filters/serializeparsetree.js -type: application/javascript -module-type: filteroperator - -Filter operator for serializing JSON string of Abstract Syntax Tree (AST) of Wiki parse tree to a raw WikiText string. - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -/* -Export our filter function -*/ -exports.serializeparsetree = function(source,operator,options) { - var results = []; - source(function(tiddler,title) { - var parseTreeObject = $tw.utils.parseJSONSafe(title); - if(parseTreeObject) { - results.push($tw.utils.serializeParseTree(parseTreeObject)); - } - }); - return results; -}; - -})(); diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index 1b8c3940c..5416c6e07 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,15 +6,3 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> -<%if [[$:/info/browser]text[yes]] %> - <$wikify text={{!!text}} name=parsetree output=parsetree > - <$let text2={{{[serializeparsetree[]]}}}> - <$wikify name=rendered text=<> output=html > - <$diff-text source={{!!text}} dest=<>/> - - <> - - - - -<%endif%> \ No newline at end of file From 711bf01049fccda5c041f6ad5022c936dbbff6f9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:31:15 +0800 Subject: [PATCH 73/76] refactor: fold commentText variable --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 +-- core/modules/parsers/wikiparser/rules/commentinline.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 997be818c..5f87020ca 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -53,11 +53,10 @@ exports.parse = function() { // 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: "void", children: [], - text: commentText, + text: this.parser.source.slice(commentStart, commentEnd), start: commentStart, end: commentEnd }]; diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index f39d9f6ff..b96f5d78b 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -46,10 +46,9 @@ exports.parse = function() { // 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: "void", - text: commentText, + text: this.parser.source.slice(commentStart, commentEnd), start: commentStart, end: commentEnd }]; From 5c0198b7b5eaeceb99bca568d96d1d983d4c9f8d Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:31:49 +0800 Subject: [PATCH 74/76] refactor: fold long comment --- core/modules/parsers/wikiparser/rules/list.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index cf0b1e0d6..d0a5e2f65 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -186,7 +186,10 @@ exports.serialize = function (tree,serialize) { 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. + /** + * 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) { if(isListNode(subNode)) { From a97aedec34edd3617eee93de20cb5e7a3522dc2e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:35:52 +0800 Subject: [PATCH 75/76] fix: double quotes for parameter values --- core/modules/parsers/wikiparser/rules/fnprocdef.js | 10 +++++----- .../tests/data/serialize/FunctionDefinition.tid | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index cbc36bae5..8343e0cca 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -6,15 +6,15 @@ module-type: wikirule Wiki pragma rule for function, procedure and widget definitions ``` -\function name(param:defaultvalue,param2:defaultvalue) +\function name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\procedure name(param:defaultvalue,param2:defaultvalue) +\procedure name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\widget $mywidget(param:defaultvalue,param2:defaultvalue) +\widget $mywidget(param:"defaultvalue", param2:"defaultvalue") definition text \end ``` @@ -100,8 +100,8 @@ exports.serialize = function(tree,serialize) { 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(","); + return param.name + (param.default ? ':"' + param.default + '"' : ""); + }).join(", "); // Definition text var definition = tree.attributes.value.value; // Construct the serialized string, concat the children because pragma rule wrap everything below it as children diff --git a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid index ebd4119a5..3585564a9 100644 --- a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid +++ b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid @@ -2,14 +2,14 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/FunctionDefinition type: text/vnd.tiddlywiki -\function name(param:defaultvalue,param2:defaultvalue) +\function name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\procedure name(param:defaultvalue,param2:defaultvalue) +\procedure name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\widget $mywidget(param:defaultvalue,param2:defaultvalue) +\widget $mywidget(param:"defaultvalue", param2:"defaultvalue") definition text \end \ No newline at end of file From 7c6c0c30e01001dd9bebbff5ae488117fca8a522 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 23 Mar 2025 01:26:38 +0800 Subject: [PATCH 76/76] Update void.js --- core/modules/widgets/void.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js index d2b6445a7..2f73db513 100755 --- a/core/modules/widgets/void.js +++ b/core/modules/widgets/void.js @@ -6,10 +6,7 @@ module-type: widget Void widget that is not intended for render. It still renders all its children. \*/ -(function(){ -/*jslint node: true, browser: true */ -/*global $tw: false */ "use strict"; var Widget = require("$:/core/modules/widgets/widget.js").widget; @@ -50,5 +47,3 @@ VoidNodeWidget.prototype.refresh = function(changedTiddlers) { }; exports.void = VoidNodeWidget; - -})();