mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-30 21:39:57 +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.setValue = this.getAttribute("value");
|
||||||
this.setEmptyValue = this.getAttribute("emptyValue");
|
this.setEmptyValue = this.getAttribute("emptyValue");
|
||||||
// Set context variable
|
// Set context variable
|
||||||
|
if(this.parseTreeNode.isMacroDefinition) {
|
||||||
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!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
|
// Construct the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
const { parse } = require("../parsers/wikiparser/rules/transcludeinline");
|
||||||
|
|
||||||
/*\
|
/*\
|
||||||
title: $:/core/modules/widgets/transclude.js
|
title: $:/core/modules/widgets/transclude.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
@ -169,7 +171,26 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
|
|||||||
}
|
}
|
||||||
var parser;
|
var parser;
|
||||||
if(this.transcludeVariable) {
|
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 {
|
} else {
|
||||||
parser = this.wiki.parseTextReference(
|
parser = this.wiki.parseTextReference(
|
||||||
this.transcludeTitle,
|
this.transcludeTitle,
|
||||||
|
@ -88,9 +88,19 @@ name: name of the variable
|
|||||||
value: value of the variable
|
value: value of the variable
|
||||||
params: array of {name:, default:} for each parameter
|
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)
|
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) {
|
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) {
|
||||||
this.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition};
|
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,6 +119,22 @@ 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() {
|
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(
|
expect(parse("<!-- comment in pragma area -->\n\\define aMacro()\nnothing\n\\end\n")).toEqual(
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user