mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-10-30 15:13:00 +00:00
Extend transclude widget to work with old-style macros and use it for the macrocall shortcut syntax
This commit is contained in:
@@ -175,7 +175,36 @@ exports.parseMacroParameter = function(source,pos) {
|
||||
};
|
||||
|
||||
/*
|
||||
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
|
||||
Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:}
|
||||
*/
|
||||
exports.parseMacroInvocationAsTransclusion = function(source,pos) {
|
||||
var node = $tw.utils.parseMacroInvocation(source,pos);
|
||||
if(node) {
|
||||
var positionalName = 0,
|
||||
transclusion = {
|
||||
type: "transclude",
|
||||
start: node.start,
|
||||
end: node.end
|
||||
};
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name);
|
||||
$tw.utils.each(node.params,function(param) {
|
||||
var name = param.name;
|
||||
if(name) {
|
||||
if(name.charAt(0) === "$") {
|
||||
name = "$" + name;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end});
|
||||
} else {
|
||||
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end});
|
||||
}
|
||||
});
|
||||
return transclusion;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
/*
|
||||
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, params:, start:, end:}
|
||||
*/
|
||||
exports.parseMacroInvocation = function(source,pos) {
|
||||
var node = {
|
||||
|
||||
@@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) {
|
||||
var nextStart = startPos;
|
||||
// Try parsing at all possible macrocall openers until we match
|
||||
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
|
||||
var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
|
||||
var nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
|
||||
if(nextCall) {
|
||||
var c = this.parser.source.charAt(nextCall.end);
|
||||
// Ensure EOL after parsed macro
|
||||
|
||||
@@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) {
|
||||
var nextStart = startPos;
|
||||
// Try parsing at all possible macrocall openers until we match
|
||||
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
|
||||
this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
|
||||
this.nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
|
||||
if(this.nextCall) {
|
||||
return nextStart;
|
||||
}
|
||||
|
||||
@@ -166,27 +166,45 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
|
||||
}
|
||||
var parser;
|
||||
if(this.transcludeVariable) {
|
||||
var variableInfo = this.getVariableInfo(this.transcludeVariable).srcVariable;
|
||||
if(variableInfo) {
|
||||
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
|
||||
srcVariable = variableInfo.srcVariable;
|
||||
if(srcVariable) {
|
||||
var mode = parseAsInline ? "inlineParser" : "blockParser";
|
||||
if(variableInfo[mode]) {
|
||||
parser = variableInfo[mode];
|
||||
if(srcVariable.isCacheable && srcVariable[mode]) {
|
||||
parser = srcVariable[mode];
|
||||
} else {
|
||||
parser = this.wiki.parseText(this.transcludeType,variableInfo.value || "",{parseAsInline: parseAsInline});
|
||||
variableInfo[mode] = parser;
|
||||
}
|
||||
if(parser && variableInfo.isFunctionDefinition) {
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "parameters",
|
||||
children: parser.tree
|
||||
}
|
||||
]
|
||||
parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline});
|
||||
if(srcVariable.isCacheable) {
|
||||
srcVariable[mode] = parser;
|
||||
}
|
||||
}
|
||||
if(parser) {
|
||||
if(srcVariable.isFunctionDefinition) {
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "parameters",
|
||||
children: parser.tree
|
||||
}
|
||||
]
|
||||
}
|
||||
$tw.utils.each(srcVariable.params,function(param) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],param.name,param["default"])
|
||||
});
|
||||
} else if(srcVariable.isMacroDefinition) {
|
||||
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "vars",
|
||||
children: parser.tree
|
||||
}
|
||||
]
|
||||
}
|
||||
$tw.utils.each(variableInfo.params,function(param) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
|
||||
});
|
||||
}
|
||||
$tw.utils.each(variableInfo.params,function(param) {
|
||||
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],param.name,param["default"])
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -218,6 +236,39 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all the string parameters as an ordered array of {name:, value:} where the name is optional
|
||||
*/
|
||||
TranscludeWidget.prototype.getOrderedTransclusionParameters = function() {
|
||||
var result = [];
|
||||
// Collect the parameters
|
||||
for(var name in this.stringParametersByName) {
|
||||
var value = this.stringParametersByName[name];
|
||||
result.push({name: name, value: value});
|
||||
}
|
||||
// Sort numerical parameter names first
|
||||
result.sort(function(a,b) {
|
||||
var aIsNumeric = !isNaN(a.name),
|
||||
bIsNumeric = !isNaN(b.name);
|
||||
if(aIsNumeric && bIsNumeric) {
|
||||
return a.name - b.name;
|
||||
} else if(aIsNumeric) {
|
||||
return -1;
|
||||
} else if(bIsNumeric) {
|
||||
return 1;
|
||||
} else {
|
||||
return a.name === b.name ? 0 : (a.name < b.name ? -1 : 1);
|
||||
}
|
||||
});
|
||||
// Remove names from numerical parameters
|
||||
$tw.utils.each(result,function(param,index) {
|
||||
if(!isNaN(param.name)) {
|
||||
delete param.name;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch the value of a parameter
|
||||
*/
|
||||
|
||||
@@ -122,14 +122,14 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
||||
if(parentWidget && name in parentWidget.variables) {
|
||||
var variable = parentWidget.variables[name],
|
||||
originalValue = variable.value,
|
||||
value = originalValue,
|
||||
params = this.resolveVariableParameters(variable.params,actualParams);
|
||||
// Substitute any parameters specified in the definition
|
||||
$tw.utils.each(params,function(param) {
|
||||
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
|
||||
});
|
||||
// Only substitute variable references if this variable was defined with the \define pragma
|
||||
value = originalValue;
|
||||
// Only substitute parameter and variable references if this variable was defined with the \define pragma
|
||||
if(variable.isMacroDefinition) {
|
||||
var params = this.resolveVariableParameters(variable.params,actualParams);
|
||||
// Substitute any parameters specified in the definition
|
||||
$tw.utils.each(params,function(param) {
|
||||
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
|
||||
});
|
||||
value = this.substituteVariableReferences(value,options);
|
||||
}
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user