From bfd116a438a61f790928e77a4cbb8a079c75ccfa Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 2 Aug 2024 22:54:45 +0800 Subject: [PATCH] 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()); + }); });