pub struct VRow {Show 15 fields
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 align: Option<Align>,
pub line_height: Option<LineSpacing>,
pub boundary: Option<Boundary>,
pub mark_ends: Vec<usize>,
}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
media 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 media
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.
align: Option<Align>How this row’s block is aligned across the measure — the author’s
class="center", on every row the block emits and None for the
theme’s default, which is left.
A row fact and not a glyph one for heading’s reason,
and more sharply: alignment is a property of the line, not of the
letters on it, so an empty paragraph the author has just centred has to
carry it with no glyph to hang it on. It rides the row like a plain
Copy flag, so BlockCache reuse and build_spliced carry it
untouched.
Read from the paragraph’s or heading’s own attributes and from those of
every div around it, the nearest winning — so <div class="center">
around three paragraphs centres all three, which is what the author of
that HTML meant.
line_height: Option<LineSpacing>How far apart this row’s block sets its lines, as a multiple of the
theme’s own line height — the author’s data-line-height, on every row
the block emits and None for the theme’s spacing.
A frontend that lays rows out in pixels scales the row’s height by
LineSpacing::ratio; one that draws a row per terminal line ignores it,
the way it ignores a heading’s size. Read at the same two levels
align is.
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.
mark_ends: Vec<usize>The offsets on this row where an inline mark’s content ends under a
hidden closing delimiter — the end of the d in **bold**, one byte
before the ** that draws nothing. Each is a caret stop with no glyph
of its own: the caret standing there is drawn where the next glyph is,
but typing there extends the mark, where typing past the delimiter
leaves it. See VisualMap::mark_ends for the rule.
Source offsets, so [shift_row] moves them with the glyphs; empty on
decoration rows and on every row no mark closes on.