Allow custom functions to be invoked as attributes

This commit is contained in:
jeremy@jermolene.com 2022-05-23 20:18:54 +01:00
parent 9e8d05f699
commit cbce4ebb7b
3 changed files with 69 additions and 20 deletions

View File

@ -24,30 +24,15 @@ exports["[unknown]"] = function(source,operator,options) {
var customDefinition = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator);
if(customDefinition && customDefinition.srcVariable && customDefinition.srcVariable.isFunctionDefinition) {
var variables = Object.create(null);
// Go through each of the defined parameters, and make a variable with the value of the corresponding operand
$tw.utils.each(customDefinition.srcVariable.params,function(param,index) {
var value = operator.operands[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) {
if(name in variables) {
return {
text: variables[name]
};
} else {
return options.widget.getVariableInfo(name,opts);
};
}
var list = options.wiki.filterTiddlers(customDefinition.srcVariable.value,{getVariable: getVariable,getVariableInfo: getVariableInfo},source);
var list = options.wiki.filterTiddlers(customDefinition.srcVariable.value,options.widget.makeFakeWidgetWithVariables(variables),source);
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {

View File

@ -275,6 +275,32 @@ Widget.prototype.getStateQualifier = function(name) {
}
};
/*
Make a fake widget with specified variables, suitable for variable lookup in filters
*/
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
var self = this;
return {
getVariable: function(name,opts) {
if(name in variables) {
return variables[name];
} else {
return self.getVariable(name,opts);
};
},
getVariableInfo: function(name,opts) {
if(name in variables) {
return {
text: variables[name]
};
} else {
return self.getVariableInfo(name,opts);
};
},
makeFakeWidgetWithVariables: self.makeFakeWidgetWithVariables
};
};
/*
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed.
Options include:
@ -300,13 +326,27 @@ Widget.prototype.computeAttributes = function(options) {
};
Widget.prototype.computeAttribute = function(attribute) {
var value;
var self = this,
value;
if(attribute.type === "filtered") {
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
} else if(attribute.type === "indirect") {
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
} else if(attribute.type === "macro") {
value = this.getVariable(attribute.value.name,{params: attribute.value.params});
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// It's a function definition
var variables = Object.create(null);
// Go through each of the defined parameters, and make a variable with the value of the corresponding provided parameter
var params = this.resolveVariableParameters(variableInfo.srcVariable.params,attribute.value.params);
$tw.utils.each(params,function(param,index) {
variables[param.name] = param.value;
});
var list = self.wiki.filterTiddlers(variableInfo.text,this.makeFakeWidgetWithVariables(variables));
value = list[0] || "";
} else {
value = variableInfo.text;
}
} else { // String attribute
value = attribute.value;
}

View File

@ -0,0 +1,24 @@
title: Functions/FunctionAttributes
description: Attributes specified as function invocations
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\function .dividebysomething(factor:0.5)
[divide<factor>]
\end
\function multiplebysomething(first:ignored,factor:2)
[<factor>multiply[2].dividebysomething[0.25]]
\end
<$text text=<<multiplebysomething>>/>
|
<$text text=<<multiplebysomething "nothing" "4">>/>
+
title: ExpectedResult
<p>16|32</p>