Skip to content

[BUG] Substitute operator does not correctly resolve functions when substituting variables #9188

@saqimtiaz

Description

@saqimtiaz

When substituting a $(varname)$ placeholder using the substitute[] operator, where varname is a function, the function does not have access to variables set in the filter run (currentTiddler, index, etc). Substitutions for filtered expressions work as expected.

This is discrepancy is likely because the wiki.getSubstitutedText method predates functions and just calls widget.getVariable to resolve variable references for substitution:

// Substitute any variable references with their values
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
return widget.getVariable(varname,{defaultValue: ""})
});

Instead we probably want to do something along these lines:

// Substitute any variable references with their values
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
		return widget.evaluateVariable(name, defaultValue: ""})[0];
});

See widget.evaluateVariable:

Widget.evaluateVariable = function(widget,name,options) {
var result;
if(widget.getVariableInfo) {
var variableInfo = widget.getVariableInfo(name,options);
result = variableInfo.resultList || [variableInfo.text];
} else {
result = [widget.getVariable(name)];
}
return result;
};

Questions and concerns:

I am pressed for time at present and have not had the time to consider:

  • Whether we need to take into account variable/function parameters.
    • Do we support parameters for variables being substituted. e.g. $(varname myparam)$ ?
    • We do support string parameters for variables in filters:
      var varTree = $tw.utils.parseFilterVariable(operand.text);
      operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || "";
  • What would be the possible ramifications of adapting widget.getVariable to properly evaluate functions?
  • Are there any repercussions for substituted attributes because of this change?

To reproduce:


\function getIndex() [<index>add[1]] 

\procedure template-with-var() $(getIndex)$

\procedure template-with-filteredexpression() ${ [<getIndex>] }$

\function test-with-substitute-variable()
[[abc]split[]] :map[<template-with-var>substitute[]] :and[join[ / ]]
\end

\function test-with-substitute-filteredexpression()
[[abc]split[]] :map[<template-with-filteredexpression>substitute[]] :and[join[ / ]]
\end

\function test-with-function()
[[abc]split[]] :map[function[getIndex]substitute[]] :and[join[ / ]]
\end


!! Test with substitute (variable)
<<test-with-substitute-variable>>

!! Test with substitute (filtered expression):
<<test-with-substitute-filteredexpression>>

!! Test with function:
<<test-with-function>>

All three test functions should return the same output: 1 / 2 / 3. but test-with-substitute-variable returns 1 / 1 / 1 because the value of index in getIndex is an empty string, i.e. the variable is undefined. (TiddlyWiki v5.3.7)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions