Render LaTeX in model-authored text (#7, REQ-019) #12

Merged
crowmaki merged 2 commits from feat/issue-7-latex-rendering into main 2026-08-29 20:11:15 +00:00
Owner

Closes #7. Model-authored text is now rendered as LaTeX in the desktop half, per REQ-019.

Backend

  • Prompts for tutor, assignments, and diagnostics instruct the model to author math in \( ... \) / \[ ... \] (Temml-compatible), with plain text as fallback when LaTeX adds no clarity.
  • Model output flows through unchanged — rendering is presentation-only and never touches course state or the mastery critical path.

Desktop

  • Added Temml (vendored, self-contained) and render LaTeX spans in model-authored text: inline $...$ / \(...\) and display \[...\], with careful escaping so only intended spans are transformed.
  • Line math does not affect answer-choice semantics: choice comparison stays on raw text; correctness is still a local comparison against the stored answer key.

Build / lint

  • Bundle is now minified (esbuild minify: true), reducing dist/plugin.js from ~597 KiB to ~315 KiB (under the 512 KiB soft limit).
  • Bundle lint gate reworked for minified output (unanchored import-specifier checks, colour rule uses a fail-closed hex allowlist built from the vendored Temml palette instead of section markers).
  • scripts/install.py re-implements the same gate so a stale lint script can't ship a bad bundle.

Tests

  • npm test: 21/21 (a11y + math rendering spot checks, axe-core).
  • npm run typecheck / npm run build green.
  • pytest: 450 passed; the 5 known pre-existing Windows failures on main are unchanged.
Closes #7. Model-authored text is now rendered as LaTeX in the desktop half, per REQ-019. ## Backend - Prompts for tutor, assignments, and diagnostics instruct the model to author math in `\( ... \)` / `\[ ... \]` (Temml-compatible), with plain text as fallback when LaTeX adds no clarity. - Model output flows through unchanged — rendering is presentation-only and never touches course state or the mastery critical path. ## Desktop - Added Temml (vendored, self-contained) and render LaTeX spans in model-authored text: inline `$...$` / `\(...\)` and display `\[...\]`, with careful escaping so only intended spans are transformed. - Line math does not affect answer-choice semantics: choice comparison stays on raw text; correctness is still a local comparison against the stored answer key. ## Build / lint - Bundle is now minified (`esbuild minify: true`), reducing `dist/plugin.js` from ~597 KiB to ~315 KiB (under the 512 KiB soft limit). - Bundle lint gate reworked for minified output (unanchored import-specifier checks, colour rule uses a fail-closed hex allowlist built from the vendored Temml palette instead of section markers). - `scripts/install.py` re-implements the same gate so a stale lint script can't ship a bad bundle. ## Tests - `npm test`: 21/21 (a11y + math rendering spot checks, axe-core). - `npm run typecheck` / `npm run build` green. - `pytest`: 450 passed; the 5 known pre-existing Windows failures on `main` are unchanged.
Desktop half: model-authored strings (tutor prose and claims, reasoning
spans, check prompts/choices/feedback, assignment questions and
explanations) now render through a shared MathText component
(desktop/src/components/MathText.tsx) backed by desktop/src/math.ts, which
splits text on the $...$ / \(...\) / $$...$$ / \[...\] delimiters and
renders each math region to MathML with the vendored Temml library. The
Hermes desktop shell (Electron/Chromium) renders MathML Core natively, so
no renderer CSS or webfonts are needed; annotate keeps the TeX available to
assistive technology (NFR-001), and unparseable TeX falls back to plain
text (REQ-019.2). Learner-authored text is never math-rendered.

Bundle lint (lint-bundle.mjs and its install.py port): the hard-coded
colour rule now applies to first-party sections only, exempting the
node_modules sections esbuild marks in unminified output (third-party
colour tables, e.g. Temml's, are not UI styling).

Backend: the tutor, assignment and diagnostic prompts now ask the model to
emit LaTeX in the supported delimiters (REQ-019.4) so the desktop half can
render it consistently.
dist/plugin.js drops from ~597 KiB to ~315 KiB, comfortably under the
512 KiB BUNDLE_SOFT_LIMIT that older Hermes Desktop shells effectively
impose.

The lint gate (lint-bundle.mjs and its install.py port) is reworked for
minified output:

- import-specifier scan no longer anchors to line starts (the minified
  bundle packs many imports onto one line);
- the jsx()/jsxs() call-name smoke check is dropped: minification renames
  the bindings, and the react/jsx-runtime import itself survives
  tree-shaking only when the automatic runtime is actually used;
- the hard-coded-colour rule can no longer locate vendored code by
  esbuild's unminified `// <path>` section comments, so it allowlists hex
  literals that appear in the vendored Temml dist file (its LaTeX colour
  table) instead; every other colour literal is authored UI styling and
  fails, and a missing vendor file means an empty allowlist (fail-closed).

design.md constraints updated accordingly.
crowmaki deleted branch feat/issue-7-latex-rendering 2026-08-29 20:11:15 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crowmaki/hermes-learning!12
No description provided.