Expand Macros
HTML
<button id="run">Expand Macros</button>
<textarea id="input">
\documentclass{amsart}
\usepackage{amsmath,amssymb}
\newcommand{\N}{\mathbb{N}}
\DeclareMathOperator{\End}{End}
\begin{document}
In this lecture we'll study the ring of Endomorphisms of an Abelian group $A$.
Let's denote this ring by $\End(A)$. Throughout the lecture, $\N$ will denote
the set of natural numbers.
\end{document}
</textarea>
<textarea id="output">Output</textarea>
CSS
html, body {
height: 90%;
}
button {
display: block;
}
textarea {
float: left;
width: 48%;
height: 80%;
}
JavaScript
function expandMacros(tex) {
function nestBrackets(level) {
var level = level || 5, re = c = "(?:[^\\r\\n\\{\\}]|\\\\[\\{\\}]|\\r?\\n(?!\\r?\\n))*?";
while (level--) re = c + "(?:\\{" + re + "\}" + c + ")*?";
return " *(\\{" + re + "\\}|[^\\{])";
}
function getRegExp(name, macro) {
var num = macro.num, def = macro.def, re = "";
while (num--) re += nestBrackets();
re = "\\" + name + "(?![a-zA-Z\\}])" + re;
return new RegExp(re, "g");
}
function trimString(s) {
return s.replace(/^ +| +$/g, '').replace(/^\{|\}$/g, "");
}
function extractMacros() {
var cs = "\\\\\\w+", re;
// \def, \gdef, \edef and \xdef
re = new RegExp("\\\\[gex]?def\\*? *(" + cs + ") *(#\\d)*" + nestBrackets(), "g");
tex = tex.replace(re, function(match){
var m = arguments;
var macro = {
num: m[2] ? Math.min(m[2].length / 2, 9) : 0,
def: trimString(m[3])
};
macros[trimString(m[1])] = macro;
return "";
});
// \newcommand, \newcommand*, \renewcommand and \renewcommand*
re = new RegExp("\\\\(?:re)?newcommand\\*? *(" + cs + "|\\{" + cs + "\}) *(\\[(\\d)\\])?"
+ nestBrackets(), "g");
console.log(re)
tex = tex.replace(re, function(match){
var m = arguments;
var macro = {
num: m[3] || 0,
def: trimString(m[4])
};
macros[trimString(m[1])] = macro;
return "";
});
// \DeclareMathOperator and \DeclareMathOperator* inside amsmath
re = new RegExp("\\\\DeclareMathOperator(\\*?) *(" + cs + "|\\{" + cs + "\}) *"
+ nestBrackets(), "g");
tex = tex.replace(re, function(match){
var m = arguments;
var macro = {
num: 0,
...