diff --git a/core/modules/filters.js b/core/modules/filters.js index a5e02b543..06fa603b5 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -253,7 +253,8 @@ exports.compileFilter = function(filterString) { if(operand.indirect) { operand.value = self.getTextReference(operand.text,"",currTiddlerTitle); } else if(operand.variable) { - operand.value = widget.getVariable(operand.text,{defaultValue: ""}); + var varTree = $tw.utils.parseFilterVariable(operand.text); + operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""}); } else { operand.value = operand.text; } diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 8d83efd1b..0743229c2 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -123,6 +123,19 @@ exports.parseStringLiteral = function(source,pos) { } }; +exports.parseMacroParameters = function(node,source,pos) { + // Process parameters + var parameter = $tw.utils.parseMacroParameter(source,pos); + while(parameter) { + node.params.push(parameter); + pos = parameter.end; + // Get the next parameter + parameter = $tw.utils.parseMacroParameter(source,pos); + } + node.end = pos; + return node; +} + /* Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:} */ @@ -187,14 +200,8 @@ exports.parseMacroInvocation = function(source,pos) { } node.name = name.match[1]; pos = name.end; - // Process parameters - var parameter = $tw.utils.parseMacroParameter(source,pos); - while(parameter) { - node.params.push(parameter); - pos = parameter.end; - // Get the next parameter - parameter = $tw.utils.parseMacroParameter(source,pos); - } + node = $tw.utils.parseMacroParameters(node,source,pos); + pos = node.end; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for a double greater than sign @@ -208,6 +215,29 @@ exports.parseMacroInvocation = function(source,pos) { return node; }; +exports.parseFilterVariable = function(source) { + var node = { + name: "", + params: [], + }, + pos = 0, + reName = /([^\s"']+)/g; + // If there is no whitespace or it is an empty string then there are no macro parameters + if(/^\S*$/.test(source)) { + node.name = source; + return node; + } + // Get the variable name + var nameMatch = $tw.utils.parseTokenRegExp(source,pos,reName); + if(nameMatch) { + node.name = nameMatch.match[1]; + pos = nameMatch.end; + node = $tw.utils.parseMacroParameters(node,source,pos); + delete node.end; + } + return node; +}; + /* Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,} */ diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 9b8c2bd44..34603177b 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -825,6 +825,42 @@ function runTests(wiki) { expect(wiki.filterTiddlers("[charcode[]]").join(" ")).toBe(""); }); + it("should parse filter variable parameters", function(){ + expect($tw.utils.parseFilterVariable("currentTiddler")).toEqual( + { name: 'currentTiddler', params: [ ] } + ); + expect($tw.utils.parseFilterVariable("now DDMM")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', start: 3, value: 'DDMM', end: 8 }] } + ); + expect($tw.utils.parseFilterVariable("now DDMM UTC")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', start: 3, value: 'DDMM', end: 8 }, { type: 'macro-parameter', start: 8, value: 'UTC', end: 12 }] } + ); + expect($tw.utils.parseFilterVariable("now format:DDMM")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', name:'format', start: 3, value: 'DDMM', end: 15 }] } + ); + expect($tw.utils.parseFilterVariable("now format:'DDMM'")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', name:'format', start: 3, value: 'DDMM', end: 17 }] } + ); + expect($tw.utils.parseFilterVariable("nowformat:'DDMM'")).toEqual( + { name: 'nowformat:\'DDMM\'', params: [] } + ); + expect($tw.utils.parseFilterVariable("nowformat:'DD MM'")).toEqual( + { name: 'nowformat:', params: [{ type: 'macro-parameter', start: 10, value: 'DD MM', end: 17 }] } + ); + expect($tw.utils.parseFilterVariable("now [UTC]YYYY0MM0DD0hh0mm0ssXXX")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', start: 3, value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 31 }] } + ); + expect($tw.utils.parseFilterVariable("now '[UTC]YYYY0MM0DD0hh0mm0ssXXX'")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', start: 3, value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 33 }] } + ); + expect($tw.utils.parseFilterVariable("now format:'[UTC]YYYY0MM0DD0hh0mm0ssXXX'")).toEqual( + { name: 'now', params: [{ type: 'macro-parameter', start: 3, name:'format', value: '[UTC]YYYY0MM0DD0hh0mm0ssXXX', end: 40 }] } + ); + expect($tw.utils.parseFilterVariable("")).toEqual( + { name: '', params: [] } + ); + }); + } });