mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-27 18:40:28 +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:
parent
5eeb45cd79
commit
3ff1d9a76c
@ -14,7 +14,7 @@ var WikiStore = require("./WikiStore.js").WikiStore,
|
||||
tiddlerInput = require("./TiddlerInput.js"),
|
||||
tiddlerOutput = require("./TiddlerOutput.js"),
|
||||
WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor,
|
||||
Sandbox = require("./Sandbox.js").Sandbox,
|
||||
JavaScriptParser = require("./JavaScriptParser.js").JavaScriptParser,
|
||||
Navigators = require("./Navigators.js").Navigators,
|
||||
StoryNavigator = require("./StoryNavigator.js").StoryNavigator;
|
||||
|
||||
@ -73,11 +73,11 @@ var App = function() {
|
||||
this.store.addTiddler(new Tiddler(tiddlers[t]));
|
||||
}
|
||||
}
|
||||
// Set up the sandbox for JavaScript parsing
|
||||
// Set up the JavaScript parser
|
||||
if(this.isBrowser) {
|
||||
this.store.sandbox = new Sandbox(this.store.getTiddlerText("javascript.pegjs"));
|
||||
this.store.jsParser = new JavaScriptParser(this.store.getTiddlerText("javascript.pegjs"));
|
||||
} 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
|
||||
this.store.installMacros();
|
||||
|
135
js/JavaScriptParseTree.js
Normal file
135
js/JavaScriptParseTree.js
Normal 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
29
js/JavaScriptParser.js
Normal 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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -307,8 +307,8 @@ WikiStore.prototype.installMacros = function() {
|
||||
text: {byPos: 0, type: "text", optional: false}
|
||||
},
|
||||
code: {
|
||||
"text/html": this.sandbox.parse("return utils.htmlEncode(params.text);"),
|
||||
"text/plain": this.sandbox.parse("return params.text;")
|
||||
"text/html": this.jsParser.parse("return utils.htmlEncode(params.text);"),
|
||||
"text/plain": this.jsParser.parse("return params.text;")
|
||||
}
|
||||
},
|
||||
view: {
|
||||
@ -318,8 +318,8 @@ WikiStore.prototype.installMacros = function() {
|
||||
template: {byPos: 2, type: "text", optional: true}
|
||||
},
|
||||
code: {
|
||||
"text/html": this.sandbox.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/html": this.jsParser.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: {
|
||||
@ -329,26 +329,26 @@ WikiStore.prototype.installMacros = function() {
|
||||
emptyMessage: {byName: true, type: "text", optional: true}
|
||||
},
|
||||
code: {
|
||||
"text/html": this.sandbox.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/html": this.jsParser.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: {
|
||||
params: {
|
||||
},
|
||||
code: {
|
||||
"text/html": this.sandbox.parse("return '5.0.0';"),
|
||||
"text/plain": this.sandbox.parse("return '5.0.0';")
|
||||
"text/html": this.jsParser.parse("return '5.0.0';"),
|
||||
"text/plain": this.jsParser.parse("return '5.0.0';")
|
||||
}
|
||||
},
|
||||
tiddler: {
|
||||
params: {
|
||||
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: {
|
||||
"text/html": this.sandbox.parse("return store.renderTiddler('text/html',params.target);"),
|
||||
"text/plain": this.sandbox.parse("return store.renderTiddler('text/plain',params.target);")
|
||||
"text/html": this.jsParser.parse("return store.renderTiddler('text/html',params.target);"),
|
||||
"text/plain": this.jsParser.parse("return store.renderTiddler('text/plain',params.target);")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ title: js/WikiTextCompiler.js
|
||||
"use strict";
|
||||
|
||||
var ArgParser = require("./ArgParser.js").ArgParser,
|
||||
JavaScriptParseTree = require("./JavaScriptParseTree.js").JavaScriptParseTree,
|
||||
utils = require("./Utils.js"),
|
||||
util = require("util");
|
||||
|
||||
@ -17,121 +18,6 @@ var WikiTextCompiler = function(store,title,parser) {
|
||||
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) {
|
||||
if(type === "text/html") {
|
||||
return this.compileAsHtml(treenode);
|
||||
@ -193,8 +79,8 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
|
||||
paramsProps = {};
|
||||
var insertParam = function(name,arg) {
|
||||
if(arg.evaluated) {
|
||||
var prog = me.store.sandbox.parse(arg.string);
|
||||
paramsProps[name] = prog.elements[0];
|
||||
var prog = me.store.jsParser.parse(arg.string);
|
||||
paramsProps[name] = prog.tree.elements[0];
|
||||
} else {
|
||||
paramsProps[name] = {type: "StringLiteral", value: arg.string};
|
||||
}
|
||||
@ -225,7 +111,7 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
|
||||
properties: []
|
||||
}]
|
||||
};
|
||||
macroCall.name.elements = macro.code["text/html"].elements;
|
||||
macroCall.name.elements = macro.code["text/html"].tree.elements;
|
||||
for(m in paramsProps) {
|
||||
macroCall["arguments"][0].properties.push({
|
||||
type: "PropertyAssignment",
|
||||
@ -281,7 +167,7 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
|
||||
// Compile the wiki parse tree into a javascript parse tree
|
||||
compileSubTree(treenode);
|
||||
// And then render the javascript parse tree back into JavaScript code
|
||||
return compileJavaScript(
|
||||
var parseTree = this.store.jsParser.createTree(
|
||||
[
|
||||
{
|
||||
type: "Function",
|
||||
@ -309,8 +195,8 @@ WikiTextCompiler.prototype.compileAsHtml = function(treenode) {
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
).join("");
|
||||
]);
|
||||
return parseTree.render();
|
||||
};
|
||||
|
||||
WikiTextCompiler.prototype.compileAsText = function(treenode) {
|
||||
@ -343,8 +229,8 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
|
||||
paramsProps = {};
|
||||
var insertParam = function(name,arg) {
|
||||
if(arg.evaluated) {
|
||||
var prog = me.store.sandbox.parse(arg.string);
|
||||
paramsProps[name] = prog.elements[0];
|
||||
var prog = me.store.jsParser.parse(arg.string);
|
||||
paramsProps[name] = prog.tree.elements[0];
|
||||
} else {
|
||||
paramsProps[name] = {type: "StringLiteral", value: arg.string};
|
||||
}
|
||||
@ -375,7 +261,7 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
|
||||
properties: []
|
||||
}]
|
||||
};
|
||||
macroCall.name.elements = macro.code["text/plain"].elements;
|
||||
macroCall.name.elements = macro.code["text/plain"].tree.elements;
|
||||
for(m in paramsProps) {
|
||||
macroCall["arguments"][0].properties.push({
|
||||
type: "PropertyAssignment",
|
||||
@ -421,7 +307,7 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
|
||||
// Compile the wiki parse tree into a javascript parse tree
|
||||
compileSubTree(treenode);
|
||||
// And then render the javascript parse tree back into JavaScript code
|
||||
return compileJavaScript(
|
||||
var parseTree = this.store.jsParser.createTree(
|
||||
[
|
||||
{
|
||||
type: "Function",
|
||||
@ -449,8 +335,8 @@ WikiTextCompiler.prototype.compileAsText = function(treenode) {
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
).join("");
|
||||
]);
|
||||
return parseTree.render();
|
||||
};
|
||||
|
||||
exports.WikiTextCompiler = WikiTextCompiler;
|
||||
|
@ -9,8 +9,7 @@ Parses a block of tiddlywiki-format wiki text into a parse tree object.
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var WikiTextRenderer = require("./WikiTextRenderer.js").WikiTextRenderer,
|
||||
WikiTextCompiler = require("./WikiTextCompiler.js").WikiTextCompiler,
|
||||
var WikiTextCompiler = require("./WikiTextCompiler.js").WikiTextCompiler,
|
||||
utils = require("./Utils.js"),
|
||||
util = require("util");
|
||||
|
||||
@ -139,11 +138,6 @@ WikiTextParser.prototype.render = function(type,treenode,store,title) {
|
||||
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;
|
||||
|
||||
})();
|
||||
|
@ -135,7 +135,7 @@ WikiTextRenderer.prototype.executeMacro = function(macroNode,title) {
|
||||
globals: {
|
||||
title: title
|
||||
},
|
||||
sandbox: this.store.sandbox
|
||||
sandbox: this.store.jsProcessor
|
||||
};
|
||||
for(var g in macroInfo.argOptions) {
|
||||
argOptions[g] = macroInfo.argOptions[g];
|
||||
|
@ -7,7 +7,8 @@ recipe: ../parsers/split.recipe
|
||||
|
||||
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/FileRetriever.js
|
||||
jsmodule: ../js/Utils.js
|
||||
|
Loading…
Reference in New Issue
Block a user