mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-08-25 11:06:45 +00:00
![Jeremy Ruston](/assets/img/avatar_default.png)
We now use a fake DOM implementation on the server to let us share more rendering code between the text output vs. DOM output paths.
90 lines
3.0 KiB
JavaScript
90 lines
3.0 KiB
JavaScript
/*\
|
|
title: $:/core/modules/rendertree/renderers/macrocall.js
|
|
type: application/javascript
|
|
module-type: wikirenderer
|
|
|
|
Macro call renderer
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
/*global $tw: false */
|
|
"use strict";
|
|
|
|
/*
|
|
Macro call renderer
|
|
*/
|
|
var MacroCallRenderer = function(renderTree,parentRenderer,parseTreeNode) {
|
|
// Store state information
|
|
this.renderTree = renderTree;
|
|
this.parentRenderer = parentRenderer;
|
|
this.parseTreeNode = parseTreeNode;
|
|
// Find the macro definition
|
|
var macro = this.renderTree.findMacroDefinition(this.parentRenderer,this.parseTreeNode.name);
|
|
// Insert an error message if we couldn't find the macro
|
|
var childTree;
|
|
if(!macro) {
|
|
childTree = [{type: "text", text: "<<Undefined macro: " + this.parseTreeNode.name + ">>"}];
|
|
} else {
|
|
// Substitute the macro parameters
|
|
var text = this.substituteParameters(macro.text,this.parseTreeNode,macro);
|
|
// Parse the text
|
|
childTree = this.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.parseTreeNode.isBlock}).tree;
|
|
}
|
|
// Create the renderers for the child nodes
|
|
this.children = this.renderTree.createRenderers(this,childTree);
|
|
};
|
|
|
|
/*
|
|
Expand the parameters in a block of text
|
|
*/
|
|
MacroCallRenderer.prototype.substituteParameters = function(text,macroCallParseTreeNode,macroDefinition) {
|
|
var nextAnonParameter = 0; // Next candidate anonymous parameter in macro call
|
|
// Step through each of the parameters in the macro definition
|
|
for(var p=0; p<macroDefinition.params.length; p++) {
|
|
// Check if we've got a macro call parameter with the same name
|
|
var paramInfo = macroDefinition.params[p],
|
|
paramValue = undefined;
|
|
for(var m=0; m<macroCallParseTreeNode.params.length; m++) {
|
|
if(macroCallParseTreeNode.params[m].name === paramInfo.name) {
|
|
paramValue = macroCallParseTreeNode.params[m].value;
|
|
}
|
|
}
|
|
// If not, use the next available anonymous macro call parameter
|
|
if(!paramValue && macroCallParseTreeNode.params.length > 0) {
|
|
while(macroCallParseTreeNode.params[nextAnonParameter].name && nextAnonParameter < macroCallParseTreeNode.params.length-1) {
|
|
nextAnonParameter++;
|
|
}
|
|
if(!macroCallParseTreeNode.params[nextAnonParameter].name) {
|
|
paramValue = macroCallParseTreeNode.params[nextAnonParameter].value;
|
|
nextAnonParameter++;
|
|
}
|
|
}
|
|
// If we've still not got a value, use the default, if any
|
|
paramValue = paramValue || paramInfo["default"] || "";
|
|
// Replace any instances of this parameter
|
|
text = text.replace(new RegExp("\\$" + $tw.utils.escapeRegExp(paramInfo.name) + "\\$","mg"),paramValue);
|
|
}
|
|
return text;
|
|
};
|
|
|
|
MacroCallRenderer.prototype.renderInDom = function() {
|
|
// Create the element
|
|
this.domNode = this.renderTree.document.createElement(this.parseTreeNode.isBlock ? "div" : "span");
|
|
this.domNode.setAttribute("data-macro-name",this.parseTreeNode.name);
|
|
// Render any child nodes
|
|
var self = this;
|
|
$tw.utils.each(this.children,function(node,index) {
|
|
if(node.renderInDom) {
|
|
self.domNode.appendChild(node.renderInDom());
|
|
}
|
|
});
|
|
// Return the dom node
|
|
return this.domNode;
|
|
};
|
|
|
|
exports.macrocall = MacroCallRenderer
|
|
|
|
})();
|