pub struct VRow {
pub glyphs: Vec<Glyph>,
pub end_src: usize,
pub decoration: bool,
pub code: bool,
pub code_lang: Option<String>,
pub directive: bool,
pub directive_label: Option<String>,
pub media: Option<MediaMark>,
pub task: Option<bool>,
pub leaf_directive: Option<DirectiveMark>,
pub heading: Option<u8>,
pub boundary: Option<Boundary>,
}Expand description
One visual line. end_src is the source offset a caret sits at when placed
at the line’s end (past its last glyph) — the anchor for end-of-line and
click-past-content.
Clone so a block’s rows can be cached and re-emitted at a shifted offset
across an edit — see BlockCache.
Fields§
§glyphs: Vec<Glyph>§end_src: usize§decoration: boolA row that is drawn but holds no caret: a table’s ├───┼───┤ rules, and
the blank gap a block boundary is spelled with. Vertical motion steps
over it, pos_of_offset never resolves onto it, and its stops (it has
none) and end_src stay out of the map’s stop table.
Emptiness isn’t the test — an empty paragraph is a blank row too, and a real caret stop. The test is whether the row is somewhere text can go.
code: boolThis row is one line of a fenced or indented code block. Set on every row
the "code_block" arm emits — including its blank lines, which carry no
glyph to tell them apart otherwise. A frontend draws its own chrome (a
border and a tinted background) around each maximal run of these, and
scrolls them horizontally instead of wrapping; see
VisualMap::code_blocks. Survives the row shuffling of BlockCache
reuse and build_spliced because it rides on the row, not on a
row-index span the way a table’s picture does.
code_lang: Option<String>A fenced code block’s info string (its language), carried on the first
row of the block so it survives row reuse the way code
does. None on every other row, and on an indented block (which has no
fence to label). A frontend paints it as a small label on the block’s box
and edits it through a prompt — see CodeBlockInfo::lang. It’s a plain
display string, not a source slice, so it needs no offset shifting; the
label re-derives from twig on the next build.
directive: boolThis row belongs to a :::name{.class} directive container — twig’s
generic fenced-div block, whose meaning is entirely up to the host app
(diaryx’s :::vis{.audience} visibility blocks, say). Set on every row
the "directive" arm emits, the same way code marks a
code block’s rows, so a frontend can draw a tinted panel around each
maximal run of these.
directive_label: Option<String>A directive container’s space-joined attrs — dot-prefixed classes
(.public .family → "public family") unioned with bare pandoc-style
words (public family, no leading dot — diaryx’s other :::vis{...}
convention), carried on the block’s first row only — the
code_lang pattern. None on every other row, and
when the directive carries no such attrs. A frontend paints it as a
small label on the block’s panel; it’s a plain display string, not a
source slice, so it rides row reuse untouched.
media: Option<MediaMark>Set on the single placeholder row a block-level image renders to, carrying
the image’s destination and alt text; None on every other row. The row’s
glyphs are the default 🖼 alt label (which a plain surface paints as-is);
an image-capable frontend reads this to paint the real picture instead,
skipping the row named by MediaInfo::rows_span. Like
code_lang it’s plain display strings, not source
slices, so it rides row reuse and needs no offset shifting; the map’s
images side-table is derived from it once the rows
are final, the same way code_blocks is.
task: Option<bool>Set on the first row of a task list item, carrying whether its box is
ticked; None on every other row, including a plain list_item’s. The
row’s glyphs already draw the box as ☐ /☑ in the marker’s place, so a
plain surface needs nothing further; a GUI reads this to paint a real
checkbox widget and to know which way it is facing.
A bool rather than a source span, for the reason
code_lang is a plain string: it rides BlockCache
reuse and build_spliced untouched, needing no offset shifting. To
toggle the box, a frontend maps its click to a source offset the way it
maps any other — the marker’s glyphs carry the item’s own src — and
hands that to crate::Doc::toggle_task_at.
leaf_directive: Option<DirectiveMark>Set on the single placeholder row a leaf directive (::name{…})
renders to, carrying its name and attributes; None on every other row.
The container form isn’t this — it wraps real blocks and marks each of
them directive instead. Like image
it’s plain display strings, so it rides row reuse untouched, and the map’s
directives side-table is derived from it once
the rows are final.
heading: Option<u8>The heading level (1–6) of the block this row belongs to, on every row a
heading emits (a long one wraps to several) and None everywhere else.
A frontend that sizes a whole line — a proportional renderer giving the
row a bigger line box — needs the level per row, and the glyphs can’t
always supply it: an empty heading (# with nothing typed after it,
which is what the toolbar’s H1 leaves on a blank line) has no glyph to
carry a Role::Heading at all, so a glyph scan called it body text and
the line drew at body height until the first character landed. Riding the
row says it once, for the empty case and the wrapped case alike.
Per-glyph styling still comes from Role::Heading on the glyphs; this
is the row-level fact, and the two agree wherever a heading has content —
same u8 level, clamped the same way [heading_style] clamps it.
boundary: Option<Boundary>What this row divides, on the blank rows a block boundary is drawn with
and None on every other row — including the navigable blank lines of
preserve-soft flow, which are somewhere text can go rather than a gap
between blocks. So boundary.is_some() is exactly “this row is a drawn
block boundary”, the decoration rows that come from
[Builder::emit_separators_before].
It exists because a boundary’s height is a frontend decision but its kind is not. Typography spaces a boundary by what it separates — the margin above a heading is wider than the one between two paragraphs, so the heading groups with the text it introduces — and a frontend that has only rows to look at has to re-derive the structure by sniffing glyph roles. Three frontends sniffing separately is three chances to disagree about the same document. Core already knows, having just walked the AST to emit this row, so it says so once here and each frontend multiplies by its own spacing.