latex2im / preprocess_latex.js
da03
.
b498cbf
var katex = require("./katex/katex.js")
options = require("./katex/src/Options.js")
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function(line){
a = line
if (line[0] == "%") {
line = line.substr(1, line.length - 1);
}
line = line.split('%')[0];
line = line.split('\\~').join(' ');
for (var i = 0; i < 300; i++) {
line = line.replace(/\\>/, " ");
line = line.replace('$', ' ');
line = line.replace(/\\label{.*?}/, "");
}
if (line.indexOf("matrix") == -1 && line.indexOf("cases")==-1 &&
line.indexOf("array")==-1 && line.indexOf("begin")==-1) {
for (var i = 0; i < 300; i++) {
line = line.replace(/\\\\/, "\\,");
}
}
line = line + " "
// global_str is tokenized version (build in parser.js)
// norm_str is normalized version build by renderer below.
//Yuntiantry {
if (process.argv[2] == "tokenize") {
var tree = katex.__parse(line, {});
console.log(global_str.replace(/\\label { .*? }/, ""));
} else {
for (var i = 0; i < 300; ++i) {
line = line.replace(/{\\rm/, "\\mathrm{");
line = line.replace(/{ \\rm/, "\\mathrm{");
line = line.replace(/\\rm{/, "\\mathrm{");
}
var tree = katex.__parse(line, {});
buildExpression(tree, new options({}));
for (var i = 0; i < 300; ++i) {
norm_str = norm_str.replace('SSSSSS', '$');
norm_str = norm_str.replace(' S S S S S S', '$');
}
console.log(norm_str.replace(/\\label { .*? }/, ""));
}
//} catch (e) {
// console.error(line);
// console.error(norm_str);
// console.error(e);
// console.log("");
//}
global_str = ""
norm_str = ""
})
// This is a LaTeX AST to LaTeX Renderer (modified version of KaTeX AST-> MathML).
norm_str = ""
var groupTypes = {};
groupTypes.mathord = function(group, options) {
if (options.font == "mathrm"){
for (i = 0; i < group.value.length; ++i ) {
if (group.value[i] == " ") {
norm_str = norm_str + group.value[i] + "\; ";
} else {
norm_str = norm_str + group.value[i] + " ";
}
}
} else {
norm_str = norm_str + group.value + " ";
}
};
groupTypes.textord = function(group, options) {
norm_str = norm_str + group.value + " ";
};
groupTypes.bin = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.rel = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.open = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.close = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.inner = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.punct = function(group) {
norm_str = norm_str + group.value + " ";
};
groupTypes.ordgroup = function(group, options) {
norm_str = norm_str + "{ ";
buildExpression(group.value, options);
norm_str = norm_str + "} ";
};
groupTypes.text = function(group, options) {
norm_str = norm_str + "\\mathrm { ";
buildExpression(group.value.body, options);
norm_str = norm_str + "} ";
};
groupTypes.color = function(group, options) {
var inner = buildExpression(group.value.value, options);
var node = new mathMLTree.MathNode("mstyle", inner);
node.setAttribute("mathcolor", group.value.color);
return node;
};
groupTypes.supsub = function(group, options) {
buildGroup(group.value.base, options);
if (group.value.sub) {
norm_str = norm_str + "_ ";
if (group.value.sub.type != 'ordgroup') {
norm_str = norm_str + " { ";
buildGroup(group.value.sub, options);
norm_str = norm_str + "} ";
} else {
buildGroup(group.value.sub, options);
}
}
if (group.value.sup) {
norm_str = norm_str + "^ ";
if (group.value.sup.type != 'ordgroup') {
norm_str = norm_str + " { ";
buildGroup(group.value.sup, options);
norm_str = norm_str + "} ";
} else {
buildGroup(group.value.sup, options);
}
}
};
groupTypes.genfrac = function(group, options) {
if (!group.value.hasBarLine) {
norm_str = norm_str + "\\binom ";
} else {
norm_str = norm_str + "\\frac ";
}
buildGroup(group.value.numer, options);
buildGroup(group.value.denom, options);
};
groupTypes.array = function(group, options) {
norm_str = norm_str + "\\begin{" + group.value.style + "} ";
if (group.value.style == "array" || group.value.style == "tabular") {
norm_str = norm_str + "{ ";
if (group.value.cols) {
group.value.cols.map(function(start) {
if (start) {
if (start.type == "align") {
norm_str = norm_str + start.align + " ";
} else if (start.type == "separator") {
norm_str = norm_str + start.separator + " ";
}
}
});
} else {
group.value.body[0].map(function(start) {
norm_str = norm_str + "c ";
} );
}
norm_str = norm_str + "} ";
}
group.value.body.map(function(row) {
if (row.length > 1 || row[0].value.length > 0) {
if (row[0].value[0] && row[0].value[0].value == "\\hline") {
norm_str = norm_str + "\\hline ";
row[0].value = row[0].value.slice(1);
}
out = row.map(function(cell) {
buildGroup(cell, options);
norm_str = norm_str + "& ";
});
norm_str = norm_str.substring(0, norm_str.length-2) + "\\\\ ";
}
});
norm_str = norm_str + "\\end{" + group.value.style + "} ";
};
groupTypes.sqrt = function(group, options) {
var node;
if (group.value.index) {
norm_str = norm_str + "\\sqrt [ " + group.value.index + " ] ";
buildGroup(group.value.body, options);
} else {
norm_str = norm_str + "\\sqrt ";
buildGroup(group.value.body, options);
}
};
groupTypes.leftright = function(group, options) {
norm_str = norm_str + "\\left" + group.value.left + " ";
buildExpression(group.value.body, options);
norm_str = norm_str + "\\right" + group.value.right + " ";
};
groupTypes.accent = function(group, options) {
if (group.value.base.type != 'ordgroup') {
norm_str = norm_str + group.value.accent + " { ";
buildGroup(group.value.base, options);
norm_str = norm_str + "} ";
} else {
norm_str = norm_str + group.value.accent + " ";
buildGroup(group.value.base, options);
}
};
groupTypes.spacing = function(group) {
var node;
if (group.value == " ") {
norm_str = norm_str + "~ ";
} else {
norm_str = norm_str + group.value + " ";
}
return node;
};
groupTypes.op = function(group) {
var node;
// TODO(emily): handle big operators using the `largeop` attribute
if (group.value.symbol) {
// This is a symbol. Just add the symbol.
norm_str = norm_str + group.value.body + " ";
} else {
if (group.value.limits == false) {
norm_str = norm_str + "\\\operatorname { ";
} else {
norm_str = norm_str + "\\\operatorname* { ";
}
for (i = 1; i < group.value.body.length; ++i ) {
norm_str = norm_str + group.value.body[i] + " ";
}
norm_str = norm_str + "} ";
}
};
groupTypes.katex = function(group) {
var node = new mathMLTree.MathNode(
"mtext", [new mathMLTree.TextNode("KaTeX")]);
return node;
};
groupTypes.font = function(group, options) {
var font = group.value.font;
if (font == "mbox" || font == "hbox") {
font = "mathrm";
}
norm_str = norm_str + "\\" + font + " ";
buildGroup(group.value.body, options.withFont(font));
};
groupTypes.delimsizing = function(group) {
var children = [];
norm_str = norm_str + group.value.funcName + " " + group.value.value + " ";
};
groupTypes.styling = function(group, options) {
norm_str = norm_str + " " + group.value.original + " ";
buildExpression(group.value.value, options);
};
groupTypes.sizing = function(group, options) {
if (group.value.original == "\\rm") {
norm_str = norm_str + "\\mathrm { ";
buildExpression(group.value.value, options.withFont("mathrm"));
norm_str = norm_str + "} ";
} else {
norm_str = norm_str + " " + group.value.original + " ";
buildExpression(group.value.value, options);
}
};
groupTypes.overline = function(group, options) {
norm_str = norm_str + "\\overline { ";
buildGroup(group.value.body, options);
norm_str = norm_str + "} ";
norm_str = norm_str;
};
groupTypes.underline = function(group, options) {
norm_str = norm_str + "\\underline { ";
buildGroup(group.value.body, options);
norm_str = norm_str + "} ";
norm_str = norm_str;
};
groupTypes.rule = function(group) {
norm_str = norm_str + "\\rule { "+group.value.width.number+" "+group.value.width.unit+" } { "+group.value.height.number+" "+group.value.height.unit+ " } ";
};
groupTypes.llap = function(group, options) {
norm_str = norm_str + "\\llap ";
buildGroup(group.value.body, options);
};
groupTypes.rlap = function(group, options) {
norm_str = norm_str + "\\rlap ";
buildGroup(group.value.body, options);
};
groupTypes.phantom = function(group, options, prev) {
norm_str = norm_str + "\\phantom { ";
buildExpression(group.value.value, options);
norm_str = norm_str + "} ";
};
/**
* Takes a list of nodes, builds them, and returns a list of the generated
* MathML nodes. A little simpler than the HTML version because we don't do any
* previous-node handling.
*/
var buildExpression = function(expression, options) {
var groups = [];
for (var i = 0; i < expression.length; i++) {
var group = expression[i];
buildGroup(group, options);
}
// console.log(norm_str);
// return groups;
};
/**
* Takes a group from the parser and calls the appropriate groupTypes function
* on it to produce a MathML node.
*/
var buildGroup = function(group, options) {
if (groupTypes[group.type]) {
groupTypes[group.type](group, options);
} else {
throw new ParseError(
"Got group of unknown type: '" + group.type + "'");
}
};