mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-24 02:27:19 +00:00
Add wikitext shortcut for new-style function definitions
This commit is contained in:
parent
886c8620f5
commit
c9bd1b5274
93
core/modules/parsers/wikiparser/rules/functiondef.js
Normal file
93
core/modules/parsers/wikiparser/rules/functiondef.js
Normal file
@ -0,0 +1,93 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/functiondef.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki pragma rule for function definitions
|
||||
|
||||
```
|
||||
\function name(param:defaultvalue,param2:defaultvalue)
|
||||
definition text
|
||||
\end
|
||||
```
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "functiondef";
|
||||
exports.types = {pragma: true};
|
||||
|
||||
/*
|
||||
Instantiate parse rule
|
||||
*/
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /^\\function\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[2],
|
||||
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];
|
||||
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[3]) {
|
||||
// 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
|
||||
return [{
|
||||
type: "set",
|
||||
attributes: {
|
||||
name: {type: "string", value: this.match[1]},
|
||||
value: {type: "string", value: text}
|
||||
},
|
||||
children: [],
|
||||
variableParams: params,
|
||||
isFunctionDefinition: true
|
||||
}];
|
||||
};
|
||||
|
||||
})();
|
||||
|
@ -48,7 +48,13 @@ SetWidget.prototype.execute = function() {
|
||||
this.setValue = this.getAttribute("value");
|
||||
this.setEmptyValue = this.getAttribute("emptyValue");
|
||||
// Set context variable
|
||||
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);
|
||||
if(this.parseTreeNode.isMacroDefinition) {
|
||||
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);
|
||||
} else if(this.parseTreeNode.isFunctionDefinition) {
|
||||
this.setVariable(this.setName,this.getValue(),undefined,undefined,{isFunctionDefinition: this.parseTreeNode.isFunctionDefinition,variableParams: this.parseTreeNode.variableParams});
|
||||
} else {
|
||||
this.setVariable(this.setName,this.getValue());
|
||||
}
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
const { parse } = require("../parsers/wikiparser/rules/transcludeinline");
|
||||
|
||||
/*\
|
||||
title: $:/core/modules/widgets/transclude.js
|
||||
type: application/javascript
|
||||
@ -169,7 +171,26 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
|
||||
}
|
||||
var parser;
|
||||
if(this.transcludeVariable) {
|
||||
parser = this.wiki.parseText(this.transcludeType,this.getVariable(this.transcludeVariable,""),{parseAsInline: !this.parseTreeNode.isBlock});
|
||||
var variableInfo = this.getVariableInfo(this.transcludeVariable).srcVariable;
|
||||
parser = this.wiki.parseText(this.transcludeType,variableInfo.value || "",{parseAsInline: !this.parseTreeNode.isBlock});
|
||||
if(parser && variableInfo.isFunctionDefinition) {
|
||||
parser = {
|
||||
tree: [
|
||||
{
|
||||
type: "parameters",
|
||||
name: "$parameters",
|
||||
children: parser.tree,
|
||||
attributes: {},
|
||||
orderedAttributes: []
|
||||
}
|
||||
]
|
||||
}
|
||||
$tw.utils.each(variableInfo.variableParams,function(param,index) {
|
||||
var attr = {name: param.name, type: "string", value: param["default"]};
|
||||
parser.tree[0].attributes[param.name] = attr;
|
||||
parser.tree[0].orderedAttributes.push(attr);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
parser = this.wiki.parseTextReference(
|
||||
this.transcludeTitle,
|
||||
|
@ -88,9 +88,19 @@ name: name of the variable
|
||||
value: value of the variable
|
||||
params: array of {name:, default:} for each parameter
|
||||
isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed)
|
||||
options includes:
|
||||
isFunctionDefinition: true if the variable is set via a \function pragma (and hence should not have variable substitution performed)
|
||||
variableParams: array of {name:, default:} for each function parameter
|
||||
*/
|
||||
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition) {
|
||||
this.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition};
|
||||
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) {
|
||||
options = options || {};
|
||||
this.variables[name] = {
|
||||
value: value,
|
||||
params: params,
|
||||
isMacroDefinition: !!isMacroDefinition,
|
||||
isFunctionDefinition: !!options.isFunctionDefinition,
|
||||
variableParams: options.variableParams
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -0,0 +1,18 @@
|
||||
title: Transclude/Parameterised/Shortcut
|
||||
description: Simple parameterised transclusion
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
tags: [[$:/tags/wiki-test-spec]]
|
||||
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
\function test(one:'Jaguar')
|
||||
{<$text text=<<one>>/>}
|
||||
\end
|
||||
|
||||
<$transclude $variable='test' one='Ferret'/>
|
||||
<$transclude $variable='test'/>
|
||||
_
|
||||
title: ExpectedResult
|
||||
|
||||
<p>{Ferret}{Jaguar}</p>
|
@ -119,10 +119,26 @@ describe("WikiText parser tests", function() {
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse function definitions", function() {
|
||||
expect(parse("\\function myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual(
|
||||
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], variableParams : [ { name: 'one' }, { name: 'two' }, { name: 'three' }, { name: 'four', default: 'elephant' } ], isFunctionDefinition : true } ]
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse function definitions", function() {
|
||||
expect(parse("\\function myMacro(one:'Jaguar')\n<$text text=<<one>>/>\n\\end\n\n")).toEqual(
|
||||
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : '<$text text=<<one>>/>' } }, children : [ ], variableParams : [ { name: 'one', "default": 'Jaguar' } ], isFunctionDefinition : true } ]
|
||||
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse comment in pragma area. Comment will be invisible", function() {
|
||||
expect(parse("<!-- comment in pragma area -->\n\\define aMacro()\nnothing\n\\end\n")).toEqual(
|
||||
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'aMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ]
|
||||
[ { type : 'set', attributes : { name : { type : 'string', value : 'aMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ]
|
||||
|
||||
);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user