1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-08-05 21:33:52 +00:00

Added skeleton support for evaluated macro parameters

This commit is contained in:
Jeremy Ruston 2011-12-21 16:54:51 +00:00
parent 02a2630dd6
commit 4c11503bae
6 changed files with 121 additions and 40 deletions

View File

@ -14,7 +14,11 @@ Options and their defaults are:
defaultName: null, defaultName: null,
defaultValue: null, defaultValue: null,
noNames: false, noNames: false,
cascadeDefaults: false cascadeDefaults: false,
allowEval: true
globals: null
`globals` is the global variable object provided to evaluated parameters
\*/ \*/
(function(){ (function(){
@ -22,23 +26,26 @@ Options and their defaults are:
/*jslint node: true */ /*jslint node: true */
"use strict"; "use strict";
var Sandbox = require("./Sandbox.js").Sandbox;
var ArgParser = function(argString,options) { var ArgParser = function(argString,options) {
var parseToken = function(match,p) { var parseToken = function(match,p) {
var n; var n;
if(match[p]) // Double quoted if(match[p]) { // Double quoted
n = match[p]; n = match[p];
else if(match[p+1]) // Single quoted } else if(match[p+1]) { // Single quoted
n = match[p+1]; n = match[p+1];
else if(match[p+2]) // Double-square-bracket quoted } else if(match[p+2]) { // Double-square-bracket quoted
n = match[p+2]; n = match[p+2];
else if(match[p+3]) // Double-brace quoted } else if(match[p+3]) { // Double-brace quoted
n = match[p+3]; n = options.allowEval === false ? match[p+3] : Sandbox(match[p+3],options.globals);
else if(match[p+4]) // Unquoted } else if(match[p+4]) { // Unquoted
n = match[p+4]; n = match[p+4];
else if(match[p+5]) // empty quote } else if(match[p+5]) { // empty quote
n = ""; n = "";
return n; }
}; return n;
};
this.byPos = []; this.byPos = [];
var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")", var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")",
sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')", sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')",

53
js/Sandbox.js Normal file
View File

@ -0,0 +1,53 @@
/*\
title: js/Sandbox.js
Execute a fragment of JavaScript in a sandbox
\*/
(function(){
/*jslint node: true */
"use strict";
var uglify = require("uglify-js");
var safeEval = function(e) {
return eval(e);
};
var Sandbox = function(code,globals) {
var globalNames = [],
globalValues = [],
collectGlobals = function(globals) {
if(globals) {
for(var g in globals) {
globalNames.push(g);
globalValues.push(globals[g]);
}
}
};
// Collect the supplied globals
collectGlobals(globals);
// Add the default globals
collectGlobals({
tiddlywiki: "5"
});
// Compose the code
var out = [];
out.push("(function(")
out.push(globalNames.join(","));
out.push(") { return ");
out.push(code);
out.push(";})");
// Parse the code
var tree = uglify.parser.parse(out.join(""));
// XXX: Sanitise the code by checking for references to globals
// Recompile the code
var compiledCode = uglify.uglify.gen_code(tree);
// Execute it
return eval(compiledCode).apply(null,globalValues);
};
exports.Sandbox = Sandbox;
})();

View File

@ -129,7 +129,19 @@ WikiTextRenderer.prototype.executeMacro = function(macroNode,title) {
var macroInfo = WikiTextRenderer.macros[macroNode.name]; var macroInfo = WikiTextRenderer.macros[macroNode.name];
macroNode.output = []; macroNode.output = [];
if(macroInfo) { if(macroInfo) {
macroInfo.handler.call(this,macroNode,title); var args;
if(macroInfo.argOptions) {
var argOptions = {
globals: {
title: title
}
};
for(var g in macroInfo.argOptions) {
argOptions[g] = macroInfo.argOptions[g];
}
args = new ArgParser(macroNode.params,argOptions);
}
macroInfo.handler.call(this,macroNode,args,title);
} else { } else {
macroNode.output.push({type: "text", value: "Unknown macro " + macroNode.name}); macroNode.output.push({type: "text", value: "Unknown macro " + macroNode.name});
} }
@ -139,18 +151,25 @@ WikiTextRenderer.versionTiddlyWiki = "2.6.5";
WikiTextRenderer.macros = { WikiTextRenderer.macros = {
allTags: { allTags: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
br: { br: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
macroNode.output.push({type: "br"}); macroNode.output.push({type: "br"});
} }
}, },
echo: {
argOptions: {defaultName: "anon"},
handler: function(macroNode,args,title) {
var globals = {title: title};
macroNode.output.push({type: "text", value: args.byPos[0].v});
}
},
timeline: { timeline: {
handler: function(macroNode,title) { argOptions: {defaultName:"anon"},
var args = new ArgParser(macroNode.params,{defaultName:"anon"}), handler: function(macroNode,args,title) {
anonByPos = args.getValuesByName("anon",[]), var anonByPos = args.getValuesByName("anon",[]),
field = anonByPos[0] || "modified", field = anonByPos[0] || "modified",
limit = anonByPos[1] || null, limit = anonByPos[1] || null,
dateformat = anonByPos[2] || "DD MMM YYYY", dateformat = anonByPos[2] || "DD MMM YYYY",
@ -214,9 +233,9 @@ WikiTextRenderer.macros = {
} }
}, },
list: { list: {
handler: function(macroNode,title) { argOptions: {defaultName:"type"},
var args = new ArgParser(macroNode.params,{defaultName:"type"}), handler: function(macroNode,args,title) {
type = args.getValueByName("type","all"), var type = args.getValueByName("type","all"),
template = args.getValueByName("template",null), template = args.getValueByName("template",null),
templateType = "text/x-tiddlywiki", templateText = "<<view title link>>", templateType = "text/x-tiddlywiki", templateText = "<<view title link>>",
emptyMessage = args.getValueByName("emptyMessage",null); emptyMessage = args.getValueByName("emptyMessage",null);
@ -275,29 +294,29 @@ WikiTextRenderer.macros = {
} }
}, },
slider: { slider: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
tabs: { tabs: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
tag: { tag: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
tagging: { tagging: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
tags: { tags: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
} }
}, },
tiddler: { tiddler: {
handler: function(macroNode,title) { argOptions: {defaultName:"name",cascadeDefaults:true},
var args = new ArgParser(macroNode.params,{defaultName:"name",cascadeDefaults:true}), handler: function(macroNode,args,title) {
targetTitle = args.getValueByName("name",null), var targetTitle = args.getValueByName("name",null),
withTokens = args.getValuesByName("with",[]), withTokens = args.getValuesByName("with",[]),
tiddler = this.store.getTiddler(targetTitle), tiddler = this.store.getTiddler(targetTitle),
text = this.store.getTiddlerText(targetTitle,""), text = this.store.getTiddlerText(targetTitle,""),
@ -312,22 +331,22 @@ WikiTextRenderer.macros = {
} }
}, },
today: { today: {
handler: function(macroNode,title) { argOptions: {noNames:true},
handler: function(macroNode,args,title) {
var now = new Date(), var now = new Date(),
args = new ArgParser(macroNode.params,{noNames:true}),
value = args.byPos[0] ? utils.formatDateString(now,args.byPos[0].v) : now.toLocaleString(); value = args.byPos[0] ? utils.formatDateString(now,args.byPos[0].v) : now.toLocaleString();
macroNode.output.push({type: "text", value: value}); macroNode.output.push({type: "text", value: value});
} }
}, },
version: { version: {
handler: function(macroNode,title) { handler: function(macroNode,args,title) {
macroNode.output.push({type: "text", value: WikiTextRenderer.versionTiddlyWiki}); macroNode.output.push({type: "text", value: WikiTextRenderer.versionTiddlyWiki});
} }
}, },
view: { view: {
handler: function(macroNode,title) { argOptions: {noNames:true},
var args = new ArgParser(macroNode.params,{noNames:true}), handler: function(macroNode,args,title) {
field = args.byPos[0] ? args.byPos[0].v : null, var field = args.byPos[0] ? args.byPos[0].v : null,
format = args.byPos[1] ? args.byPos[1].v : "text", format = args.byPos[1] ? args.byPos[1].v : "text",
tiddler = this.store.getTiddler(title), tiddler = this.store.getTiddler(title),
value = tiddler ? tiddler.fields[field] : null; value = tiddler ? tiddler.fields[field] : null;

View File

@ -7,7 +7,6 @@
Given the absolute path of a srcModule, and a relative reference to a dstModule, return the fully resolved module name Given the absolute path of a srcModule, and a relative reference to a dstModule, return the fully resolved module name
*/ */
function resolveModuleName(srcModule,dstModule) { function resolveModuleName(srcModule,dstModule) {
console.log("Resolving " + dstModule + " in the context of " + srcModule);
var src = srcModule.split("/"), var src = srcModule.split("/"),
dst = dstModule.split("/"), dst = dstModule.split("/"),
c; c;

View File

@ -8,3 +8,5 @@ TiddlyWiki is a unique [[wiki|WikiWikiWeb]] that people [[love using|Raves]] to
TiddlyWiki is written in [[HTML]], [[CSS]] and JavaScript to run on any reasonably modern [[browser|Browsers]] without needing any ServerSide logic. It allows anyone to create personal SelfContained hypertext documents that can be published to a WebServer, sent by email, stored in a DropBox or kept on a USB thumb drive to make a WikiOnAStick. Because it doesn't need to be installed and configured it makes a great GuerillaWiki. This is revision <<version>> of TiddlyWiki, and is published under an OpenSourceLicense. TiddlyWiki is written in [[HTML]], [[CSS]] and JavaScript to run on any reasonably modern [[browser|Browsers]] without needing any ServerSide logic. It allows anyone to create personal SelfContained hypertext documents that can be published to a WebServer, sent by email, stored in a DropBox or kept on a USB thumb drive to make a WikiOnAStick. Because it doesn't need to be installed and configured it makes a great GuerillaWiki. This is revision <<version>> of TiddlyWiki, and is published under an OpenSourceLicense.
Unlike most wikis, TiddlyWiki doesn't directly support group collaboration; it is a wiki in the sense of elevating linking be a part of the punctuation of writing. You can easily publish a TiddlyWiki you have created by placing the single file on a web server (for instance the homepage hosting provided by many ISPs). If you need full group collaboration features, there are several HostedOptions to choose from. Unlike most wikis, TiddlyWiki doesn't directly support group collaboration; it is a wiki in the sense of elevating linking be a part of the punctuation of writing. You can easily publish a TiddlyWiki you have created by placing the single file on a web server (for instance the homepage hosting provided by many ISPs). If you need full group collaboration features, there are several HostedOptions to choose from.
<<echo {{2+2 /* something */ - 3 * 17 + title + tiddlywiki + out.length}}>>

View File

@ -9,6 +9,7 @@ recipe: tiddlers/split.recipe
jslib: ../test/tiddlywiki.2.6.5/source/tiddlywiki/jquery/jquery.js jslib: ../test/tiddlywiki.2.6.5/source/tiddlywiki/jquery/jquery.js
jsmodule: ../js/Sandbox.js
jsmodule: ../js/ArgParser.js jsmodule: ../js/ArgParser.js
jsmodule: ../js/FileRetriever.js jsmodule: ../js/FileRetriever.js
jsmodule: ../js/Utils.js jsmodule: ../js/Utils.js