feat: label code fences so Vicinae can colour them #10

Merged
adrianbonpin merged 1 commits from feat/code-blocks into prod 2026-10-03 21:37:12 +00:00
1 Commits
Author SHA1 Message Date
adrianbonpin f6c8471045 feat: label code fences so Vicinae can colour them
Nothing needed building for the dark code panel: MdCodeBlock.qml already
provides a rounded secondaryBackground panel, a header naming the
language, a Copy button with "Copied!" feedback, and horizontal scroll.
The language string is the only missing piece, and it is also what turns
on highlighting. syntax::highlight resolves it with
definitionForName(language) and then definitionForFileName("file." +
language), so `bash` and `ts` colour correctly while an unrecognised
string such as `terminal` still renders a label but produces no
highlighting at all.

Two changes:

- The default prompt now requires a language on every fence, and forbids
  leaving commands inline in a sentence or padding them with a leading $,
  so commands stay copy-pasteable.
- code.ts labels fences the model left bare. It is deliberately
  conservative, because a wrong label is worse than none: it claims bash
  only on a clear shell signal, json only when the body actually parses,
  ts only on TypeScript-specific syntax, and leaves plain JavaScript
  alone rather than guessing.

Verified by rendering a probe with four fences and reading the result:

  ```bash     -> "bash" label, "git" coloured
  ```        -> no label, no colouring
  ```ts       -> "ts" label, const/number/length coloured
  ```terminal -> "terminal" label, no colouring

`bash` is used over `terminal` for shell commands precisely because
`terminal` costs the colouring.

Also fixes an index bug in labelCodeFences found by its own test: the
unlabelled branch pushed the wrong line back, duplicating code instead of
preserving the opening fence.

typecheck, eslint, 156 tests and vici build all pass.
2026-10-04 05:36:21 +08:00