From 48e6863a89909dce188d225cefc0684747721c11 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Mon, 12 May 2025 17:16:08 +0100 Subject: [PATCH] Parse attribute macros with the new parser This fixes the tests --- core/modules/parsers/parseutils.js | 5 +- core/modules/widgets/widget.js | 16 +- .../test/tiddlers/tests/test-html-parser.js | 278 +++++++++++++++++- .../tiddlers/tests/test-wikitext-parser.js | 8 +- 4 files changed, 297 insertions(+), 10 deletions(-) diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index e20f464558..73eefa7d90 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -214,7 +214,7 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) { orderedAttributes: [] }; // Define our regexps - var reVarName = /([a-zA-Z0-9\-\$\._<]+)/g; + var reVarName = /([^\s>"'=:]+)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for a double opening angle bracket @@ -260,6 +260,7 @@ exports.parseMacroParametersAsAttributes = function(node,source,pos) { while(attribute) { if(!attribute.name) { attribute.name = (position++) + ""; + attribute.isPositional = true; } node.orderedAttributes.push(attribute); node.attributes[attribute.name] = attribute; @@ -485,7 +486,7 @@ exports.parseAttribute = function(source,pos) { node.value = unquotedValue.match[1]; } else { // Look for a macro invocation value - var macroInvocation = $tw.utils.parseMacroInvocation(source,pos); + var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos); if(macroInvocation) { pos = macroInvocation.end; node.type = "macro"; diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index b89df34b7c..c53ffbce37 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -374,7 +374,21 @@ Widget.prototype.computeAttribute = function(attribute) { } else if(attribute.type === "indirect") { value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler")) || ""; } else if(attribute.type === "macro") { - var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params}); + // Get the macro name + var macroName = attribute.value.attributes["$variable"].value; + // Collect macro parameters + var params = []; + $tw.utils.each(attribute.value.orderedAttributes,function(attr) { + var param = { + value: self.computeAttribute(attr) + }; + if(attr.name && !attr.isPositional) { + param.name = attr.name; + } + params.push(param); + }); + // Invoke the macro + var variableInfo = this.getVariableInfo(macroName,{params: params}); value = variableInfo.text; } else if(attribute.type === "substituted") { value = this.wiki.getSubstitutedText(attribute.rawValue,this) || ""; diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index 9fc1082358..911dcb825d 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -204,11 +204,283 @@ describe("HTML tag new parser tests", function() { 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 } + expect(parser.parseTag("<$mytag attrib3=<>>", 0)).toEqual( + { + "type": "mytag", + "start": 0, + "attributes": { + "attrib3": { + "start": 7, + "name": "attrib3", + "type": "macro", + "value": { + "type": "transclude", + "start": 16, + "attributes": { + "$variable": { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + "one": { + "start": 25, + "name": "one", + "type": "string", + "value": "two", + "end": 33 + }, + "three": { + "start": 33, + "name": "three", + "type": "string", + "value": "four and five", + "end": 55 + } + }, + "orderedAttributes": [ + { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + { + "start": 25, + "name": "one", + "type": "string", + "value": "two", + "end": 33 + }, + { + "start": 33, + "name": "three", + "type": "string", + "value": "four and five", + "end": 55 + } + ], + "end": 57 + }, + "end": 57 + } + }, + "orderedAttributes": [ + { + "start": 7, + "name": "attrib3", + "type": "macro", + "value": { + "type": "transclude", + "start": 16, + "attributes": { + "$variable": { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + "one": { + "start": 25, + "name": "one", + "type": "string", + "value": "two", + "end": 33 + }, + "three": { + "start": 33, + "name": "three", + "type": "string", + "value": "four and five", + "end": 55 + } + }, + "orderedAttributes": [ + { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + { + "start": 25, + "name": "one", + "type": "string", + "value": "two", + "end": 33 + }, + { + "start": 33, + "name": "three", + "type": "string", + "value": "four and five", + "end": 55 + } + ], + "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": { + "start": 7, + "name": "attrib1", + "type": "string", + "value": "something", + "end": 27 + }, + "attrib2": { + "start": 27, + "name": "attrib2", + "type": "string", + "value": "else", + "end": 40 + }, + "thing": { + "start": 40, + "name": "thing", + "type": "string", + "value": "true", + "end": 47 + }, + "attrib3": { + "start": 47, + "name": "attrib3", + "type": "macro", + "value": { + "type": "transclude", + "start": 55, + "attributes": { + "$variable": { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + "one": { + "start": 64, + "name": "one", + "type": "string", + "value": "two", + "end": 72 + }, + "three": { + "start": 72, + "name": "three", + "type": "string", + "value": "four and five", + "end": 94 + } + }, + "orderedAttributes": [ + { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + { + "start": 64, + "name": "one", + "type": "string", + "value": "two", + "end": 72 + }, + { + "start": 72, + "name": "three", + "type": "string", + "value": "four and five", + "end": 94 + } + ], + "end": 96 + }, + "end": 96 + } + }, + "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": 47 + }, + { + "start": 47, + "name": "attrib3", + "type": "macro", + "value": { + "type": "transclude", + "start": 55, + "attributes": { + "$variable": { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + "one": { + "start": 64, + "name": "one", + "type": "string", + "value": "two", + "end": 72 + }, + "three": { + "start": 72, + "name": "three", + "type": "string", + "value": "four and five", + "end": 94 + } + }, + "orderedAttributes": [ + { + "name": "$variable", + "type": "string", + "value": "myMacro" + }, + { + "start": 64, + "name": "one", + "type": "string", + "value": "two", + "end": 72 + }, + { + "start": 72, + "name": "three", + "type": "string", + "value": "four and five", + "end": 94 + } + ], + "end": 96 + }, + "end": 96 + } + ], + "tag": "$mytag", + "end": 97 + } ); }); diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index c35ad1dce7..b80c5d1a37 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -281,23 +281,23 @@ describe("WikiText parser tests", function() { it("should parse tricky macrocall parameters", function() { expect(parse("<am>>")).toEqual( - [{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12}],"isBlock":true,"rule":"macrocallblock"}] + [{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}] ); expect(parse("< >>")).toEqual( - [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13}],"isBlock":true,"rule":"macrocallblock"}] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}] ); 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","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12,"isPositional":true}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed expect(parse("<=4 >>")).toEqual( - [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13}],"isBlock":true,"rule":"macrocallblock"}] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13,"isPositional":true},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13,"isPositional":true}],"isBlock":true,"rule":"macrocallblock"}] );