mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-09-17 01:39:42 +00:00
f636349007
The basic idea is that if we don't find a variable `foo` then we fallback to retrieving the value from the tiddler `$:/global/foo`, if it exists. This allows us to replace the usual importvariables-based mechanism for global definitions, avoiding cluttering up the variable namespace with every macro. In order to permit subprocedures to be overridden, we also introduce a mechanism for conditional definitions: preceding the word definition|procedure|function|widget with a + causes the definition only to occur if the specified variable doesn't already exist. In the next commit we'll apply this mechanism to the tabs macro
99 lines
2.6 KiB
JavaScript
99 lines
2.6 KiB
JavaScript
/*\
|
|
title: $:/core/modules/parsers/wikiparser/rules/macrodef.js
|
|
type: application/javascript
|
|
module-type: wikirule
|
|
|
|
Wiki pragma rule for macro definitions
|
|
|
|
```
|
|
\define name(param:defaultvalue,param2:defaultvalue)
|
|
definition text, including $param$ markers
|
|
\end
|
|
```
|
|
|
|
\*/
|
|
(function(){
|
|
|
|
/*jslint node: true, browser: true */
|
|
/*global $tw: false */
|
|
"use strict";
|
|
|
|
exports.name = "macrodef";
|
|
exports.types = {pragma: true};
|
|
|
|
/*
|
|
Instantiate parse rule
|
|
*/
|
|
exports.init = function(parser) {
|
|
this.parser = parser;
|
|
// Regexp to match
|
|
this.matchRegExp = /^\\(\+?)define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg;
|
|
};
|
|
|
|
/*
|
|
Parse the most recent match
|
|
*/
|
|
exports.parse = function() {
|
|
// Move past the macro name and parameters
|
|
this.parser.pos = this.matchRegExp.lastIndex;
|
|
// Parse the parameters
|
|
var paramString = this.match[3],
|
|
params = [];
|
|
if(paramString !== "") {
|
|
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))?/mg,
|
|
paramMatch = reParam.exec(paramString);
|
|
while(paramMatch) {
|
|
// Save the parameter details
|
|
var paramInfo = {name: paramMatch[1]},
|
|
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6];
|
|
if(defaultValue) {
|
|
paramInfo["default"] = defaultValue;
|
|
}
|
|
params.push(paramInfo);
|
|
// Look for the next parameter
|
|
paramMatch = reParam.exec(paramString);
|
|
}
|
|
}
|
|
// Is this a multiline definition?
|
|
var reEnd;
|
|
if(this.match[4]) {
|
|
// If so, the end of the body is marked with \end
|
|
reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg;
|
|
} else {
|
|
// Otherwise, the end of the definition is marked by the end of the line
|
|
reEnd = /($|\r?\n)/mg;
|
|
// Move past any whitespace
|
|
this.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos);
|
|
}
|
|
// Find the end of the definition
|
|
reEnd.lastIndex = this.parser.pos;
|
|
var text,
|
|
endMatch = reEnd.exec(this.parser.source);
|
|
if(endMatch) {
|
|
text = this.parser.source.substring(this.parser.pos,endMatch.index);
|
|
this.parser.pos = endMatch.index + endMatch[0].length;
|
|
} else {
|
|
// We didn't find the end of the definition, so we'll make it blank
|
|
text = "";
|
|
}
|
|
// Save the macro definition
|
|
var parseTreeNodes = [{
|
|
type: "set",
|
|
attributes: {
|
|
name: {type: "string", value: this.match[2]},
|
|
value: {type: "string", value: text}
|
|
},
|
|
children: [],
|
|
params: params,
|
|
isMacroDefinition: true
|
|
}];
|
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[2]);
|
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
|
|
if(this.match[1] === "+") {
|
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"conditional","yes");
|
|
}
|
|
return parseTreeNodes;
|
|
};
|
|
|
|
})();
|