diff --git a/core/modules/filters.js b/core/modules/filters.js index e0a2779e3..5f4eb6492 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -244,13 +244,15 @@ exports.compileFilter = function(filterString) { var operands = [], operatorFunction; if(!operator.operator) { + // Use the "title" operator if no operator is specified operatorFunction = filterOperators.title; } else if(!filterOperators[operator.operator]) { - operatorFunction = filterOperators.field; + // Unknown operators treated as "unknown" - at run time we can distinguish between a custom operator and falling back to the default "field" operator + operatorFunction = filterOperators.unknown; } else { + // Use the operator function operatorFunction = filterOperators[operator.operator]; } - $tw.utils.each(operator.operands,function(operand) { if(operand.indirect) { operand.value = self.getTextReference(operand.text,"",currTiddlerTitle); diff --git a/core/modules/filters/unknown.js b/core/modules/filters/unknown.js new file mode 100644 index 000000000..93b42c706 --- /dev/null +++ b/core/modules/filters/unknown.js @@ -0,0 +1,59 @@ +/*\ +title: $:/core/modules/filters/unknown.js +type: application/javascript +module-type: filteroperator + +Filter operator for handling unknown filter operators + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var fieldFilterOperatorFn = require("$:/core/modules/filters/field.js").field; + +/* +Export our filter function +*/ +exports.unknown = function(source,operator,options) { + var customDefinitionTitle = "[" + operator.operator + "[]]", + customDefinition = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(customDefinitionTitle); + if(customDefinition && customDefinition.srcVariable) { + var variables = Object.create(null); + $tw.utils.each(customDefinition.srcVariable.variableParams,function(param,index) { + var value = operator.operands[index]; + if(value === undefined) { + value = param["default"] || ""; + } + variables[param.name] = value; + }); + var getVariable = function(name,opts) { + if(name in variables) { + return variables[name]; + } else { + return options.widget.getVariable(name,opts); + }; + }; + var getVariableInfo = function(name,opts) { + return options.widget.getVariableInfo(name,opts); + } + var list = options.wiki.filterTiddlers(customDefinition.srcVariable.value,{getVariable: getVariable,getVariableInfo: getVariableInfo},source); + if(operator.prefix === "!") { + var results = []; + source(function(tiddler,title) { + if(list.indexOf(title) === -1) { + results.push(title); + } + }); + return results; + } else { + return list; + } + } else { + return fieldFilterOperatorFn(source,operator,options); + } +}; + +})(); diff --git a/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid new file mode 100644 index 000000000..cbeb1570d --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid @@ -0,0 +1,24 @@ +title: CustomOperators/NestedParameterised +description: Nested parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function [dividebysomething[]](first:ignored,factor:0.5) +[divide[2]multiply] +\end + +\function [multiplebysomething[]](first:ignored,factor:2) +[multiply[2]dividebysomething[],] +\end + +<$text text={{{ [[123]multiplebysomething[]] }}}/> +- +<$text text={{{ [[123]multiplebysomething[x],[4]] }}}/> + ++ +title: ExpectedResult + +

246-492

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid new file mode 100644 index 000000000..42ca40ec6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid @@ -0,0 +1,20 @@ +title: CustomOperators/Parameterised +description: Parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function [multiplybysomething[]](first:ignored,factor:2) +[multiply[2]multiply] +\end + +<$text text={{{ [[123]multiplybysomething[]] }}}/> +- +<$text text={{{ [[123]multiplybysomething[x],[4]] }}}/> + ++ +title: ExpectedResult + +

492-984

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Simple.tid b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid new file mode 100644 index 000000000..076a54dad --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid @@ -0,0 +1,16 @@ +title: CustomOperators/Simple +description: Simple custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\function [multiplybytwo[]]() +[multiply[2]] +\end + +<$text text={{{ [[123]multiplybytwo[]] }}}/> ++ +title: ExpectedResult + +

246

\ No newline at end of file