1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-17 10:59:55 +00:00
TiddlyWiki5/core/modules/parsers/wikiparser/rules/fnprocdef.js

111 lines
2.9 KiB
JavaScript

/*\
title: $:/core/modules/parsers/wikiparser/rules/fnprocdef.js
type: application/javascript
module-type: wikirule
Wiki pragma rule for function, procedure and widget definitions
```
\function name(param:defaultvalue,param2:defaultvalue)
definition text
\end
\procedure name(param:defaultvalue,param2:defaultvalue)
definition text
\end
\widget $mywidget(param:defaultvalue,param2:defaultvalue)
definition text
\end
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "fnprocdef";
exports.types = {pragma: true};
/*
Instantiate parse rule
*/
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\(function|procedure|widget)\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[4],
params = [];
if(this.match[3]) {
var reParam = /\s*([^:),\s]+)(?:\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];
if(defaultValue !== undefined) {
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[5]) {
// 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
}];
if(this.match[1] === "function") {
parseTreeNodes[0].isFunctionDefinition = true;
} else if(this.match[1] === "procedure") {
parseTreeNodes[0].isProcedureDefinition = true;
} else if(this.match[1] === "widget") {
parseTreeNodes[0].isWidgetDefinition = true;
}
if(this.parser.configTrimWhiteSpace) {
parseTreeNodes[0].configTrimWhiteSpace = true;
}
return parseTreeNodes;
};
})();