const fs = require('fs'); const path = require('path'); const dir = path.join(__dirname, '..', '..', 'frontend', 'textbooks'); const files = ['geometry_10_hub.html','geometry_10_r1.html','geometry_10_r2.html','geometry_10_r3.html','geometry_10_r4.html']; const cmds = ['dfrac','sqrt','sin','cos','tan','angle','vec','triangle','Rightarrow','cdot','ne','le','ge','pi','alpha','beta','gamma','delta','varphi','circ','perp','parallel','frac','tfrac','overline','left','right','begin','end','boxed','cot','arcsin','arccos','arctan','log','ln','lim','sum','int','infty','Delta','theta','lambda','mu','rho','sigma','tau','omega','Omega','phi','psi','xi','zeta','eta','epsilon','varepsilon','Pi','Sigma','approx','equiv','pm','mp','times','div','leq','geq','neq','sim','cong','subset','supset','cup','cap','forall','exists','overrightarrow','overleftarrow','widehat','widetilde','mathbf','mathrm','mathbb','mathcal','quad','qquad','hline','cline','displaystyle','textstyle','scriptstyle','underline','operatorname','land','lor','lnot','mapsto','Leftrightarrow','Leftarrow','leftarrow','rightarrow','uparrow','downarrow','prime','colon']; for (const f of files) { const fp = path.join(dir, f); if (!fs.existsSync(fp)) { console.log('MISSING', f); continue; } const txt = fs.readFileSync(fp, 'utf8'); const scriptRe = /]*\bsrc=)[^>]*>([\s\S]*?)<\/script>/g; let m; let totalKatexErrs = 0; const errSamples = []; let scriptBlocks = 0; let combinedJs = ''; while ((m = scriptRe.exec(txt)) !== null) { scriptBlocks++; const body = m[1]; combinedJs += body + ';\n'; const cmdRe = /(^|[^\\])\\([a-zA-Z]+)/g; let cm; while ((cm = cmdRe.exec(body)) !== null) { const cmd = cm[2]; if (cmds.includes(cmd)) { totalKatexErrs++; const idxAbs = m.index + cm.index + cm[1].length; const before = txt.slice(0, idxAbs); const line = (before.match(/\n/g) || []).length + 1; if (errSamples.length < 10) errSamples.push({line, cmd, ctx: body.slice(Math.max(0,cm.index-30), cm.index+50).replace(/\n/g,' ')}); } } } //