Code Enrichment
Adds diff/line/word-highlight decorations to fenced code blocks after syntax highlighting.
The codeEnrichment feature decorates fenced code blocks with per-line/per-word annotations — diff markers, line highlighting, and word highlighting. It runs as a hast-phase visitor after syntax highlighting, so it operates on the already-tokenized <span class="line"> output.
Opt-in feature
This feature is disabled by default. Enable it with the codeEnrichment key in zfb.config.ts. It is an object-typed feature, so it must be given an options object ({} or fields) — the true shorthand is rejected.
Title bar is a separate, always-on feature
The filename/title bar shown above a titled fence (.code-block-container / .code-block-title) comes from a separate, always-on core mechanism — not from codeEnrichment. It renders whether or not codeEnrichment is enabled. See Code Title.
Configuration
export default defineConfig({
markdown: {
features: {
codeEnrichment: {},
},
},
});All three enhancements (diff markers, line highlighting, and word highlighting) are active by default. Disable any individually:
codeEnrichment: {
diffMarkers: false,
lineHighlight: true,
wordHighlight: true,
}Diff markers
Append / or / comments at line ends. The marker is stripped from the output, and the line receives a data-line-diff attribute (added or removed):
const unchanged = 1;
const removed = 2;const added = 3;Supported comment styles match the language: / (JavaScript/TypeScript/Rust), # (Python/Ruby/Shell), -- (SQL/Lua).
Line highlighting
Add brace-delimited ranges to the fence info-string. Matching lines receive a data-line-highlight="true" attribute:
const a = 1;
const b = 2;
const c = 3;
const d = 4;
const e = 5;The fence above was authored as:
```js {1,3-5}
const a = 1;
const b = 2;
const c = 3;
const d = 4;
const e = 5;
```Supported range syntax: single numbers ({3}), inclusive ranges ({3-5}), and combinations ({1,3-5,8}).
Word highlighting
Add whitespace-delimited / expressions to the fence info-string. Every visible occurrence of the phrase in the block is wrapped in a .highlighted-word span, preserving syntax-highlighting markup at the match boundaries:
const answer = 42;
console.log(answer);The fence above was authored as:
```js title="word-demo.js" /answer/
const answer = 42;
console.log(answer);
```Multiple expressions are space-separated (/); a literal slash inside a phrase is escaped as \/ (/). Malformed or unterminated expressions are silently ignored.
Copy and wrap buttons
The copy and word-wrap toggle buttons are added by client-side JavaScript at runtime; they are not present in the server-rendered HTML. This runs unconditionally on every highlighted code block — independent of whether codeEnrichment is configured. When hydrated, the copy button markup is button.code-btn.code-btn-copy containing svg.code-icon.code-icon-copy.
Word wrap is a page-wide preference, not a per-block one: toggling any wrap button wraps every code block on the page, and the choice is remembered for the browser-tab session (sessionStorage, key zudo-doc-code-wrap) so it survives a reload. The toggle is only offered on blocks whose content actually overflows — a block that already fits never shows one, whether wrap is on or off.
Emitted DOM
| Trigger | Emitted element(s) | Class names |
|---|---|---|
| Diff marker line | <span class="line" data-line-diff="added|removed"> | span.line[data-line-diff] |
| Highlighted line | <span class="line" data-line-highlight="true"> | span.line[data-line-highlight] |
| Word match | wraps the matched visible text | .highlighted-word |