Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.render

Transient Markdown parsing and renderer projections.

Canonical answers are role-labelled, string-keyed content blocks from com.blockether.vis.internal.content. Parsed Markdown trees are created only inside renderers and are never transported or persisted.

markdown->ast parses prose for renderer-local layout. render, extract-code, extract-text, and session->markdown are disposable projections; none of their intermediate trees are canonical message data.

Transient Markdown parsing and renderer projections.

Canonical answers are role-labelled, string-keyed content blocks from
`com.blockether.vis.internal.content`. Parsed Markdown trees are created only
inside renderers and are never transported or persisted.

`markdown->ast` parses prose for renderer-local layout. `render`,
`extract-code`, `extract-text`, and `session->markdown` are disposable
projections; none of their intermediate trees are canonical message data.
raw docstring

*soft-break*clj

How a CommonMark SoftLineBreak (a bare between two non-blank lines) is lifted into IR. CommonMark prose semantics collapse a soft break to a single space, which is correct for model-authored answers and thinking. User-typed / pasted input is line-oriented (an input box, not a prose document): a literal newline is intent, so we lift it to [:br] to preserve the pasted shape (code, line-numbered dumps, tables). Bound to :hard via (markdown->ast text {:soft-break :hard}). Default :space keeps every existing caller unchanged.

How a CommonMark SoftLineBreak (a bare `
` between two non-blank
   lines) is lifted into IR. CommonMark prose semantics collapse a soft
   break to a single space, which is correct for model-authored answers
   and thinking. User-typed / pasted input is line-oriented (an input
   box, not a prose document): a literal newline is intent, so we lift
   it to `[:br]` to preserve the pasted shape (code, line-numbered
   dumps, tables). Bound to `:hard` via `(markdown->ast text {:soft-break
   :hard})`. Default `:space` keeps every existing caller unchanged.
sourceraw docstring

->astclj

(->ast v)

Soft-normalize any answer-input value into canonical [:ast & blocks]. Pure, total, idempotent.

Identity-preserving: when the input already satisfies the canonical invariants (canonical?), the return value is the SAME object. This keeps downstream System/identityHashCode caches (format-answer-with-thinking-data, etc.) hot across repeated render passes — walker output is computed once per canonical IR identity, not once per equal-but-fresh allocation.

Before canonicalization, Hiccup child positions are walked with clojure+.walk semantics and non-vector sequential values (notably lazy seqs from (map ...) inside renderer input) are safely realized to at most 100 items, then replaced with an explicit … many more marker when truncated. This avoids persisting Java LazySeq identity strings and avoids hanging on infinite seqs.

See namespace docstring for the full canonical-form invariants.

Soft-normalize any answer-input value into canonical [:ast & blocks].
Pure, total, idempotent.

Identity-preserving: when the input already satisfies the canonical
invariants (`canonical?`), the return value is the SAME object.
This keeps downstream `System/identityHashCode` caches
(`format-answer-with-thinking-data`, etc.) hot across repeated
render passes — walker output is computed once per canonical IR
identity, not once per equal-but-fresh allocation.

Before canonicalization, Hiccup child positions are walked with
`clojure+.walk` semantics and non-vector sequential values (notably
lazy seqs from `(map ...)` inside renderer input) are safely realized to
at most 100 items, then replaced with an explicit `… many more`
marker when truncated. This avoids persisting Java LazySeq identity
strings and avoids hanging on infinite seqs.

See namespace docstring for the full canonical-form invariants.
sourceraw docstring

ast?clj

(ast? x)

True when x is a canonical [:ast ...] AST.

True when x is a canonical [:ast ...] AST.
sourceraw docstring

block-structurally-silent?clj

(block-structurally-silent? form-source)

True when the block source carries NO :code segment — it is purely structural engine chrome (a bare title call). The engine stamps such a block + its stream chunk with :vis/silent? true so channels drop the whole entry from display (web folds it on :silent, the TUI hides the form slot). Any block that DOES carry a :code segment flows through and its raw source paints unconditionally.

True when the block source carries NO `:code` segment — it is purely
structural engine chrome (a bare title call). The engine stamps such a
block + its stream chunk with `:vis/silent? true` so channels drop the
whole entry from display (web folds it on `:silent`, the TUI hides the
form slot). Any block that DOES carry a `:code` segment flows through and
its raw source paints unconditionally.
sourceraw docstring

canonical?clj

(canonical? x)

Cheap structural check: x is already a canonical [:ast & blocks] AST. When true, (->ast x) is the identity (returns the same object), so downstream caches keyed on System/identityHashCode hit cleanly across repeated render passes.

Cheap structural check: `x` is already a canonical `[:ast & blocks]`
AST. When true, `(->ast x)` is the identity (returns the same
object), so downstream caches keyed on `System/identityHashCode`
hit cleanly across repeated render passes.
sourceraw docstring

diff-line-kindclj

(diff-line-kind line)

Classify ONE unified-diff line for channel-neutral colouring: :meta (file headers ---/+++), :hunk (@@), :add (+), :del (-), or :ctx (context / unchanged). The SINGLE classifier both channels share — the TUI maps the kind to an ANSI colour, the web to a CSS class — so a diff fence colours IDENTICALLY in both, from one source of truth (no per-channel copy to drift).

Classify ONE unified-diff line for channel-neutral colouring: `:meta` (file
headers `---`/`+++`), `:hunk` (`@@`), `:add` (`+`), `:del` (`-`), or `:ctx`
(context / unchanged). The SINGLE classifier both channels share — the TUI maps
the kind to an ANSI colour, the web to a CSS class — so a `diff` fence colours
IDENTICALLY in both, from one source of truth (no per-channel copy to drift).
sourceraw docstring

extract-codeclj

(extract-code input)

Walk the AST and return a vector of strings, one per [:code ...] block, in source order. Used by vis --code.

Walk the AST and return a vector of strings, one per [:code ...] block,
in source order. Used by `vis --code`.
sourceraw docstring

extract-textclj

(extract-text input)

Walk the AST and return concatenated plain-text content of all [:p] blocks (inline content stripped). Used by voice TTS.

Walk the AST and return concatenated plain-text content of all [:p]
blocks (inline content stripped). Used by voice TTS.
sourceraw docstring

markdown->astclj

(markdown->ast text)
(markdown->ast text {:keys [soft-break]})

Parse a Markdown string into canonical transient Markdown tree. Idempotent: when the input is already canonical IR, returns it unchanged (identical? preserved — cache-friendly).

This is the SINGLE entry point for turning Markdown source into IR. Used by:

  • the final-answer pipeline (model's plain-prose Markdown answer)
  • thinking text from the model
  • user-typed messages from the TUI input box

Returns canonical [:ast & blocks] directly (no further ->ast round-trip needed). Empty / nil input yields [:ast {}].

Implementation: commonmark-java parser + GFM tables / strikethrough extensions, then a faithful Node→IR walker. Soft line breaks collapse to a single space; hard line breaks become [:br].

opts (2-arity) currently understands {:soft-break :hard}, which lifts every bare newline to [:br] instead of a space — used for line-oriented user/pasted input so the rendered bubble keeps the exact line structure the user typed. Default keeps prose semantics.

Parse a Markdown string into canonical transient Markdown tree.
Idempotent: when the input is already canonical IR, returns it
unchanged (`identical?` preserved — cache-friendly).

This is the SINGLE entry point for turning Markdown source into IR.
Used by:
  - the final-answer pipeline (model's plain-prose Markdown answer)
  - thinking text from the model
  - user-typed messages from the TUI input box

Returns canonical `[:ast & blocks]` directly (no further `->ast`
round-trip needed). Empty / nil input yields `[:ast {}]`.

Implementation: commonmark-java parser + GFM tables / strikethrough
extensions, then a faithful Node→IR walker. Soft line breaks collapse
to a single space; hard line breaks become `[:br]`.

`opts` (2-arity) currently understands `{:soft-break :hard}`, which
lifts every bare newline to `[:br]` instead of a space — used for
line-oriented user/pasted input so the rendered bubble keeps the
exact line structure the user typed. Default keeps prose semantics.
sourceraw docstring

normalize-reasoningclj

(normalize-reasoning text)

Canonical normalization for model reasoning / thinking text before it is rendered as a trace. Reasoning streams carry whitespace-padded blank rows (trailing spaces/tabs the model emits) and paragraph-style double newlines that make the compact thinking block look ragged (glm-5.2 especially). Strip per-line trailing whitespace, collapse every run of newlines down to ONE line break, then give the trace BREATHING ROOM: a line that ENDS A SENTENCE (./!/?/, optionally closed by a quote/paren/bracket) and is followed by more text gets a blank line after it, so consecutive sentences read as separate paragraphs instead of a wall. Finally trim. Shared by every channel so the TUI bubble and the web thinking card normalize identically.

Canonical normalization for model reasoning / thinking text before it is
rendered as a trace. Reasoning streams carry whitespace-padded blank rows
(trailing spaces/tabs the model emits) and paragraph-style double newlines
that make the compact thinking block look ragged (glm-5.2 especially). Strip
per-line trailing whitespace, collapse every run of newlines down to ONE line
break, then give the trace BREATHING ROOM: a line that ENDS A SENTENCE
(`.`/`!`/`?`/`…`, optionally closed by a quote/paren/bracket) and is
followed by more text gets a blank line after it, so consecutive sentences
read as separate paragraphs instead of a wall. Finally trim. Shared by every
channel so the TUI bubble and the web thinking card normalize identically.
sourceraw docstring

parse-block-displayclj

(parse-block-display form-source)

Return the model's authored source as ONE verbatim :code segment.

The engine is full-Python: the source is Python and we keep it VERBATIM here — exactly what the model wrote, no splitting, no classification. This is the canonical segment (tests + the model's own context depend on it being the raw bytes). Channels that want a beautified view call prettify-python at paint time; the IR stays raw.

Pure helper. Never throws. Blank / nil input returns [].

Return the model's authored source as ONE verbatim `:code` segment.

The engine is full-Python: the source is Python and we keep it VERBATIM here —
exactly what the model wrote, no splitting, no classification. This is the
canonical segment (tests + the model's own context depend on it being the raw
bytes). Channels that want a beautified view call `prettify-python` at paint
time; the IR stays raw.

Pure helper. Never throws. Blank / nil input returns `[]`.
sourceraw docstring

prettify-pythonclj

(prettify-python src)

Beautify Python src via ruff (long calls/collections wrapped multiline, black-style) for DISPLAY at a CHANNEL boundary. NOT applied to the canonical :code IR (which stays VERBATIM — the executed/stored source, and the model's exact bytes), so channels opt in when painting. Cached (bounded LRU) and verbatim-safe: format-or returns src unchanged when ruff is unavailable or the snippet isn't valid Python (partial streams, prose), so it never changes meaning and never throws. ruff runs in-process via clj-ruff — ONE process-wide cdylib, leak-free (confined arena + ruff_free_string per call).

Beautify Python `src` via ruff (long calls/collections wrapped multiline,
black-style) for DISPLAY at a CHANNEL boundary. NOT applied to the canonical
`:code` IR (which stays VERBATIM — the executed/stored source, and the
model's exact bytes), so channels opt in when painting. Cached (bounded LRU)
and verbatim-safe: `format-or` returns `src` unchanged when ruff is
unavailable or the snippet isn't valid Python (partial streams, prose), so it
never changes meaning and never throws. ruff runs in-process via clj-ruff —
ONE process-wide cdylib, leak-free (confined arena + `ruff_free_string` per call).
sourceraw docstring

reasoning->astclj

(reasoning->ast text)

Reasoning / thinking text -> canonical transient Markdown tree. The SINGLE shared entry point for rendering a model's thinking trace (TUI thinking bubble AND the web thinking card), so both channels paint the SAME structure. Reasoning is line-oriented (a trace, not flowing prose): normalize via normalize-reasoning then lift every bare newline to a HARD break ([:br]) via {:soft-break :hard}. Without the hard break a bold heading collapses onto its body line (the TUI **heading** body bug); with it the heading keeps its own line, matching the web ticker's marked({:breaks true}).

Reasoning / thinking text -> canonical transient Markdown tree. The SINGLE shared entry
point for rendering a model's thinking trace (TUI thinking bubble AND the web
thinking card), so both channels paint the SAME structure. Reasoning is
line-oriented (a trace, not flowing prose): normalize via `normalize-reasoning`
then lift every bare newline to a HARD break (`[:br]`) via `{:soft-break
:hard}`. Without the hard break a bold heading collapses onto its body line
(the TUI `**heading** body` bug); with it the heading keeps its own line,
matching the web ticker's `marked({:breaks true})`.
sourceraw docstring

reasoning-collapse-min-hiddenclj

Minimum number of HIDDEN reasoning rows required before a thinking trace is COLLAPSED behind a disclosure at all. If the remainder beyond the preview is smaller than this, the whole trace renders inline — a +1 more toggle that only reveals one extra line is pure friction. One source of truth shared by the TUI thinking bubble and the web thinking card.

Minimum number of HIDDEN reasoning rows required before a thinking trace is
COLLAPSED behind a disclosure at all. If the remainder beyond the preview is
smaller than this, the whole trace renders inline — a `+1 more` toggle that
only reveals one extra line is pure friction. One source of truth shared by
the TUI thinking bubble and the web thinking card.
sourceraw docstring

reasoning-preview-line-limitclj

Canonical reasoning PREVIEW height shared by every channel. Up to this many rows/lines of a thinking trace stay visible; the remainder folds behind a +N more disclosure (web) / ▸ THINKING +N more toggle (TUI). One source of truth so the TUI bubble and the web card clamp reasoning to the SAME height.

Canonical reasoning PREVIEW height shared by every channel. Up to this many
rows/lines of a thinking trace stay visible; the remainder folds behind a
`+N more` disclosure (web) / `▸ THINKING +N more` toggle (TUI). One
source of truth so the TUI bubble and the web card clamp reasoning to the
SAME height.
sourceraw docstring

renderclj

(render input flavor)
(render input flavor opts)

Render any answer input into a flavor.

Input: string | Hiccup vector | [:ast ...] AST | sequential of mixed Flavor: :html | :markdown | :plain Opts: {:context #{:answer :thinking :status :error} :max-length int - hard cap; truncate at paragraph boundary}

Render any answer input into a flavor.

Input:  string | Hiccup vector | [:ast ...] AST | sequential of mixed
Flavor: :html | :markdown | :plain
Opts:   {:context    #{:answer :thinking :status :error}
         :max-length int  - hard cap; truncate at paragraph boundary}
sourceraw docstring

search-textclj

(search-text v)

Universal plain-text projection for full-text search / clipboard / logging. Accepts canonical IR, a markdown string, or anything ->ast can coerce; returns a single concatenated string suitable for FT5 indexing or substring matching.

IR-side rendering: all prose/list/quote/table text collapses to spaces; :code/:c bodies are included verbatim (often the highest-signal text for search). Strings are parsed via markdown->ast so search sees the rendered shape regardless of upstream contract.

Idempotent on parsed input via the markdown->ast shortcut.

Universal plain-text projection for full-text search / clipboard /
logging. Accepts canonical IR, a markdown string, or anything
`->ast` can coerce; returns a single concatenated string suitable
for FT5 indexing or substring matching.

IR-side rendering: all prose/list/quote/table text collapses to spaces;
`:code`/`:c` bodies are included verbatim (often the highest-signal text
for search).
Strings are parsed via `markdown->ast` so search sees the rendered shape
regardless of upstream contract.

Idempotent on parsed input via the `markdown->ast` shortcut.
sourceraw docstring

session->markdownclj

(session->markdown db-info session-ref)
(session->markdown db-info session-ref opts)

Project a full session as a Markdown document on top of the IR pipeline.

Project a full session as a Markdown document on top of the IR
pipeline.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close