1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-27 03:57:21 +00:00

Cleaned up JavaScript processing

I'm slowly trying to make the JavaScript processing and the WikiText
processing use the same conventions
This commit is contained in:
Jeremy Ruston 2012-01-04 18:31:19 +00:00
parent 5eeb45cd79
commit 3ff1d9a76c
9 changed files with 196 additions and 175 deletions

View File

@ -14,7 +14,7 @@ var WikiStore = require("./WikiStore.js").WikiStore,
tiddlerInput = require("./TiddlerInput.js"), tiddlerInput = require("./TiddlerInput.js"),
tiddlerOutput = require("./TiddlerOutput.js"), tiddlerOutput = require("./TiddlerOutput.js"),
WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor, WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor,
Sandbox = require("./Sandbox.js").Sandbox, JavaScriptParser = require("./JavaScriptParser.js").JavaScriptParser,
Navigators = require("./Navigators.js").Navigators, Navigators = require("./Navigators.js").Navigators,
StoryNavigator = require("./StoryNavigator.js").StoryNavigator; StoryNavigator = require("./StoryNavigator.js").StoryNavigator;
@ -73,11 +73,11 @@ var App = function() {
this.store.addTiddler(new Tiddler(tiddlers[t])); this.store.addTiddler(new Tiddler(tiddlers[t]));
} }
} }
// Set up the sandbox for JavaScript parsing // Set up the JavaScript parser
if(this.isBrowser) { if(this.isBrowser) {
this.store.sandbox = new Sandbox(this.store.getTiddlerText("javascript.pegjs")); this.store.jsParser = new JavaScriptParser(this.store.getTiddlerText("javascript.pegjs"));
} else { } else {
this.store.sandbox = new Sandbox(require("fs").readFileSync("parsers/javascript.pegjs","utf8")); this.store.jsParser = new JavaScriptParser(require("fs").readFileSync("parsers/javascript.pegjs","utf8"));
} }
// Hack to install standard macros // Hack to install standard macros
this.store.installMacros(); this.store.installMacros();

135
js/JavaScriptParseTree.js Normal file
View File

@ -0,0 +1,135 @@
/*\
title: js/JavaScriptParseTree.js
JavaScript parse tree
\*/
(function(){
/*jslint node: true */
"use strict";
var utils = require("./Utils.js");
// Create a new JavaScript tree object
var JavaScriptParseTree = function(tree,processor) {
this.tree = tree;
this.processor = processor;
};
// Render the entire JavaScript tree object to JavaScript source code
JavaScriptParseTree.prototype.render = function() {
this.output = [];
this.renderSubTree(this.tree);
return this.output.join("");
};
JavaScriptParseTree.prototype.renderSubTree = function(tree) {
for(var t=0; t<tree.length; t++) {
if(t) {
this.output.push(";\n");
}
this.renderNode(tree[t]);
}
};
// Compile a javascript tree into an array of string fragments
JavaScriptParseTree.prototype.renderNode = function(node) {
var p;
switch(node.type) {
case "StringLiteral":
this.output.push(utils.stringify(node.value));
break;
case "StringLiterals":
this.output.push(utils.stringify(node.value.join("")));
break;
case "FunctionCall":
this.output.push("(");
this.renderNode(node.name);
this.output.push(")(");
for(p=0; p<node["arguments"].length; p++) {
if(p) {
this.output.push(",");
}
this.renderNode(node["arguments"][p]);
}
this.output.push(")");
break;
case "PropertyAccess":
this.renderNode(node.base);
if(typeof node.name === "string") {
this.output.push("." + node.name);
} else {
this.output.push("[");
this.renderNode(node.name);
this.output.push("]");
}
break;
case "ArrayLiteral":
this.output.push("[");
for(p=0; p<node.elements.length; p++) {
if(p) {
this.output.push(",");
}
this.renderNode(node.elements[p]);
}
this.output.push("]");
break;
case "Variable":
this.output.push(node.name);
break;
case "ObjectLiteral":
this.output.push("{");
for(p=0; p<node.properties.length; p++) {
if(p) {
this.output.push(",");
}
this.renderNode(node.properties[p]);
}
this.output.push("}");
break;
case "PropertyAssignment":
this.output.push(node.name);
this.output.push(":");
this.renderNode(node.value);
break;
case "BinaryExpression":
this.output.push("(");
this.renderNode(node.left);
this.output.push(")");
this.output.push(node.operator);
this.output.push("(");
this.renderNode(node.right);
this.output.push(")");
break;
case "NumericLiteral":
this.output.push(node.value);
break;
case "Function":
this.output.push("(function ");
if(node.name !== null) {
this.output.push(node.name);
}
this.output.push("(");
this.output.push(node.params.join(","));
this.output.push("){");
this.renderSubTree(node.elements);
this.output.push("})");
break;
case "ReturnStatement":
this.output.push("return ");
this.renderNode(node.value);
break;
case "This":
this.output.push("this");
break;
default:
console.log(node);
throw "Unknown JavaScript node type: " + node.type;
//break;
}
};
exports.JavaScriptParseTree = JavaScriptParseTree;
})();

29
js/JavaScriptParser.js Normal file
View File

@ -0,0 +1,29 @@
/*\
title: js/JavaScriptParser.js
JavaScript processing
\*/
(function(){
/*jslint node: true */
"use strict";
var JavaScriptParseTree = require("./JavaScriptParseTree.js").JavaScriptParseTree,
pegjs = require("pegjs");
var JavaScriptParser = function(parserText) {
this.parser = pegjs.buildParser(parserText);
};
JavaScriptParser.prototype.parse = function(code) {
return new JavaScriptParseTree(this.parser.parse(code),this);
};
JavaScriptParser.prototype.createTree = function(tree) {
return new JavaScriptParseTree(tree,this);
};
exports.JavaScriptParser = JavaScriptParser;
})();

View File

@ -1,24 +0,0 @@
/*\
title: js/Sandbox.js
Execute a fragment of JavaScript in a sandbox
\*/
(function(){
/*jslint evil: true, node: true */
"use strict";
var pegjs = require("pegjs");
var Sandbox = function(parserText) {
this.parser = pegjs.buildParser(parserText);
};
Sandbox.prototype.parse = function(code) {
return this.parser.parse(code);
};
exports.Sandbox = Sandbox;
})();

View File

@ -307,8 +307,8 @@ WikiStore.prototype.installMacros = function() {
text: {byPos: 0, type: "text", optional: false} text: {byPos: 0, type: "text", optional: false}
}, },
code: { code: {
"text/html": this.sandbox.parse("return utils.htmlEncode(params.text);"), "text/html": this.jsParser.parse("return utils.htmlEncode(params.text);"),
"text/plain": this.sandbox.parse("return params.text;") "text/plain": this.jsParser.parse("return params.text;")
} }
}, },
view: { view: {
@ -318,8 +318,8 @@ WikiStore.prototype.installMacros = function() {
template: {byPos: 2, type: "text", optional: true} template: {byPos: 2, type: "text", optional: true}
}, },
code: { code: {
"text/html": this.sandbox.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);"), "text/html": this.jsParser.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);"),
"text/plain": this.sandbox.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);") "text/plain": this.jsParser.parse("return store.getFormattedTiddlerField(tiddler.fields.title,params.field,params.format,params.template);")
} }
}, },
list: { list: {
@ -329,26 +329,26 @@ WikiStore.prototype.installMacros = function() {
emptyMessage: {byName: true, type: "text", optional: true} emptyMessage: {byName: true, type: "text", optional: true}
}, },
code: { code: {
"text/html": this.sandbox.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);"), "text/html": this.jsParser.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);"),
"text/plain": this.sandbox.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);") "text/plain": this.jsParser.parse("return store.listTiddlers(params.type,params.template,params.emptyMessage);")
} }
}, },
version: { version: {
params: { params: {
}, },
code: { code: {
"text/html": this.sandbox.parse("return '5.0.0';"), "text/html": this.jsParser.parse("return '5.0.0';"),
"text/plain": this.sandbox.parse("return '5.0.0';") "text/plain": this.jsParser.parse("return '5.0.0';")
} }
}, },
tiddler: { tiddler: {
params: { params: {
target: {byName: "default", type: "tiddler", optional: false}, target: {byName: "default", type: "tiddler", optional: false},
with: {byName: true, type: "text", optional: true, cascade: true} "with": {byName: true, type: "text", optional: true, cascade: true}
}, },
code: { code: {
"text/html": this.sandbox.parse("return store.renderTiddler('text/html',params.target);"), "text/html": this.jsParser.parse("return store.renderTiddler('text/html',params.target);"),
"text/plain": this.sandbox.parse("return store.renderTiddler('text/plain',params.target);") "text/plain": this.jsParser.parse("return store.renderTiddler('text/plain',params.target);")
} }
} }
}; };

View File

@ -8,6 +8,7 @@ title: js/WikiTextCompiler.js
"use strict"; "use strict";
var ArgParser = require("./ArgParser.js").ArgParser, var ArgParser = require("./ArgParser.js").ArgParser,
JavaScriptParseTree = require("./JavaScriptParseTree.js").JavaScriptParseTree,
utils = require("./Utils.js"), utils = require("./Utils.js"),
util = require("util"); util = require("util");
@ -17,121 +18,6 @@ var WikiTextCompiler = function(store,title,parser) {
this.title = title; this.title = title;
}; };
// Compile a javascript tree into an array of string fragments
var compileJavaScript = function(tree) {
var output = [],
compileJavaScriptTree,
compileJavaScriptNode = function(node) {
var p;
switch(node.type) {
case "StringLiteral":
output.push(utils.stringify(node.value));
break;
case "StringLiterals":
output.push(utils.stringify(node.value.join("")));
break;
case "FunctionCall":
output.push("(");
compileJavaScriptNode(node.name);
output.push(")");
output.push("(");
for(p=0; p<node["arguments"].length; p++) {
if(p) {
output.push(",");
}
compileJavaScriptNode(node["arguments"][p]);
}
output.push(")");
break;
case "PropertyAccess":
compileJavaScriptNode(node.base);
if(typeof node.name === "string") {
output.push("." + node.name);
} else {
output.push("[");
compileJavaScriptNode(node.name);
output.push("]");
}
break;
case "ArrayLiteral":
output.push("[");
for(p=0; p<node.elements.length; p++) {
if(p) {
output.push(",");
}
compileJavaScriptNode(node.elements[p]);
}
output.push("]");
break;
case "Variable":
output.push(node.name);
break;
case "ObjectLiteral":
output.push("{");
for(p=0; p<node.properties.length; p++) {
if(p) {
output.push(",");
}
compileJavaScriptNode(node.properties[p]);
}
output.push("}");
break;
case "PropertyAssignment":
output.push(node.name);
output.push(":");
compileJavaScriptNode(node.value);
break;
case "BinaryExpression":
output.push("(");
compileJavaScriptNode(node.left);
output.push(")");
output.push(node.operator);
output.push("(");
compileJavaScriptNode(node.right);
output.push(")");
break;
case "NumericLiteral":
output.push(node.value);
break;
case "Function":
output.push("(");
output.push("function ");
if(node.name !== null) {
output.push(node.name);
}
output.push("(");
output.push(node.params.join(","));
output.push(")");
output.push("{");
compileJavaScriptTree(node.elements);
output.push("}");
output.push(")");
break;
case "ReturnStatement":
output.push("return ");
compileJavaScriptNode(node.value);
break;
case "This":
output.push("this");
break;
default:
console.log(node);
throw "Unknown JavaScript node type: " + node.type;
//break;
}
};
compileJavaScriptTree = function(tree) {
for(var t=0; t<tree.length; t++) {
if(t) {
output.push(";\n");
}
compileJavaScriptNode(tree[t]);
}
};
compileJavaScriptTree(tree);
return output;
};
WikiTextCompiler.prototype.compile = function(type,treenode) { WikiTextCompiler.prototype.compile = function(type,treenode) {
if(type === "text/html") { if(type === "text/html") {
return this.compileAsHtml(treenode); return this.compileAsHtml(treenode);
@ -193,8 +79,8 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
paramsProps = {}; paramsProps = {};
var insertParam = function(name,arg) { var insertParam = function(name,arg) {
if(arg.evaluated) { if(arg.evaluated) {
var prog = me.store.sandbox.parse(arg.string); var prog = me.store.jsParser.parse(arg.string);
paramsProps[name] = prog.elements[0]; paramsProps[name] = prog.tree.elements[0];
} else { } else {
paramsProps[name] = {type: "StringLiteral", value: arg.string}; paramsProps[name] = {type: "StringLiteral", value: arg.string};
} }
@ -225,7 +111,7 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
properties: [] properties: []
}] }]
}; };
macroCall.name.elements = macro.code["text/html"].elements; macroCall.name.elements = macro.code["text/html"].tree.elements;
for(m in paramsProps) { for(m in paramsProps) {
macroCall["arguments"][0].properties.push({ macroCall["arguments"][0].properties.push({
type: "PropertyAssignment", type: "PropertyAssignment",
@ -281,7 +167,7 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
// Compile the wiki parse tree into a javascript parse tree // Compile the wiki parse tree into a javascript parse tree
compileSubTree(treenode); compileSubTree(treenode);
// And then render the javascript parse tree back into JavaScript code // And then render the javascript parse tree back into JavaScript code
return compileJavaScript( var parseTree = this.store.jsParser.createTree(
[ [
{ {
type: "Function", type: "Function",
@ -309,8 +195,8 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
} }
] ]
} }
] ]);
).join(""); return parseTree.render();
}; };
WikiTextCompiler.prototype.compileAsText = function(treenode) { WikiTextCompiler.prototype.compileAsText = function(treenode) {
@ -343,8 +229,8 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
paramsProps = {}; paramsProps = {};
var insertParam = function(name,arg) { var insertParam = function(name,arg) {
if(arg.evaluated) { if(arg.evaluated) {
var prog = me.store.sandbox.parse(arg.string); var prog = me.store.jsParser.parse(arg.string);
paramsProps[name] = prog.elements[0]; paramsProps[name] = prog.tree.elements[0];
} else { } else {
paramsProps[name] = {type: "StringLiteral", value: arg.string}; paramsProps[name] = {type: "StringLiteral", value: arg.string};
} }
@ -375,7 +261,7 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
properties: [] properties: []
}] }]
}; };
macroCall.name.elements = macro.code["text/plain"].elements; macroCall.name.elements = macro.code["text/plain"].tree.elements;
for(m in paramsProps) { for(m in paramsProps) {
macroCall["arguments"][0].properties.push({ macroCall["arguments"][0].properties.push({
type: "PropertyAssignment", type: "PropertyAssignment",
@ -421,7 +307,7 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
// Compile the wiki parse tree into a javascript parse tree // Compile the wiki parse tree into a javascript parse tree
compileSubTree(treenode); compileSubTree(treenode);
// And then render the javascript parse tree back into JavaScript code // And then render the javascript parse tree back into JavaScript code
return compileJavaScript( var parseTree = this.store.jsParser.createTree(
[ [
{ {
type: "Function", type: "Function",
@ -449,8 +335,8 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
} }
] ]
} }
] ]);
).join(""); return parseTree.render();
}; };
exports.WikiTextCompiler = WikiTextCompiler; exports.WikiTextCompiler = WikiTextCompiler;

View File

@ -9,8 +9,7 @@ Parses a block of tiddlywiki-format wiki text into a parse tree object.
/*jslint node: true */ /*jslint node: true */
"use strict"; "use strict";
var WikiTextRenderer = require("./WikiTextRenderer.js").WikiTextRenderer, var WikiTextCompiler = require("./WikiTextCompiler.js").WikiTextCompiler,
WikiTextCompiler = require("./WikiTextCompiler.js").WikiTextCompiler,
utils = require("./Utils.js"), utils = require("./Utils.js"),
util = require("util"); util = require("util");
@ -139,11 +138,6 @@ WikiTextParser.prototype.render = function(type,treenode,store,title) {
return fn(tiddler,store,utils); return fn(tiddler,store,utils);
}; };
WikiTextParser.prototype.compile = function(type,treenode,store,title) {
var compiler = new WikiTextCompiler(store,title,this);
return compiler.compile(type,treenode);
};
exports.WikiTextParser = WikiTextParser; exports.WikiTextParser = WikiTextParser;
})(); })();

View File

@ -135,7 +135,7 @@ WikiTextRenderer.prototype.executeMacro = function(macroNode,title) {
globals: { globals: {
title: title title: title
}, },
sandbox: this.store.sandbox sandbox: this.store.jsProcessor
}; };
for(var g in macroInfo.argOptions) { for(var g in macroInfo.argOptions) {
argOptions[g] = macroInfo.argOptions[g]; argOptions[g] = macroInfo.argOptions[g];

View File

@ -7,7 +7,8 @@ recipe: ../parsers/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/JavaScriptParser.js
jsmodule: ../js/JavaScriptParseTree.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