diff --git a/playground/css/pseudocode.css b/playground/css/pseudocode.css index cc8dd34c..d666d65e 100644 --- a/playground/css/pseudocode.css +++ b/playground/css/pseudocode.css @@ -59,6 +59,8 @@ button:focus { border-radius: 4px; box-sizing: border-box; color: #3c4043; + font-family: 'TheSansMonoCd',monospace; + font-weight: 450; font-size: 14px; margin: 8px 0; } diff --git a/playground/js/pseudocode.js b/playground/js/pseudocode.js index e94aaf25..85a2c39c 100644 --- a/playground/js/pseudocode.js +++ b/playground/js/pseudocode.js @@ -71,84 +71,82 @@ function modifyMessage(msg, e) { } function markup(code, elt) { - const RE = /(?:\[(?[^\]\}]+)\])|(?:\{(?.+)\})|(?\n)/g; - - let out = "$\\begin{aligned}"; - let indent = 0; - let blank = true; + let out = ""; + let indent = [0]; let lineno = 0; - let opened = false; let opening = false; - for (const match of code.matchAll(RE)) { - if (match.groups.NL) { - out += "\\\\\n"; - blank = true; - if (opening) { - out += "&\\begin{aligned}"; - opening = false; - opened = true; - } + let opened = false; + let keep = false; + + const RE = /(?:\$(?(?:\\.|[^$\\])+)\$)|(?[\w-]+)/g; + const INDENT = /^ */; + + for (const line of code.split("\n")) { + let cur = ""; + let len = line.match(INDENT)[0].length; + if (len === line.length) { continue; } - if (blank) { - if (match.groups.CK === 'function') { - if (opened) { - out += "\\end{aligned}\\\\\n"; - lineno = 0; - opened = false; - } - opening = true; - } else { - if (opened) { - out += `\\qquad{\\scriptsize ${++lineno}\\colon}`; - } - out += "&"; - if (match.groups.CK && match.groups.CK.startsWith('end')) { - --indent; + if (indent[indent.length - 1] < len) { + indent.push(len); + } else if (indent[indent.length - 1] > len) { + indent.pop(); + } + + for (const match of line.matchAll(RE)) { + if (cur !== "") { + cur += "\\;"; + } + + if (match.groups.TEX) { + cur += `${match.groups.TEX}`; + } else if (match.groups.KW) { + if (["function"].includes(match.groups.KW)) { + opening = true; } - out += "\\quad ".repeat(indent); - if (match.groups.CK && !match.groups.CK.startsWith('end')) { - if (opened && !["function", "return"].includes(match.groups.CK)) { - ++indent; - } + if (/\b(?:const|let|global)/.test(match.groups.KW)) { + keep = true; } + cur += `\\text{\\textbf{${match.groups.KW}}}`; } - blank = false; - } else { - out += "\\;"; } - if (match.groups.CK) { - if (match.groups.CK === "function") { - out += "&"; + if (cur !== "") { + if (lineno > 0) { + out += "\\\\\n"; + } + + if (keep) { + out += " \\quad".repeat(indent.length - 1); + } else if (!opening) { + out += `\\qquad {\\scriptsize ${++lineno}}{\\scriptsize\\colon} &`; + out += " \\quad".repeat(indent.length - 1); + } + if (opening) { + if (opened) { + out += "\n\\end{aligned}\\\\\n"; + lineno = 0; + } + out += `& ${cur} \\\\\n`; + out += "&\\begin{aligned}\n"; + opened = true; + } else if (keep && !opened) { + out += `& ${cur} \\\\\n`; + } else { + out += ` ${cur}`; } - out += `\\text{\\textbf{${match.groups.CK}}}`; - } else if (match.groups.CE) { - out += ` ${match.groups.CE} `; } + + keep = false; + opening = false; } + if (opened) { - out += "\\end{aligned}" - } - out += "\\end{aligned}$"; - - elt.innerHTML = out; - - let err = ""; - renderMathInElement(elt, { - delimiters: [ - { left: '$$', right: '$$', display: true }, - { left: '$', right: '$', display: false }, - ], - macros, - errorCallback: ((msg, e) => { - console.error(e); - }), - }); - if (err) { - elt.innerText += 'error, see console.'; + out += "\n\\end{aligned}"; } + + elt.innerHTML = katex.renderToString(`\\begin{aligned}${out}\\end{aligned}`, { macros }); } function render() {