# Markdown
`deft/stdext/markdown` (`md`) is the Deft-side markdown engine behind the
TUI markdown viewer: line classification, inline span rendering (`code`,
bold, links), word wrapping, fenced-code extraction, viewport
drawing, and a parse-once layout model used for hit-testing, selection
and scrolling.
import "deft/stdext/markdown" as md
This page documents the module API. The widget that uses it is described
in Widgets and Protocols, and the
draw primitives it renders with in Graphics.
## Classifying Lines
| Def | Signature | Description |
|---|---|---|
| `is-heading` / `is-subheading` / `is-h3` | `{| line |}` | `# ` / `## ` / `### ` prefixes |
| `is-code-fence` | `{| line |}` | Trimmed ` ``` ` or `~~~` |`
| `is-list-item` | `{| line |}` | Bullet or numbered opener |
| `list-prefix` | `{| line |}` | Rendered marker (`"• "` or `"N. "`), or nil |
| `is-table-row` / `is-table-separator` | `{| line |}` | Leading `|`; separator is pipes/dashes/spaces |
| `is-blockquote` | `{| line |}` | `"> "` |
## Drawing
| Def | Signature | Description |
|---|---|---|
| `default-colors` | `{||}` | Color map from the active theme's `:markdown` block, else built-in defaults |
| `draw-lines` | `{| ctx x y vp-height scroll lines max-w colors highlight-fn |}` | Scrollable viewport draw; clamps scroll, pre-scans fences |
| `draw-markdown-line` | `{| ctx x y line max-w colors in-code highlight-fn |}` | Draw one line; returns the next `in-code` state |
| `draw-markdown-line-wrapped` | `{| ctx x y line max-w colors in-code highlight-fn |}` | Same but wraps prose/headings/lists/quotes; tables/code truncate |
| `draw-inline` | `{| ctx x y line max-w text-fg text-bg code-fg code-bg bold-fg link-fg |}` | Inline spans within a line |
| `rule-for` / `draw-rule-line` | `{…}` | Optional whole-line rules (e.g. diff `+`/`-` lines) from `:line-rules` |
`highlight-fn` is `{| line | -> per-character color vector}` or nil for
uniform code colors; consumers pass the syntax registry
dispatch.
## Layout Engine
`build-layout` parses lines once into entries; the renderer, hit-testing
and selection all read the same structure.
| Def | Signature | Description |
|---|---|---|
| `build-layout` | `{| lines max-w rules |}` | `%{ entries total-rows blocks }` |
| `line-at-row` | `{| layout row |}` | Display row → source line index |
| `entry-at-line` | `{| layout line-idx |}` | Layout entry for a source line |
| `compute-line-rows` | `{| line max-w in-code |}` | `%{ in-code rows }` without drawing |
| `extract-code-at-line` | `{| lines line-idx |}` | `%{ code lang }` for the enclosing fence, or nil |
| `wrap-plain` / `wrap-markdown` | `{| text max-w |}` | Wrap a plain string / markdown text into display lines |
Layout entry: `%{ line row rows type lang? rule? }`, with `:type` one of
`:fence-open :fence-close :code :heading :subheading :h3 :table-sep`
:table-row :blockquote :list :text :empty :rule`. `:blocks` holds`
inclusive fence spans `@{ %{ start end lang } }` (an unclosed fence ends
at EOF).
## Example
set colors [merge [md/default-colors] %{ heading-fg "#ffd54f" }] [md/draw-lines $ctx 1 1 $vp-height $scroll $lines $max-w $colors nil] set layout [md/build-layout $lines 40 $rules] set src-line [md/line-at-row $layout $display-row] set code [md/extract-code-at-line $lines $cursor-line]
## Colors
`default-colors` keys: `heading-fg subheading-fg h3-fg code-fg code-bg`
bold-fg link-fg list-fg table-border-fg table-header-fg blockquote-fg
blockquote-bar-fg text-fg text-bg`, plus optional `:line-rules`. Set the`
`[theme]` `:markdown` section to retheme every viewer at once.
## See Also
- Syntax — source of `highlight-fn`
- Widgets and Protocols — `markdown-viewer`
- Graphics — `draw/*` primitives