Skip to main content

Module source

Module source 

Source
Expand description

Syntax highlighting for the source view — the AST read as markup rather than as rendered text.

crate::View::Wysiwyg resolves the document’s markup away and styles what is left; crate::View::Source shows the markup itself, and until now showed it unstyled. This module is the missing half: a SourceMap of styled byte ranges over Doc::source, so a frontend painting raw source can tell a heading from its # , a link from its destination, and a fence from the code inside it.

§Why this and not a syntax-highlighting library

leaf already has a parse of these exact bytes — twig’s, the one the caret rides. A second parser (syntect, tree-sitter) is a second opinion about what the document is, and the two disagreeing is visible: text painted as emphasis that the editor then refuses to treat as emphasis. Reading the styling off the same AST the editing model uses makes that class of bug unrepresentable.

It also costs nothing per format. twig normalizes Markdown, Djot, HTML and XML into one Kind vocabulary, so <b>bold</b>, **bold** and *bold* all arrive as Kind::Strong and are styled by the same line of code.

§The rule

Every node knows its whole extent (FlatNode::span) and, where it has delimiters, the extent of what is inside them (FlatNode::content_span). The difference between the two is exactly the markup:

  [link](https://example.dev)
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^  span
   ^^^^                        content_span
  ^    ^^^^^^^^^^^^^^^^^^^^^^  the gaps — the markup

So the whole highlighter is: style a node’s span by its kind, then restyle the bytes its content doesn’t cover as Role::Delimiter. Children paint over their parents, inheriting the parent’s style the same way crate::wysiwyg threads a base down the tree — which is what keeps *em* inside a heading both heading-colored and italic.

§What it does not do

The inner language of a fenced code block. ```rust gets Role::Code over the whole body; twig knows the fence and the info string, not Rust. Highlighting that is the one job an external highlighter is actually right for, and it belongs in the frontends that can afford the dependency — not in a core that also ships to wasm and iOS.

Bytes no node covers. A link-reference definition and a footnote definition hang off no parent (see Editor::definitions), and twig leaves some inter-element whitespace unparented; the walk starts at the root, so those stay Role::Body. Unstyled is the correct failure here — the text is still the text.

Structs§

SourceMap
The source view’s styling, as non-overlapping runs in ascending order.
StyledRun
A run of source bytes that share one style. Ranges are source byte offsets, like the caret and crate::Highlight, so nothing has to be converted to paint one.

Functions§

build
Style the source of a parsed document.