Parse attribute macros with the new parser

This fixes the tests
This commit is contained in:
Jeremy Ruston 2025-05-12 17:16:08 +01:00
parent f5d5a23aff
commit 48e6863a89
4 changed files with 297 additions and 10 deletions

View file

@ -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";

View file

@ -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) || "";

View file

@ -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=<<myMacro one:two three:'four and five'>>>",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=<<myMacro one:two three:'four and five'>>>", 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=<<myMacro one:two three:'four and five'>>>",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
}
);
});

View file

@ -281,23 +281,23 @@ describe("WikiText parser tests", function() {
it("should parse tricky macrocall parameters", function() {
expect(parse("<<john pa>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("<<john param> >>")).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("<<john param>>>")).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("<<john var>=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"}]
);