Skip to content

feat(highlight): user-supplied sublime-syntax via syntaxes/ next to the deck#122

Merged
mizzy merged 1 commit into
mainfrom
issue-116-user-syntaxes
Jul 5, 2026
Merged

feat(highlight): user-supplied sublime-syntax via syntaxes/ next to the deck#122
mizzy merged 1 commit into
mainfrom
issue-116-user-syntaxes

Conversation

@mizzy

@mizzy mizzy commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Closes #116

Summary

  • Introduces peitho_core::highlight::Highlighter — a newtype owning syntect::parsing::SyntaxSet, threaded through parse_markdown and render_deck as &Highlighter. The old OnceLock<SyntaxSet> global and the free validate_language / highlight_html are deleted; no free function on highlight:: takes a language token without a &Highlighter anymore, so the "default set only" path is unrepresentable at the API surface.
  • Highlighter::with_user_dir(dir) augments the built-in set with *.sublime-syntax files under dir. A malformed file becomes a line-numbered BuildError (silent drop forbidden). An empty syntaxes/ behaves like defaults.
  • The CLI discovers syntaxes/ next to the deck by convention (same shape as layouts/ / css/) — no CLI flag added, per author decision. peitho build --watch rebuilds on .sublime-syntax changes.

Three lenses

  • Long-term — any DSL (Carina .crn, TypeScript, custom repo languages) gains highlighting without peitho having to know about it. Also unblocks a workable answer for Unknown-language help text suggests 'ts', but syntect's default set has no TypeScript #105 (TypeScript missing from defaults): drop a TS .sublime-syntax in syntaxes/.
  • Type safetyHighlighter is the only way to reach find_syntax_by_token. A caller cannot forget user syntaxes; the type requires an instance.
  • Root cause — the reason a .crn block was rejected before was not "Carina is missing" (symptom) but "the syntax set is baked in at process init with no injection point" (root). The one upstream fix threads a Highlighter through the pipeline.

All three lenses agreed unambiguously, so this shape was chosen without ambiguity.

What is NOT in this PR (by explicit plan decision)

Test plan

  • cargo test --workspace (x3)
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo fmt --all --check
  • git diff --exit-code bindings/
  • cd packages/peitho-present && npm run build && npm test && npm run typecheck
  • git diff --exit-code packages/peitho-present/dist/shell.js
  • Headline test: build_artifacts_uses_syntaxes_dir_next_to_the_deck — a deck with a ```carina block plus syntaxes/carina.sublime-syntax next to it builds and produces hl-* spans.
  • Reversal test: user_dir_validates_carina_and_defaults_reject_it — same carina token is a build error under Highlighter::defaults().

Design record: docs/plans/2026-07-05-user-syntaxes.md.

🤖 Generated with Claude Code

…he deck

Introduce a Highlighter newtype that owns the syntect SyntaxSet, threaded
through parse_markdown and render_deck. Delete the OnceLock global and
the free validate_language / highlight_html functions so no caller can
look up a language token against an unconfigured default set.

Highlighter::with_user_dir(dir) augments the built-in set with any
*.sublime-syntax files under dir; malformed files are line-numbered
BuildErrors (silent drop forbidden). The CLI discovers syntaxes/ next
to the deck by convention, mirroring layouts/ and css/, and --watch
rebuilds on .sublime-syntax changes.

Closes #116

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mizzy mizzy merged commit cf3032a into main Jul 5, 2026
3 checks passed
@mizzy mizzy deleted the issue-116-user-syntaxes branch July 5, 2026 07:34
@mizzy mizzy mentioned this pull request Jul 5, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support syntax highlighting for languages outside syntect's default set (e.g. Carina .crn)

1 participant