mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-08-06 22:04:19 +00:00
Restore the JavaScript parser
This commit is contained in:
parent
830359263d
commit
557a7b0eba
107
core/modules/parsers/javascriptparser/javascriptparser.js
Normal file
107
core/modules/parsers/javascriptparser/javascriptparser.js
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/parsers/javascriptparser/javascriptparser.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: parser
|
||||||
|
|
||||||
|
Parses a JSON object into a parse tree
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var esprima = require("./esprima.js");
|
||||||
|
|
||||||
|
// Initialise the parser
|
||||||
|
var JavaScriptParser = function(options) {
|
||||||
|
this.wiki = options.wiki;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse a string of JavaScript code and return the parse tree as a wikitext parse tree
|
||||||
|
JavaScriptParser.prototype.parse = function(type,code) {
|
||||||
|
// Simplistically replace tabs with spaces. Browsers will happily render tabs but most default to 8 character tab stops
|
||||||
|
code = code.replace(/\t/mg," ");
|
||||||
|
// Try to parse the code
|
||||||
|
var parseTree;
|
||||||
|
try {
|
||||||
|
parseTree = esprima.parse(code,{comment: true,tokens: true,range: true});
|
||||||
|
} catch(ex) {
|
||||||
|
// Return a helpful error if the parse failed
|
||||||
|
return new $tw.Renderer([
|
||||||
|
$tw.Tree.Element("pre",{"class": "javascript-source"},[
|
||||||
|
$tw.Tree.Text(code.substring(0,ex.index)),
|
||||||
|
$tw.Tree.errorNode(ex),
|
||||||
|
$tw.Tree.Text(code.substring(ex.index))
|
||||||
|
])
|
||||||
|
],new $tw.Dependencies(),this.wiki);
|
||||||
|
}
|
||||||
|
// Helpers to render the comments and tokens with the appropriate classes
|
||||||
|
var self = this,
|
||||||
|
result = [],
|
||||||
|
nextComment = 0,
|
||||||
|
nextToken = 0,
|
||||||
|
currPos = 0;
|
||||||
|
var renderWhitespace = function(nextPos) {
|
||||||
|
if(currPos < nextPos) {
|
||||||
|
result.push($tw.Tree.Text(code.substring(currPos,nextPos)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderComment = function(comment) {
|
||||||
|
var text = comment.value,
|
||||||
|
element,
|
||||||
|
classes = ["javascript-comment"],
|
||||||
|
content = [];
|
||||||
|
renderWhitespace(comment.range[0]);
|
||||||
|
if(comment.type === "Block") {
|
||||||
|
element = "div";
|
||||||
|
classes.push("javascript-block-comment");
|
||||||
|
content.push($tw.Tree.Text("/*"));
|
||||||
|
} else {
|
||||||
|
element = "span";
|
||||||
|
classes.push("javascript-line-comment");
|
||||||
|
content.push($tw.Tree.Text("//"));
|
||||||
|
}
|
||||||
|
content.push.apply(content,self.wiki.parseText("text/x-tiddlywiki",text).tree);
|
||||||
|
if(comment.type === "Block") {
|
||||||
|
content.push($tw.Tree.Text("*/"));
|
||||||
|
} else {
|
||||||
|
content.push($tw.Tree.Text("\n"));
|
||||||
|
}
|
||||||
|
result.push($tw.Tree.Element(element,{"class": classes},content));
|
||||||
|
currPos = comment.range[1] + 1;
|
||||||
|
},
|
||||||
|
renderToken = function(token) {
|
||||||
|
renderWhitespace(token.range[0]);
|
||||||
|
result.push($tw.Tree.Element("span",{
|
||||||
|
"class": "javascript-" + token.type.toLowerCase()
|
||||||
|
},[
|
||||||
|
$tw.Tree.Text(token.value)
|
||||||
|
]));
|
||||||
|
currPos = token.range[1] + 1;
|
||||||
|
};
|
||||||
|
// Process the tokens interleaved with the comments
|
||||||
|
while(nextComment < parseTree.comments.length || nextToken < parseTree.tokens.length) {
|
||||||
|
if(nextComment < parseTree.comments.length && nextToken < parseTree.tokens.length) {
|
||||||
|
if(parseTree.comments[nextComment].range[0] < parseTree.tokens[nextToken].range[0]) {
|
||||||
|
renderComment(parseTree.comments[nextComment++]);
|
||||||
|
} else {
|
||||||
|
renderToken(parseTree.tokens[nextToken++]);
|
||||||
|
}
|
||||||
|
} else if(nextComment < parseTree.comments.length) {
|
||||||
|
renderComment(parseTree.comments[nextComment++]);
|
||||||
|
} else {
|
||||||
|
renderToken(parseTree.tokens[nextToken++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderWhitespace(code.length);
|
||||||
|
// Wrap the whole lot in a `<PRE>`
|
||||||
|
return new $tw.Renderer([
|
||||||
|
$tw.Tree.Element("pre",{"class": "javascript-source"},result)
|
||||||
|
],new $tw.Dependencies(),this.wiki);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports["application/javascript"] = JavaScriptParser;
|
||||||
|
|
||||||
|
})();
|
@ -4,8 +4,12 @@
|
|||||||
"file": "../../../../node_modules/esprima/esprima.js",
|
"file": "../../../../node_modules/esprima/esprima.js",
|
||||||
"fields": {
|
"fields": {
|
||||||
"title": "$:/core/modules/parsers/javascriptparser/esprima.js",
|
"title": "$:/core/modules/parsers/javascriptparser/esprima.js",
|
||||||
"type": "application/javascript"
|
"type": "application/javascript",
|
||||||
|
"module-type": "library"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "javascriptparser.js"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -52,7 +52,7 @@ Element.prototype.render = function(type) {
|
|||||||
if(isHtml) {
|
if(isHtml) {
|
||||||
output.push("<",this.type);
|
output.push("<",this.type);
|
||||||
if(this.attributes) {
|
if(this.attributes) {
|
||||||
attr = []
|
attr = [];
|
||||||
for(a in this.attributes) {
|
for(a in this.attributes) {
|
||||||
attr.push(a);
|
attr.push(a);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user