fix(exam-prep): normalize LaTeX in dashboard preview text
Recent-attempts widget on /exam-prep/:examKey was showing raw LaTeX
like '\dfrac{7}{9}' because stripPreview only removed HTML tags.
Now it also converts common LaTeX to readable unicode (fractions →
a/b, \sqrt → √, \cdot → ·, comparisons → ≤≥≠, Greek letters, etc.)
before truncating.
KaTeX rendering would be overkill for a 100-char preview row; this
just makes the existing text legible.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -796,13 +796,39 @@ router.get('/:examKey/dashboard', (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Lightweight preview: strip tags, normalize whitespace, truncate. */
|
/* Lightweight preview: strip HTML, normalize LaTeX to readable unicode,
|
||||||
|
collapse whitespace, truncate. Used in dashboard "recent attempts" rows
|
||||||
|
where rendering KaTeX would be overkill but raw `$\dfrac{7}{9}$` is
|
||||||
|
ugly. Matches the spirit of tag-exam-tasks.js#stripText. */
|
||||||
function stripPreview(html) {
|
function stripPreview(html) {
|
||||||
const text = String(html || '')
|
let text = String(html || '')
|
||||||
.replace(/<svg[\s\S]*?<\/svg>/gi, '')
|
.replace(/<svg[\s\S]*?<\/svg>/gi, '')
|
||||||
.replace(/<[^>]+>/g, ' ')
|
.replace(/<[^>]+>/g, ' ');
|
||||||
|
|
||||||
|
// Common LaTeX → unicode/plain. Order matters: handle fractions/roots
|
||||||
|
// before stripping bare backslash commands.
|
||||||
|
text = text
|
||||||
|
.replace(/\\d?frac\s*\{([^{}]+)\}\s*\{([^{}]+)\}/g, '$1/$2')
|
||||||
|
.replace(/\\sqrt\s*\{([^{}]+)\}/g, '√($1)')
|
||||||
|
.replace(/\\cdot/g, '·')
|
||||||
|
.replace(/\\times/g, '×')
|
||||||
|
.replace(/\\pm/g, '±')
|
||||||
|
.replace(/\\mp/g, '∓')
|
||||||
|
.replace(/\\leq?/g, '≤')
|
||||||
|
.replace(/\\geq?/g, '≥')
|
||||||
|
.replace(/\\neq/g, '≠')
|
||||||
|
.replace(/\\approx/g, '≈')
|
||||||
|
.replace(/\\infty/g, '∞')
|
||||||
|
.replace(/\\pi/g, 'π')
|
||||||
|
.replace(/\\alpha/g, 'α').replace(/\\beta/g, 'β').replace(/\\gamma/g, 'γ')
|
||||||
|
.replace(/\\(?:left|right)/g, '')
|
||||||
|
.replace(/\\[a-zA-Z]+\s*/g, ' ') // any remaining LaTeX command
|
||||||
|
.replace(/[{}]/g, '') // leftover braces
|
||||||
|
.replace(/\$+/g, '') // math delimiters
|
||||||
|
.replace(/&[a-z]+;/gi, ' ') // html entities
|
||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
return text.length > 100 ? text.slice(0, 100) + '…' : text;
|
return text.length > 100 ? text.slice(0, 100) + '…' : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user