Skip to documentation
SLOP

tiny.zen.markdown

Reference tiny.zen markdown

Defined in tiny.zen.

API (13)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callstiny.zenmarkdown
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/zen/src/markdown.zig

zig
const std = @import("std");const code = @import("code.zig");const diagnostic = @import("diagnostic.zig");const diagram = @import("diagram/root.zig");const document = @import("document/root.zig");const footnote = @import("footnote/root.zig");const html = @import("html.zig");const markdown_model = @import("markdown");const math = @import("math/root.zig");const quiz = @import("quiz/root.zig");const slides = @import("slides/root.zig");const Allocator = std.mem.Allocator;pub const Diagnostic = diagnostic.Diagnostic;const RenderError = error{    InvalidColor,    InvalidContentsDirective,    InvalidCharacter,    InvalidData,    InvalidField,    InvalidFrame,    InlineDelimiterCapacityExceeded,    InvalidInlineLink,    InvalidJsonl,    InvalidRecord,    InvalidScale,    InvalidSemanticList,    InvalidTransform,    InlineNestingCapacityExceeded,    MissingField,    MissingKind,    UnknownData,    UnknownMark,    UnknownRecordKind,    UnknownTransform,};pub const Error = Allocator.Error || diagram.AsciiRenderError ||    diagram.DocumentError || diagram.ego.svg.FragmentError || document.Error ||    footnote.Error || math.Error || quiz.Error || RenderError;const InlineError = math.Error || error{    InlineDelimiterCapacityExceeded,    InvalidInlineLink,    InlineNestingCapacityExceeded,};const CodeDelimiter = struct {    start: usize,    end: usize,    length: usize,    closer_end: ?usize = null,};/// Maximum backtick runs in one rendered inline fragment.////// Exceeding it returns `InlineDelimiterCapacityExceeded`; split the paragraph/// or code-bearing label into smaller block-level elements. The delimiter index/// occupies at most 2.5 MiB on the supported 64-bit target and is reused by/// nested inline markup.pub const max_inline_delimiters: usize = 65_536;/// Maximum body rows in one semantic pipe table admitted by the block parser.pub const max_table_body_rows: usize = markdown_model.max_table_rows - 1;const code_delimiter_bytes: usize = 40;const max_inline_delimiter_bytes: usize = max_inline_delimiters * code_delimiter_bytes;const delimiter_capacity_reason = std.fmt.comptimePrint(    "inline source exceeds {d} backtick runs",    .{max_inline_delimiters},);const CodeDelimiters = struct {    items: []CodeDelimiter,    fn deinit(self: *CodeDelimiters, allocator: Allocator) void {        allocator.free(self.items);        self.* = undefined;    }    fn closingEnd(self: CodeDelimiters, start: usize, range_end: usize) ?usize {        var low: usize = 0;        var high = self.items.len;        while (low < high) {            const middle = low + (high - low) / 2;            if (self.items[middle].start < start) {                low = middle + 1;            } else {                high = middle;            }        }        if (low == self.items.len or self.items[low].start != start) return null;        const closer_end = self.items[low].closer_end orelse return null;        return if (closer_end <= range_end) closer_end else null;    }    fn span(        self: CodeDelimiters,        source: []const u8,        start: usize,        range_end: usize,    ) ?CodeSpan {        const closing_end = self.closingEnd(start, range_end) orelse return null;        const opener_end = backtickRunEnd(source, start);        const delimiter_length = opener_end - start;        return .{            .content = source[opener_end .. closing_end - delimiter_length],            .end = closing_end,        };    }};/// Maximum recursive link/emphasis levels, label brackets, or target parentheses.////// Exceeding it returns `InlineNestingCapacityExceeded`; split or simplify the/// nested inline markup.pub const max_inline_nesting: usize = 32;const inline_nesting_reason = std.fmt.comptimePrint(    "inline markup nesting exceeds {d} levels",    .{max_inline_nesting},);const label_nesting_reason = std.fmt.comptimePrint(    "link label nesting exceeds {d} brackets",    .{max_inline_nesting},);const target_nesting_reason = std.fmt.comptimePrint(    "link target nesting exceeds {d} parentheses",    .{max_inline_nesting},);/// Selects ordinary document HTML or slide-deck HTML.pub const Mode = enum {    /// Renders a continuous Markdown document.    document,    /// Renders explicit slides and optional speaker notes.    slides,};/// Bounds Markdown features and optionally captures a source-local diagnostic.pub const Options = struct {    /// Chooses document or slide rendering.    mode: Mode = .document,    /// Emits heading IDs when true; IDs are still inspected when false.    heading_anchors: bool = true,    /// Renders `zen-diagram` fences when true and leaves them as code when false.    ascii_diagrams: bool = true,    /// Keeps one exact call-map stylesheet per rendered page when true.    one_call_map_style_per_page: bool = false,    /// Requested ASCII width, clamped to 24...200 columns.    diagram_width: usize = 72,    /// Requested ASCII height, clamped to 8...80 rows.    diagram_height: usize = 22,    /// Controls syntax-highlighted code blocks.    code_blocks: code.Options = .{},    /// Rejects Markdown whose measured heading demand exceeds these limits.    heading_limits: document.Limits = document.default_limits,    /// Rejects Markdown whose measured footnote demand exceeds these limits.    footnote_limits: footnote.Limits = footnote.default_limits,    /// Rejects one quiz fence whose measured demand exceeds these limits.    quiz_limits: quiz.Limits = quiz.default_limits,    /// Controls slide layout when `mode` is `slides`.    slides: slides.Options = .{},    /// Receives source-local repair detail after a supported parse failure.    diagnostic: ?*diagnostic.Diagnostic = null,    /// Receives one record per rendered link and image when set.    link_report: ?*LinkReport = null,};/// Owns the rendered HTML and the storage borrowed by its document view./// Release it with `deinit` and the allocator passed to `render`.pub const Rendered = struct {    html: []u8,    document: document.Document,    document_storage: document.Storage,    pub fn deinit(self: *Rendered, allocator: Allocator) void {        allocator.free(self.html);        self.document_storage.reset();        self.document_storage.deinit(allocator);        self.* = undefined;    }};/// One link or image the renderer emitted, located in its rendered source.////// Offsets are valid only under the flag that admits them: `start` and `end`/// under `located`, the target pair under `located` and a locatable target.pub const RenderedLink = struct {    start: u32 = 0,    end: u32 = 0,    target_start: u32 = 0,    target_end: u32 = 0,    located: bool = false,    contiguous: bool = false,    image: bool = false,};/// Caller-owned, fixed-capacity sink for rendered link records.////// Records arrive in emission order, which is not document order: an/// enclosing link is recorded before the label it contains.pub const LinkReport = struct {    storage: []RenderedLink,    count: usize = 0,    overflowed: bool = false,    /// Drops every record and clears the overflow flag.    pub fn reset(self: *LinkReport) void {        self.count = 0;        self.overflowed = false;    }    /// Returns the records, borrowing `storage`.    pub fn links(self: *const LinkReport) []const RenderedLink {        return self.storage[0..self.count];    }    fn record(self: *LinkReport, link: RenderedLink) void {        if (self.count == self.storage.len) {            self.overflowed = true;            return;        }        self.storage[self.count] = link;        self.count += 1;    }};const Fence = struct {    marker: u8,    count: usize,    info: []const u8,    source_offset: usize = 0,};const EgoStylesheet = struct {    output_start: usize,    length: usize,};const QuizOwner = struct {    storage: ?quiz.Storage = null,    fn deinit(self: *QuizOwner, allocator: Allocator) void {        if (self.storage) |*storage| storage.deinit(allocator);        self.* = .{};    }    fn parse(        self: *QuizOwner,        allocator: Allocator,        source: []const u8,        limits: quiz.Limits,    ) Error!quiz.Quiz {        if (self.storage == null) {            var storage = try quiz.Storage.init(allocator, limits);            storage.activate();            self.storage = storage;        }        const storage = if (self.storage) |*active| active else unreachable;        std.debug.assert(std.meta.eql(storage.capacity.limits, limits));        return quiz.parse(storage, source);    }    fn reset(self: *QuizOwner) void {        const storage = if (self.storage) |*active| active else unreachable;        storage.reset();    }};const ListKind = enum {    unordered,    ordered,};const SemanticList = enum {    family_index,    module_index,};/// Computes exact heading, text, and ID demand without allocating.pub fn plan(source: []const u8) document.Error!document.Plan {    return planDiagnostic(source, null);}fn planDiagnostic(    source: []const u8,    diag: ?*diagnostic.Diagnostic,) document.Error!document.Plan {    try validateHeadingAnchors(source, diag);    var result = document.Plan.init(source.len);    var iterator = HeadingIterator.init(source, diag);    while (try iterator.next()) |heading| {        const id = try resolveHeadingId(source, heading);        try result.includeHeading(heading.text, try id.length());    }    return result;}/// Fills active caller-owned storage; the returned document borrows it until reset.pub fn inspect(storage: *document.Storage, source: []const u8) document.Error!document.Document {    return inspectPlanned(storage, source, try plan(source));}fn inspectPlanned(    storage: *document.Storage,    source: []const u8,    heading_plan: document.Plan,) document.Error!document.Document {    const regions = try storage.acquire(heading_plan);    var heading_index: usize = 0;    var text_index: usize = 0;    var id_index: usize = 0;    var iterator = HeadingIterator.init(source, null);    while (try iterator.next()) |heading| {        const text = regions.text[text_index..][0..heading.text.len];        @memcpy(text, heading.text);        text_index += text.len;        const resolved = try resolveHeadingId(source, heading);        const id_length = try resolved.length();        const id = resolved.write(regions.ids[id_index..][0..id_length]);        id_index += id.len;        regions.headings[heading_index] = .{            .level = heading.level,            .text = text,            .id = id,            .source_offset = heading.source_offset,        };        heading_index += 1;    }    std.debug.assert(heading_index == regions.plan.headings);    std.debug.assert(text_index == regions.plan.text_bytes);    std.debug.assert(id_index == regions.plan.id_bytes);    return .{ .headings = regions.headings };}/// Renders Markdown and returns an owner that must be deinitialized with the same allocator.////// A heading may end in `{#exact.id}`. Explicit IDs are exact, case-sensitive,/// page-wide unique, and omitted from the visible heading and contents label.pub fn render(allocator: Allocator, source: []const u8, options: Options) Error!Rendered {    const heading_plan = try planDiagnostic(source, options.diagnostic);    try heading_plan.require(options.heading_limits);    var document_storage = try document.Storage.init(allocator, heading_plan.exactLimits());    errdefer document_storage.deinit(allocator);    document_storage.activate();    const doc = try inspectPlanned(&document_storage, source, heading_plan);    errdefer document_storage.reset();    const footnote_plan = try footnote.Plan.inspect(source, options.footnote_limits);    var footnote_storage = try footnote.Storage.init(allocator, footnote_plan.exactLimits());    defer footnote_storage.deinit(allocator);    footnote_storage.activate();    var footnotes = try footnote.parse(&footnote_storage, source);    defer footnote_storage.reset();    var out: std.ArrayList(u8) = .empty;    errdefer out.deinit(allocator);    const track_origins = options.link_report != null;    var paragraph: InlineBuffer = .{ .track = track_origins };    defer paragraph.deinit(allocator);    var list_item: InlineBuffer = .{ .track = track_origins };    defer list_item.deinit(allocator);    var blockquote: InlineBuffer = .{ .track = track_origins };    defer blockquote.deinit(allocator);    var code_block: std.ArrayList(u8) = .empty;    defer code_block.deinit(allocator);    var math_block: std.ArrayList(u8) = .empty;    defer math_block.deinit(allocator);    var quiz_owner: QuizOwner = .{};    defer quiz_owner.deinit(allocator);    var table_storage: markdown_model.TableStorage = .{};    var math_open = false;    var cursor: usize = 0;    var code_fence: ?Fence = null;    var list_kind: ?ListKind = null;    var semantic_list: ?SemanticList = null;    var blockquote_open = false;    var footnote_definition = false;    var rendered_heading_index: usize = 0;    var ego_stylesheet: ?EgoStylesheet = null;    var deck = slides.Deck{ .options = options.slides };    if (options.mode == .slides) try deck.begin(&out, allocator);    while (true) {        const line_start = cursor;        const raw_line = nextLine(source, &cursor) orelse break;        const line = std.mem.trim(u8, raw_line, "\r");        if (code_fence) |fence| {            if (closingFence(line, fence)) {                try flushFence(                    allocator,                    &out,                    fence,                    code_block.items,                    options,                    doc,                    &quiz_owner,                    &ego_stylesheet,                );                code_block.clearRetainingCapacity();                code_fence = null;            } else {                try code_block.appendSlice(allocator, line);                try code_block.append(allocator, '\n');            }            continue;        }        if (math_open) {            const inner = std.mem.trim(u8, line, " \t");            if (std.mem.eql(u8, inner, "$$")) {                try flushDisplayMath(allocator, &out, &math_block, options.diagnostic);                math_open = false;            } else if (std.mem.endsWith(u8, inner, "$$")) {                if (math_block.items.len != 0) try math_block.append(allocator, ' ');                try math_block.appendSlice(allocator, std.mem.trimEnd(u8, inner[0 .. inner.len - 2], " \t"));                try flushDisplayMath(allocator, &out, &math_block, options.diagnostic);                math_open = false;            } else if (inner.len != 0) {                if (math_block.items.len != 0) try math_block.append(allocator, ' ');                try math_block.appendSlice(allocator, inner);            }            continue;        }        if (parseFence(line)) |fence| {            if (semantic_list != null) return error.InvalidSemanticList;            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);            code_block.clearRetainingCapacity();            var opened = fence;            opened.source_offset = line_start;            code_fence = opened;            footnote_definition = false;            continue;        }        const trimmed = std.mem.trim(u8, line, " \t");        if (parseSemanticList(trimmed)) |role| {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(                allocator,                &out,                &list_kind,                &list_item,                &footnotes,                options,            );            try closeBlockquote(                allocator,                &out,                &blockquote_open,                &blockquote,                &footnotes,                options,            );            if (semantic_list != null) return error.InvalidSemanticList;            semantic_list = role;            continue;        }        if (std.mem.startsWith(u8, trimmed, "$$")) {            if (semantic_list != null) return error.InvalidSemanticList;            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);            footnote_definition = false;            const rest = std.mem.trim(u8, trimmed[2..], " \t");            if (rest.len >= 2 and std.mem.endsWith(u8, rest, "$$")) {                try math_block.appendSlice(allocator, std.mem.trimEnd(u8, rest[0 .. rest.len - 2], " \t"));                try flushDisplayMath(allocator, &out, &math_block, options.diagnostic);            } else {                math_open = true;                try math_block.appendSlice(allocator, rest);            }            continue;        }        if (trimmed.len == 0) {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);            footnote_definition = false;            continue;        }        const parsed_list_item = parseListItem(line);        if (semantic_list != null and parsed_list_item == null) {            return error.InvalidSemanticList;        }        if (footnote.definition(line) != null) {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);            footnote_definition = true;            continue;        }        if (footnote_definition and footnote.continuation(line) != null) continue;        footnote_definition = false;        const table_source = source[line_start..];        switch (markdown_model.parseTable(&table_storage, table_source)) {            .table => |table| {                try flushParagraph(allocator, &out, &paragraph, &footnotes, options);                try closeList(                    allocator,                    &out,                    &list_kind,                    &list_item,                    &footnotes,                    options,                );                try closeBlockquote(                    allocator,                    &out,                    &blockquote_open,                    &blockquote,                    &footnotes,                    options,                );                try appendTable(                    allocator,                    &out,                    source,                    table_source,                    table,                    &footnotes,                    options,                );                cursor = line_start + table.source.end;                continue;            },            .paragraph, .rejected => {},        }        if (documentationArtifactBlock(trimmed)) {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(                allocator,                &out,                &list_kind,                &list_item,                &footnotes,                options,            );            try closeBlockquote(                allocator,                &out,                &blockquote_open,                &blockquote,                &footnotes,                options,            );            try appendInline(                &out,                allocator,                trimmed,                &footnotes,                options.diagnostic,                originWithin(source, trimmed),                options.link_report,            );            try out.append(allocator, '\n');            continue;        }        if (parseBlockquote(line)) |quote| {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            if (!blockquote_open) blockquote_open = true;            try blockquote.appendLine(allocator, source, quote);            continue;        }        try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);        if (parsed_list_item) |item| {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            if (list_kind == null or list_kind.? != item.kind) {                try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);                try openList(allocator, &out, item.kind, semantic_list);                semantic_list = null;                list_kind = item.kind;            }            try flushListItem(allocator, &out, &list_item, &footnotes, options);            try list_item.appendLine(allocator, source, item.text);            continue;        }        if (list_kind != null) {            if (listContinuation(line)) |continuation| {                try list_item.appendLine(allocator, source, continuation);                continue;            }        }        try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);        if (try parseHeading(line, line_start, options.diagnostic)) |heading| {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            std.debug.assert(rendered_heading_index < doc.headings.len);            const inspected = doc.headings[rendered_heading_index];            std.debug.assert(inspected.source_offset == line_start);            std.debug.assert(std.mem.eql(u8, inspected.text, heading.text));            rendered_heading_index += 1;            try out.appendSlice(allocator, "<h");            try appendDecimal(&out, allocator, heading.level);            if (options.heading_anchors) {                try out.appendSlice(allocator, " id=\"");                try html.appendAttributeEscaped(&out, allocator, inspected.id);                try out.append(allocator, '"');            }            try out.append(allocator, '>');            try appendInline(                &out,                allocator,                heading.text,                &footnotes,                options.diagnostic,                originWithin(source, heading.text),                options.link_report,            );            try out.appendSlice(allocator, "</h");            try appendDecimal(&out, allocator, heading.level);            try out.appendSlice(allocator, ">\n");            continue;        }        if (isThematicBreak(trimmed)) {            try flushParagraph(allocator, &out, &paragraph, &footnotes, options);            try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);            try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);            if (options.mode == .slides) {                try deck.split(&out, allocator);                continue;            }            try out.appendSlice(allocator, "<hr>\n");            continue;        }        try paragraph.appendLine(allocator, source, trimmed);    }    if (math_open) {        if (options.diagnostic) |d| d.setEquation(math_block.items, .{            .reason = "missing closing '$$'",            .offset = math_block.items.len,        });        return error.InvalidEquation;    }    if (code_fence) |fence| try flushFence(        allocator,        &out,        fence,        code_block.items,        options,        doc,        &quiz_owner,        &ego_stylesheet,    );    if (semantic_list != null) return error.InvalidSemanticList;    try flushParagraph(allocator, &out, &paragraph, &footnotes, options);    try closeList(allocator, &out, &list_kind, &list_item, &footnotes, options);    try closeBlockquote(allocator, &out, &blockquote_open, &blockquote, &footnotes, options);    try appendFootnotes(allocator, &out, source, &footnotes, options);    std.debug.assert(rendered_heading_index == doc.headings.len);    if (options.mode == .slides) try deck.finish(&out, allocator);    return .{        .html = try out.toOwnedSlice(allocator),        .document = doc,        .document_storage = document_storage,    };}fn flushFence(    allocator: Allocator,    out: *std.ArrayList(u8),    fence: Fence,    source: []const u8,    options: Options,    doc: document.Document,    quiz_owner: *QuizOwner,    ego_stylesheet: *?EgoStylesheet,) Error!void {    if (options.mode == .slides and notesFence(fence.info)) {        try appendSpeakerNotes(allocator, out, source, options);        return;    }    if (contentsFence(fence.info)) {        try appendContents(allocator, out, doc, fence, source, options.diagnostic);        return;    }    if (quizFence(fence.info)) {        try appendQuiz(            allocator,            out,            source,            options.diagnostic,            quiz_owner,            options.quiz_limits,        );        return;    }    if (egoFence(fence.info)) {        try diagram.ego.svg.validateDocumentFragment(source);        try appendEgoFragment(            allocator,            out,            source,            options.one_call_map_style_per_page,            ego_stylesheet,        );        return;    }    if (options.ascii_diagrams and diagramFence(fence.info)) {        var rendered = try diagram.renderAscii(allocator, source, .{            .width = options.diagram_width,            .height = options.diagram_height,        });        defer rendered.deinit(allocator);        try out.appendSlice(            allocator,            "<pre class=\"zen-diagram zen-role-wide\"><code>",        );        try html.appendEscaped(out, allocator, rendered.output);        try out.appendSlice(allocator, "</code></pre>\n");        return;    }    try code.render(allocator, out, fence.info, source, options.code_blocks);}fn appendEgoFragment(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    one_stylesheet_per_page: bool,    stylesheet: *?EgoStylesheet,) Allocator.Error!void {    const fragment = std.mem.trim(u8, source, " \t\r\n");    if (!one_stylesheet_per_page) {        try out.appendSlice(allocator, fragment);        try out.append(allocator, '\n');        return;    }    const range = egoStylesheetRange(fragment) orelse {        try out.appendSlice(allocator, fragment);        try out.append(allocator, '\n');        return;    };    const candidate = fragment[range.start..range.end];    if (stylesheet.*) |first| {        std.debug.assert(first.output_start <= out.items.len);        std.debug.assert(first.length <= out.items.len - first.output_start);        const retained = out.items[first.output_start..][0..first.length];        if (std.mem.eql(u8, retained, candidate)) {            try out.appendSlice(allocator, fragment[0..range.start]);            try out.appendSlice(allocator, fragment[range.end..]);            try out.append(allocator, '\n');            return;        }    } else {        stylesheet.* = .{            .output_start = out.items.len + range.start,            .length = candidate.len,        };    }    try out.appendSlice(allocator, fragment);    try out.append(allocator, '\n');}const EgoStylesheetRange = struct {    start: usize,    end: usize,};fn egoStylesheetRange(fragment: []const u8) ?EgoStylesheetRange {    const open = "<style>";    const close = "</style>";    const start = std.mem.indexOf(u8, fragment, open) orelse return null;    const close_start = std.mem.indexOfPos(u8, fragment, start + open.len, close) orelse        return null;    return .{ .start = start, .end = close_start + close.len };}fn appendSpeakerNotes(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    options: Options,) Error!void {    var note_options = options;    note_options.mode = .document;    note_options.slides.runtime = false;    var rendered = try render(allocator, source, note_options);    defer rendered.deinit(allocator);    if (std.mem.trim(u8, rendered.html, " \t\r\n").len == 0) return;    try out.appendSlice(allocator, "<aside class=\"zen-speaker-notes\" data-zen-speaker-notes hidden>\n");    try out.appendSlice(allocator, rendered.html);    try out.appendSlice(allocator, "</aside>\n");}const ContentsScope = enum {    document,    following,};const ContentsOptions = struct {    scope: ContentsScope = .following,    min_level: u8 = 1,    max_level: u8 = 6,    title: []const u8 = "Contents:",};fn contentsFence(info: []const u8) bool {    const language = firstFenceWord(info);    return std.mem.eql(u8, language, "zen-toc") or        std.mem.eql(u8, language, "zen-contents") or        std.mem.eql(u8, language, "toc");}fn egoFence(info: []const u8) bool {    return std.mem.eql(u8, firstFenceWord(info), "zen-ego");}fn appendContents(    allocator: Allocator,    out: *std.ArrayList(u8),    doc: document.Document,    fence: Fence,    source: []const u8,    diag: ?*diagnostic.Diagnostic,) !void {    const options = try parseContentsOptions(source);    var count: usize = 0;    for (doc.headings) |heading| {        if (!contentsIncludes(options, fence, heading)) continue;        count += 1;    }    if (count == 0) return;    try out.appendSlice(        allocator,        "<nav class=\"zen-contents zen-role-wide\" aria-label=\"Contents\">\n<p>",    );    try html.appendEscaped(out, allocator, options.title);    try out.appendSlice(allocator, "</p>\n<ul>\n");    for (doc.headings) |heading| {        if (!contentsIncludes(options, fence, heading)) continue;        try appendContentsItem(allocator, out, heading, options, diag);        try out.appendSlice(allocator, "</li>\n");    }    try out.appendSlice(allocator, "</ul>\n</nav>\n");}fn appendContentsItem(    allocator: Allocator,    out: *std.ArrayList(u8),    heading: document.Heading,    options: ContentsOptions,    diag: ?*diagnostic.Diagnostic,) !void {    try out.appendSlice(allocator, "<li class=\"zen-contents-level-");    try appendDecimal(out, allocator, heading.level);    if (heading.level > options.min_level) {        try out.appendSlice(allocator, "\" style=\"margin-left:calc(");        try appendDecimal(out, allocator, heading.level - options.min_level);        try out.appendSlice(allocator, " * 1.5rem)\"><a href=\"#");    } else {        try out.appendSlice(allocator, "\"><a href=\"#");    }    try html.appendAttributeEscaped(out, allocator, heading.id);    try out.appendSlice(allocator, "\">");    try appendInline(out, allocator, heading.text, null, diag, .untracked, null);    try out.appendSlice(allocator, "</a>");}fn contentsIncludes(options: ContentsOptions, fence: Fence, heading: document.Heading) bool {    if (heading.level < options.min_level or heading.level > options.max_level) return false;    return switch (options.scope) {        .document => true,        .following => heading.source_offset > fence.source_offset,    };}fn parseContentsOptions(source: []const u8) !ContentsOptions {    var options: ContentsOptions = .{};    var cursor: usize = 0;    while (nextLine(source, &cursor)) |raw_line| {        const line = std.mem.trim(u8, std.mem.trim(u8, raw_line, "\r"), " \t");        if (line.len == 0) continue;        const split = std.mem.indexOfScalar(u8, line, ':') orelse return error.InvalidContentsDirective;        const key = std.mem.trim(u8, line[0..split], " \t");        const value = std.mem.trim(u8, line[split + 1 ..], " \t");        if (std.mem.eql(u8, key, "scope")) {            options.scope = if (std.mem.eql(u8, value, "document") or std.mem.eql(u8, value, "page"))                .document            else if (std.mem.eql(u8, value, "following"))                .following            else                return error.InvalidContentsDirective;        } else if (std.mem.eql(u8, key, "min-level")) {            options.min_level = try parseHeadingLevel(value);        } else if (std.mem.eql(u8, key, "max-level")) {            options.max_level = try parseHeadingLevel(value);        } else if (std.mem.eql(u8, key, "title")) {            options.title = value;        } else {            return error.InvalidContentsDirective;        }    }    if (options.min_level > options.max_level) return error.InvalidContentsDirective;    return options;}fn parseHeadingLevel(value: []const u8) !u8 {    const level = std.fmt.parseUnsigned(u8, value, 10) catch return error.InvalidContentsDirective;    if (level < 1 or level > 6) return error.InvalidContentsDirective;    return level;}fn diagramFence(info: []const u8) bool {    const language = firstFenceWord(info);    return std.mem.eql(u8, language, "diagram") or        std.mem.eql(u8, language, "zen-diagram") or        std.mem.eql(u8, language, "zen-ascii");}fn quizFence(info: []const u8) bool {    const language = firstFenceWord(info);    return std.mem.eql(u8, language, "zen-quiz") or        std.mem.eql(u8, language, "quiz");}fn appendQuiz(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    diag: ?*diagnostic.Diagnostic,    owner: *QuizOwner,    limits: quiz.Limits,) Error!void {    const parsed = try owner.parse(allocator, source, limits);    defer owner.reset();    try out.appendSlice(allocator, "<section class=\"zen-quiz\" aria-label=\"Quiz\">\n<ol class=\"zen-quiz-questions\">\n");    for (parsed.questions) |question| {        try out.appendSlice(allocator, "<li class=\"zen-quiz-question\">\n<p class=\"zen-quiz-prompt\">");        try appendInline(out, allocator, question.prompt, null, diag, .untracked, null);        try out.appendSlice(allocator, "</p>\n");        if (question.options.len != 0) {            try out.appendSlice(allocator, "<ul class=\"zen-quiz-options\">\n");            for (question.options) |option| {                try out.appendSlice(allocator, "<li>");                try appendInline(out, allocator, option.text, null, diag, .untracked, null);                try out.appendSlice(allocator, "</li>\n");            }            try out.appendSlice(allocator, "</ul>\n");        }        try out.appendSlice(allocator, "<details class=\"zen-quiz-answer\">\n<summary>Reveal answer</summary>\n");        for (question.options) |option| {            if (!option.correct) continue;            try out.appendSlice(allocator, "<p class=\"zen-quiz-correct\"><strong>");            try appendInline(out, allocator, option.text, null, diag, .untracked, null);            try out.appendSlice(allocator, "</strong></p>\n");        }        if (question.explanation.len != 0) {            try out.appendSlice(allocator, "<p class=\"zen-quiz-explanation\">");            try appendInline(out, allocator, question.explanation, null, diag, .untracked, null);            try out.appendSlice(allocator, "</p>\n");        }        try out.appendSlice(allocator, "</details>\n</li>\n");    }    try out.appendSlice(allocator, "</ol>\n</section>\n");}fn notesFence(info: []const u8) bool {    const language = firstFenceWord(info);    return std.mem.eql(u8, language, "notes") or        std.mem.eql(u8, language, "speaker-notes") or        std.mem.eql(u8, language, "zen-notes");}fn firstFenceWord(info: []const u8) []const u8 {    const trimmed = std.mem.trim(u8, info, " \t");    var end: usize = 0;    while (end < trimmed.len and trimmed[end] != ' ' and trimmed[end] != '\t') : (end += 1) {}    return trimmed[0..end];}const MathMode = enum { inline_math, display };fn renderMath(    out: *std.ArrayList(u8),    allocator: Allocator,    source: []const u8,    mode: MathMode,    diag: ?*diagnostic.Diagnostic,) math.Error!void {    var detail: math.Diagnostic = .{};    (switch (mode) {        .inline_math => math.renderInline(out, allocator, source, &detail),        .display => math.renderDisplay(out, allocator, source, &detail),    }) catch |err| {        switch (err) {            error.InvalidEquation => if (diag) |d| d.setEquation(source, detail),            error.OutOfMemory => {},        }        return err;    };}fn flushDisplayMath(    allocator: Allocator,    out: *std.ArrayList(u8),    block: *std.ArrayList(u8),    diag: ?*diagnostic.Diagnostic,) math.Error!void {    try renderMath(out, allocator, block.items, .display, diag);    try out.append(allocator, '\n');    block.clearRetainingCapacity();}fn flushParagraph(    allocator: Allocator,    out: *std.ArrayList(u8),    paragraph: *InlineBuffer,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    if (paragraph.items().len == 0) return;    const container = try paragraphContainer(        allocator,        paragraph.items(),        options.mode,        options.diagnostic,    );    if (container) |value| {        try out.appendSlice(allocator, "<p class=\"");        try out.appendSlice(allocator, value.classes);        try out.appendSlice(allocator, "\">");    } else {        try out.appendSlice(allocator, "<p>");    }    const full_size_image = if (container) |value| value.full_size_image else null;    if (full_size_image) |image| {        try out.appendSlice(allocator, "<a href=\"");        try appendMarkdownEscaped(out, allocator, image.target);        try out.appendSlice(            allocator,            "\" target=\"_blank\" rel=\"noopener\" aria-label=\"Open ",        );        try appendMarkdownEscaped(out, allocator, image.label);        try out.appendSlice(allocator, " at full size\">");    }    try appendInline(        out,        allocator,        paragraph.items(),        footnotes,        options.diagnostic,        paragraph.origin(),        options.link_report,    );    if (full_size_image != null) try out.appendSlice(allocator, "</a>");    try out.appendSlice(allocator, "</p>\n");    paragraph.clearRetainingCapacity();}fn appendTable(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    table_source: []const u8,    table: markdown_model.Table,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    const alignments = table.delimiter.alignments;    std.debug.assert(table.header.cells.len == alignments.len);    try out.appendSlice(        allocator,        "<div class=\"content-table zen-role-wide\" tabindex=\"0\">\n",    );    try out.appendSlice(allocator, "<table>\n<thead>\n");    try appendTableRow(        allocator,        out,        source,        table_source,        table.header,        alignments,        true,        footnotes,        options,    );    try out.appendSlice(allocator, "</thead>\n<tbody>\n");    for (table.body) |row| {        std.debug.assert(row.cells.len == alignments.len);        try appendTableRow(            allocator,            out,            source,            table_source,            row,            alignments,            false,            footnotes,            options,        );    }    try out.appendSlice(allocator, "</tbody>\n</table>\n</div>\n");}fn appendTableRow(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    table_source: []const u8,    row: markdown_model.TableRow,    alignments: []const markdown_model.TableAlignment,    header: bool,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    std.debug.assert(row.cells.len == alignments.len);    try out.appendSlice(allocator, "<tr>\n");    for (row.cells, alignments) |cell, alignment| {        if (header) {            try out.appendSlice(allocator, "<th scope=\"col\"");        } else {            try out.appendSlice(allocator, "<td");        }        if (tableAlignmentClass(alignment)) |class| {            try out.appendSlice(allocator, " class=\"");            try out.appendSlice(allocator, class);            try out.append(allocator, '"');        }        try out.append(allocator, '>');        const cell_text = cell.source.bytes(table_source);        try appendInline(            out,            allocator,            cell_text,            footnotes,            options.diagnostic,            originWithin(source, cell_text),            options.link_report,        );        try out.appendSlice(allocator, if (header) "</th>\n" else "</td>\n");    }    try out.appendSlice(allocator, "</tr>\n");}fn tableAlignmentClass(alignment: markdown_model.TableAlignment) ?[]const u8 {    return switch (alignment) {        .none => null,        .left => "zen-table-align-left",        .center => "zen-table-align-center",        .right => "zen-table-align-right",    };}fn flushListItem(    allocator: Allocator,    out: *std.ArrayList(u8),    list_item: *InlineBuffer,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    if (list_item.items().len == 0) return;    try out.appendSlice(allocator, "<li>");    try appendInline(        out,        allocator,        list_item.items(),        footnotes,        options.diagnostic,        list_item.origin(),        options.link_report,    );    try out.appendSlice(allocator, "</li>\n");    list_item.clearRetainingCapacity();}fn openList(    allocator: Allocator,    out: *std.ArrayList(u8),    kind: ListKind,    semantic: ?SemanticList,) Allocator.Error!void {    try out.appendSlice(allocator, switch (kind) {        .unordered => "<ul",        .ordered => "<ol",    });    if (semantic) |role| {        try out.appendSlice(allocator, " class=\"");        try out.appendSlice(allocator, semanticListClasses(role));        try out.append(allocator, '"');    }    try out.appendSlice(allocator, ">\n");}fn closeList(    allocator: Allocator,    out: *std.ArrayList(u8),    list_kind: *?ListKind,    list_item: *InlineBuffer,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    if (list_kind.*) |kind| {        try flushListItem(allocator, out, list_item, footnotes, options);        switch (kind) {            .unordered => try out.appendSlice(allocator, "</ul>\n"),            .ordered => try out.appendSlice(allocator, "</ol>\n"),        }        list_kind.* = null;    }}fn closeBlockquote(    allocator: Allocator,    out: *std.ArrayList(u8),    open: *bool,    blockquote: *InlineBuffer,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    if (!open.*) return;    try out.appendSlice(allocator, "<blockquote><p>");    try appendInline(        out,        allocator,        blockquote.items(),        footnotes,        options.diagnostic,        blockquote.origin(),        options.link_report,    );    try out.appendSlice(allocator, "</p></blockquote>\n");    open.* = false;    blockquote.clearRetainingCapacity();}fn appendDecimal(out: *std.ArrayList(u8), allocator: Allocator, value: u8) Allocator.Error!void {    var buffer: [3]u8 = undefined;    const text = std.fmt.bufPrint(&buffer, "{d}", .{value}) catch unreachable;    try out.appendSlice(allocator, text);}fn appendUsize(out: *std.ArrayList(u8), allocator: Allocator, value: usize) Allocator.Error!void {    var buffer: [20]u8 = undefined;    const text = std.fmt.bufPrint(&buffer, "{d}", .{value}) catch unreachable;    try out.appendSlice(allocator, text);}fn nextLine(source: []const u8, cursor: *usize) ?[]const u8 {    if (cursor.* >= source.len) return null;    const start = cursor.*;    if (std.mem.indexOfScalarPos(u8, source, start, '\n')) |end| {        cursor.* = end + 1;        return source[start..end];    }    cursor.* = source.len;    return source[start..];}fn parseFence(line: []const u8) ?Fence {    const trimmed = trimLeft(line);    if (trimmed.len < 3) return null;    const marker = trimmed[0];    if (marker != '`' and marker != '~') return null;    var count: usize = 0;    while (count < trimmed.len and trimmed[count] == marker) : (count += 1) {}    if (count < 3) return null;    return .{        .marker = marker,        .count = count,        .info = std.mem.trim(u8, trimmed[count..], " \t"),    };}fn closingFence(line: []const u8, fence: Fence) bool {    const trimmed = std.mem.trim(u8, line, " \t");    var count: usize = 0;    while (count < trimmed.len and trimmed[count] == fence.marker) : (count += 1) {}    return count >= fence.count and std.mem.trim(u8, trimmed[count..], " \t").len == 0;}const Heading = struct {    level: u8,    text: []const u8,    explicit_id: ?[]const u8 = null,    anchor_offset: ?usize = null,};fn parseHeading(    line: []const u8,    source_offset: usize,    diag: ?*diagnostic.Diagnostic,) document.Error!?Heading {    const trimmed = trimLeft(line);    var level: u8 = 0;    while (level < trimmed.len and level < 6 and trimmed[level] == '#') : (level += 1) {}    if (level == 0) return null;    if (level < trimmed.len and trimmed[level] != ' ' and trimmed[level] != '\t') return null;    const text = std.mem.trim(u8, trimmed[level..], " \t#");    const anchor_start = headingAnchorStart(text) orelse return .{        .level = level,        .text = text,    };    const anchor_offset = source_offset +        (@intFromPtr(text.ptr) - @intFromPtr(line.ptr)) + anchor_start;    const anchor = text[anchor_start..];    if (anchor.len < 4 or anchor[anchor.len - 1] != '}') {        setHeadingDiagnostic(diag, "invalid heading anchor", anchor_offset);        return error.InvalidHeadingAnchor;    }    const explicit_id = anchor[2 .. anchor.len - 1];    if (!validHeadingId(explicit_id)) {        setHeadingDiagnostic(diag, "invalid heading anchor", anchor_offset);        return error.InvalidHeadingAnchor;    }    return .{        .level = level,        .text = std.mem.trimEnd(u8, text[0..anchor_start], " \t"),        .explicit_id = explicit_id,        .anchor_offset = anchor_offset,    };}fn headingAnchorStart(text: []const u8) ?usize {    var index = text.len;    while (index > 1) : (index -= 1) {        const start = index - 2;        if (text[start] != '{' or text[start + 1] != '#') continue;        if (start == 0 or text[start - 1] == ' ' or text[start - 1] == '\t') {            return start;        }    }    return null;}fn validHeadingId(id: []const u8) bool {    if (id.len == 0) return false;    for (id) |byte| {        if (asciiAlphanumeric(byte)) continue;        if (byte != '-' and byte != '_' and byte != '.' and byte != ':' and            byte != '/' and byte != '~') return false;    }    return true;}fn setHeadingDiagnostic(    diag: ?*diagnostic.Diagnostic,    reason: []const u8,    offset: usize,) void {    if (diag) |active| active.setHeading(reason, offset);}const LocatedHeading = struct {    level: u8,    text: []const u8,    explicit_id: ?[]const u8,    anchor_offset: ?usize,    source_offset: usize,};const HeadingIterator = struct {    source: []const u8,    diagnostic: ?*diagnostic.Diagnostic,    cursor: usize = 0,    code_fence: ?Fence = null,    math_open: bool = false,    footnote_definition: bool = false,    list_open: bool = false,    fn init(source: []const u8, diag: ?*diagnostic.Diagnostic) HeadingIterator {        return .{ .source = source, .diagnostic = diag };    }    fn next(self: *HeadingIterator) document.Error!?LocatedHeading {        while (true) {            const line_start = self.cursor;            const raw_line = nextLine(self.source, &self.cursor) orelse return null;            const line = std.mem.trim(u8, raw_line, "\r");            if (self.code_fence) |fence| {                if (closingFence(line, fence)) self.code_fence = null;                continue;            }            if (self.math_open) {                const inner = std.mem.trim(u8, line, " \t");                if (std.mem.eql(u8, inner, "$$") or                    std.mem.endsWith(u8, inner, "$$")) self.math_open = false;                continue;            }            if (parseFence(line)) |parsed| {                self.code_fence = parsed;                self.footnote_definition = false;                self.list_open = false;                continue;            }            const trimmed = std.mem.trim(u8, line, " \t");            if (std.mem.startsWith(u8, trimmed, "$$")) {                const rest = std.mem.trim(u8, trimmed[2..], " \t");                self.math_open = !(rest.len >= 2 and std.mem.endsWith(u8, rest, "$$"));                self.footnote_definition = false;                self.list_open = false;                continue;            }            if (trimmed.len == 0) {                self.footnote_definition = false;                self.list_open = false;                continue;            }            if (footnote.definition(line) != null) {                self.footnote_definition = true;                self.list_open = false;                continue;            }            if (self.footnote_definition and footnote.continuation(line) != null) continue;            self.footnote_definition = false;            if (parseBlockquote(line) != null) {                self.list_open = false;                continue;            }            if (parseListItem(line) != null) {                self.list_open = true;                continue;            }            if (self.list_open and listContinuation(line) != null) continue;            self.list_open = false;            if (try parseHeading(line, line_start, self.diagnostic)) |heading| return .{                .level = heading.level,                .text = heading.text,                .explicit_id = heading.explicit_id,                .anchor_offset = heading.anchor_offset,                .source_offset = line_start,            };        }    }};const ResolvedHeadingId = union(enum) {    explicit: []const u8,    generated: struct {        text: []const u8,        suffix: ?usize,    },    fn length(self: ResolvedHeadingId) error{CapacityOverflow}!usize {        return switch (self) {            .explicit => |id| id.len,            .generated => |generated| if (generated.suffix) |suffix|                std.math.add(                    usize,                    html.slugLength(generated.text),                    1 + decimalLength(suffix),                ) catch error.CapacityOverflow            else                html.slugLength(generated.text),        };    }    fn write(self: ResolvedHeadingId, out: []u8) []u8 {        std.debug.assert(out.len == (self.length() catch unreachable));        switch (self) {            .explicit => |id| @memcpy(out, id),            .generated => |generated| {                const base_length = html.slugLength(generated.text);                _ = html.writeSlug(out[0..base_length], generated.text);                if (generated.suffix) |suffix| {                    out[base_length] = '~';                    _ = std.fmt.bufPrint(out[base_length + 1 ..], "{d}", .{suffix}) catch                        unreachable;                }            },        }        return out;    }};fn validateHeadingAnchors(    source: []const u8,    diag: ?*diagnostic.Diagnostic,) document.Error!void {    var iterator = HeadingIterator.init(source, diag);    while (try iterator.next()) |heading| {        const id = heading.explicit_id orelse continue;        var prior = HeadingIterator.init(source, null);        while (try prior.next()) |candidate| {            if (candidate.source_offset >= heading.source_offset) break;            const candidate_id = candidate.explicit_id orelse continue;            if (!std.mem.eql(u8, candidate_id, id)) continue;            setHeadingDiagnostic(diag, "duplicate heading anchor", heading.anchor_offset.?);            return error.DuplicateHeadingAnchor;        }    }}fn resolveHeadingId(    source: []const u8,    target: LocatedHeading,) document.Error!ResolvedHeadingId {    if (target.explicit_id) |id| return .{ .explicit = id };    var occurrence: usize = 0;    var explicit_reserved = false;    var iterator = HeadingIterator.init(source, null);    while (try iterator.next()) |heading| {        if (heading.explicit_id) |id| {            explicit_reserved = explicit_reserved or slugMatches(target.text, id);            continue;        }        if (heading.source_offset > target.source_offset) continue;        if (!slugsEqual(target.text, heading.text)) continue;        occurrence = std.math.add(usize, occurrence, 1) catch            return error.CapacityOverflow;    }    std.debug.assert(occurrence > 0);    const suffix = if (explicit_reserved or occurrence > 1) occurrence else null;    return .{ .generated = .{ .text = target.text, .suffix = suffix } };}const SlugIterator = struct {    source: []const u8,    index: usize = 0,    emitted: usize = 0,    pending_separator: bool = false,    delayed: ?u8 = null,    fallback_index: usize = 0,    fn next(self: *SlugIterator) ?u8 {        if (self.delayed) |byte| {            self.delayed = null;            self.emitted += 1;            return byte;        }        while (self.index < self.source.len) {            const byte = self.source[self.index];            self.index += 1;            if (asciiAlphanumeric(byte)) {                const normalized = std.ascii.toLower(byte);                if (self.pending_separator and self.emitted != 0) {                    self.pending_separator = false;                    self.delayed = normalized;                    self.emitted += 1;                    return '-';                }                self.pending_separator = false;                self.emitted += 1;                return normalized;            }            if (byte == ' ' or byte == '\t' or byte == '-' or byte == '_') {                if (self.emitted != 0) self.pending_separator = true;            }        }        if (self.emitted != 0 or self.fallback_index == "section".len) return null;        const byte = "section"[self.fallback_index];        self.fallback_index += 1;        return byte;    }};fn slugsEqual(left: []const u8, right: []const u8) bool {    var left_iterator = SlugIterator{ .source = left };    var right_iterator = SlugIterator{ .source = right };    while (true) {        const left_byte = left_iterator.next();        const right_byte = right_iterator.next();        if (left_byte == null or right_byte == null) return left_byte == right_byte;        if (left_byte.? != right_byte.?) return false;    }}fn slugMatches(text: []const u8, id: []const u8) bool {    var iterator = SlugIterator{ .source = text };    var index: usize = 0;    while (iterator.next()) |byte| {        if (index == id.len or id[index] != byte) return false;        index += 1;    }    return index == id.len;}fn asciiAlphanumeric(byte: u8) bool {    return (byte >= 'a' and byte <= 'z') or        (byte >= 'A' and byte <= 'Z') or        (byte >= '0' and byte <= '9');}fn decimalLength(value: usize) usize {    var buffer: [20]u8 = undefined;    return (std.fmt.bufPrint(&buffer, "{d}", .{value}) catch unreachable).len;}const ListItem = struct {    kind: ListKind,    text: []const u8,};fn parseListItem(line: []const u8) ?ListItem {    const trimmed = trimLeft(line);    if (trimmed.len >= 2 and (trimmed[0] == '-' or trimmed[0] == '*' or trimmed[0] == '+') and (trimmed[1] == ' ' or trimmed[1] == '\t')) {        return .{ .kind = .unordered, .text = std.mem.trim(u8, trimmed[2..], " \t") };    }    var index: usize = 0;    while (index < trimmed.len and trimmed[index] >= '0' and trimmed[index] <= '9') : (index += 1) {}    if (index == 0 or index + 1 >= trimmed.len or trimmed[index] != '.') return null;    if (trimmed[index + 1] != ' ' and trimmed[index + 1] != '\t') return null;    return .{ .kind = .ordered, .text = std.mem.trim(u8, trimmed[index + 2 ..], " \t") };}fn parseSemanticList(line: []const u8) ?SemanticList {    if (std.mem.eql(        u8,        line,        "{.docs-index-family .zen-role-wide}",    )) return .family_index;    if (std.mem.eql(        u8,        line,        "{.docs-index-module .zen-role-wide}",    )) return .module_index;    return null;}fn semanticListClasses(role: SemanticList) []const u8 {    return switch (role) {        .family_index => "docs-index-family zen-role-wide",        .module_index => "docs-index-module zen-role-wide",    };}fn listContinuation(line: []const u8) ?[]const u8 {    var index: usize = 0;    while (index < line.len and (line[index] == ' ' or line[index] == '\t')) : (index += 1) {}    if (index == 0) return null;    const continuation = std.mem.trim(u8, line[index..], " \t");    if (continuation.len == 0) return null;    return continuation;}fn parseBlockquote(line: []const u8) ?[]const u8 {    const trimmed = trimLeft(line);    if (trimmed.len == 0 or trimmed[0] != '>') return null;    return std.mem.trim(u8, trimmed[1..], " \t");}fn isThematicBreak(line: []const u8) bool {    if (line.len < 3) return false;    const marker = line[0];    if (marker != '-' and marker != '*' and marker != '_') return false;    for (line) |byte| {        if (byte != marker) return false;    }    return true;}fn trimLeft(line: []const u8) []const u8 {    var index: usize = 0;    while (index < line.len and (line[index] == ' ' or line[index] == '\t')) : (index += 1) {}    return line[index..];}fn appendFootnotes(    allocator: Allocator,    out: *std.ArrayList(u8),    source: []const u8,    footnotes: *footnote.Set,    options: Options,) InlineError!void {    if (!footnotes.hasReferences()) return;    try out.appendSlice(allocator, "<section class=\"footnotes\" aria-label=\"References\">\n<ol>\n");    var number: usize = 1;    while (number < footnotes.next_number) : (number += 1) {        for (footnotes.definitions) |definition| {            if (definition.number != number) continue;            try out.appendSlice(allocator, "<li id=\"fn-");            try html.appendAttributeEscaped(out, allocator, definition.key);            try out.appendSlice(allocator, "\">");            try appendInline(                out,                allocator,                definition.text,                null,                options.diagnostic,                originWithin(source, definition.text),                options.link_report,            );            try out.appendSlice(allocator, " <a class=\"footnote-backref\" href=\"#fnref-");            try html.appendAttributeEscaped(out, allocator, definition.key);            try out.appendSlice(allocator, "\" aria-label=\"Back to reference\">&#8617;</a></li>\n");        }    }    try out.appendSlice(allocator, "</ol>\n</section>\n");}fn appendFootnoteReference(    out: *std.ArrayList(u8),    allocator: Allocator,    footnotes: ?*footnote.Set,    key: []const u8,) Allocator.Error!bool {    const notes = footnotes orelse return false;    const mark = notes.markFor(key) orelse return false;    try out.appendSlice(allocator, "<sup id=\"fnref-");    try html.appendAttributeEscaped(out, allocator, key);    if (mark.reference > 1) {        try out.append(allocator, '-');        try appendUsize(out, allocator, mark.reference);    }    try out.appendSlice(allocator, "\"><a class=\"footnote-ref\" href=\"#fn-");    try html.appendAttributeEscaped(out, allocator, key);    try out.appendSlice(allocator, "\">[");    try appendUsize(out, allocator, mark.number);    try out.appendSlice(allocator, "]</a></sup>");    return true;}fn appendInline(    out: *std.ArrayList(u8),    allocator: Allocator,    value: []const u8,    footnotes: ?*footnote.Set,    diag: ?*diagnostic.Diagnostic,    origin: InlineOrigin,    report: ?*LinkReport,) InlineError!void {    var delimiters = indexCodeDelimiters(allocator, value, null) catch |err| {        if (err == error.InlineDelimiterCapacityExceeded) {            if (diag) |detail| detail.setInline(value, delimiter_capacity_reason, 0);        }        return err;    };    defer delimiters.deinit(allocator);    try appendInlineIndexed(        out,        allocator,        value,        value,        footnotes,        diag,        0,        false,        delimiters,        origin,        report,    );}fn appendInlineIndexed(    out: *std.ArrayList(u8),    allocator: Allocator,    source: []const u8,    value: []const u8,    footnotes: ?*footnote.Set,    diag: ?*diagnostic.Diagnostic,    depth: usize,    inside_link: bool,    delimiters: CodeDelimiters,    origin: InlineOrigin,    report: ?*LinkReport,) InlineError!void {    std.debug.assert(depth <= max_inline_nesting);    std.debug.assert(@intFromPtr(value.ptr) >= @intFromPtr(source.ptr));    const base = @intFromPtr(value.ptr) - @intFromPtr(source.ptr);    std.debug.assert(base <= source.len);    std.debug.assert(value.len <= source.len - base);    var index: usize = 0;    while (index < value.len) {        if (documentationHtmlTagEnd(value, index)) |end| {            try out.appendSlice(allocator, value[index..end]);            index = end;            continue;        }        if (value[index] == '`') {            const opener_end = backtickRunEnd(value, index);            if (delimiters.span(source, base + index, base + value.len)) |span| {                try out.appendSlice(allocator, "<code>");                try html.appendEscaped(out, allocator, span.content);                try out.appendSlice(allocator, "</code>");                index = span.end - base;                continue;            }            try html.appendEscaped(out, allocator, value[index..opener_end]);            index = opener_end;            continue;        }        if (value[index] == '\\' and index + 1 < value.len and            isAsciiPunctuation(value[index + 1]))        {            try html.appendEscapedByte(out, allocator, value[index + 1]);            index += 2;            continue;        }        if (value[index] == '$') {            if (inlineMathEnd(value, index)) |end| {                try renderMath(out, allocator, value[index + 1 .. end], .inline_math, diag);                index = end + 1;                continue;            }        }        if (index + 1 < value.len and value[index] == '!' and value[index + 1] == '[') {            if (try parseInlineLink(                source,                value,                base,                index,                true,                diag,                delimiters,            )) |link| {                recordRenderedLink(report, origin, base, index, value, link, true);                const video = std.mem.endsWith(u8, link.target, ".webm");                const attributes = parseImageAttributes(value, link.end);                var motion_base: ?usize = null;                if (!video) {                    if (attributes) |image_attributes| {                        if (hasAttributeClass(                            image_attributes.content,                            "zen-slide-motion",                        )) {                            motion_base = motionPosterBase(link.target);                        }                    }                }                if (video) {                    try out.appendSlice(allocator, "<video src=\"");                    try appendMarkdownEscaped(out, allocator, link.target);                    try out.appendSlice(allocator, "\" poster=\"");                    try appendMarkdownEscaped(                        out,                        allocator,                        link.target[0 .. link.target.len - ".webm".len],                    );                    try out.appendSlice(allocator, ".webp\" aria-label=\"");                } else {                    try out.appendSlice(allocator, "<img src=\"");                    if (motion_base) |motion_offset| {                        try appendMarkdownEscaped(out, allocator, link.target[0..motion_offset]);                        try out.appendSlice(allocator, ".poster.svg");                        try appendMarkdownEscaped(                            out,                            allocator,                            link.target[motion_offset + ".svg".len ..],                        );                        try out.appendSlice(allocator, "\" data-zen-motion-src=\"");                        try appendMarkdownEscaped(out, allocator, link.target);                        try out.appendSlice(allocator, "\" alt=\"");                    } else {                        try appendMarkdownEscaped(out, allocator, link.target);                        try out.appendSlice(allocator, "\" alt=\"");                    }                }                try appendMarkdownEscaped(out, allocator, link.label);                try out.append(allocator, '"');                if (video) try out.appendSlice(allocator, " autoplay loop muted playsinline");                if (motion_base != null) try out.appendSlice(allocator, " decoding=\"async\"");                var end = link.end;                if (attributes) |image_attributes| {                    try appendImageAttributes(out, allocator, image_attributes.content);                    end = image_attributes.end;                }                try out.append(allocator, '>');                if (video) try out.appendSlice(allocator, "</video>");                index = end;                continue;            }        }        if (value[index] == '[') {            if (!inside_link) {                if (parseFootnoteReference(value, index)) |reference| {                    if (try appendFootnoteReference(out, allocator, footnotes, reference.key)) {                        index = reference.end;                        continue;                    }                }            }            if (!inside_link) {                if (try parseInlineLink(                    source,                    value,                    base,                    index,                    false,                    diag,                    delimiters,                )) |link| {                    recordRenderedLink(report, origin, base, index, value, link, false);                    try out.appendSlice(allocator, "<a href=\"");                    try appendMarkdownEscaped(out, allocator, link.target);                    try out.appendSlice(allocator, "\">");                    try appendNestedInline(                        out,                        allocator,                        source,                        link.label,                        footnotes,                        diag,                        depth,                        true,                        delimiters,                        origin,                        report,                    );                    try out.appendSlice(allocator, "</a>");                    index = link.end;                    continue;                }            }        }        if (index + 1 < value.len and ((value[index] == '*' and value[index + 1] == '*') or (value[index] == '_' and value[index + 1] == '_'))) {            const token = value[index .. index + 2];            if (std.mem.indexOfPos(u8, value, index + 2, token)) |end| {                try out.appendSlice(allocator, "<strong>");                try appendNestedInline(                    out,                    allocator,                    source,                    value[index + 2 .. end],                    footnotes,                    diag,                    depth,                    inside_link,                    delimiters,                    origin,                    report,                );                try out.appendSlice(allocator, "</strong>");                index = end + 2;                continue;            }        }        if (value[index] == '*' or value[index] == '_') {            if (std.mem.indexOfScalarPos(u8, value, index + 1, value[index])) |end| {                try out.appendSlice(allocator, "<em>");                try appendNestedInline(                    out,                    allocator,                    source,                    value[index + 1 .. end],                    footnotes,                    diag,                    depth,                    inside_link,                    delimiters,                    origin,                    report,                );                try out.appendSlice(allocator, "</em>");                index = end + 1;                continue;            }        }        try html.appendEscapedByte(out, allocator, value[index]);        index += 1;    }}fn documentationHtmlTagEnd(value: []const u8, start: usize) ?usize {    const tags = [_][]const u8{        "<span class=\"docs-breadcrumb\" role=\"navigation\" aria-label=\"Declaration hierarchy\">",        "<span class=\"docs-breadcrumb\" role=\"navigation\" aria-label=\"Verification hierarchy\">",        "<span aria-hidden=\"true\">",        "<span aria-current=\"page\">",        "<span class=\"docs-sidenote zen-role-margin\">",        "<span class=\"docs-verification-source\">",        "<span class=\"docs-verification-freshness-content\">",        "<span class=\"docs-verification-freshness-content docs-verification-freshness-content-local\">",        "<span class=\"docs-margin-figure zen-role-margin\">",        "<span class=\"zen-role-reading\">",        "<span class=\"zen-role-wide\">",        "<span class=\"zen-role-margin\">",        "<span class=\"zen-role-full\">",        "<table class=\"docs-audit-table zen-role-wide\">",        "</span>",        "</table>",        "<thead>",        "</thead>",        "<tbody>",        "</tbody>",        "<tr>",        "</tr>",        "<th>",        "</th>",        "<td>",        "</td>",        "<strong>",        "</strong>",        "<code>",        "</code>",        "<br>",    };    if (start >= value.len or value[start] != '<') return null;    for (tags) |tag| {        if (std.mem.startsWith(u8, value[start..], tag)) return start + tag.len;    }    return null;}fn documentationArtifactBlock(value: []const u8) bool {    return std.mem.startsWith(        u8,        value,        "<table class=\"docs-audit-table zen-role-wide\">",    ) and std.mem.endsWith(u8, value, "</table>");}const ParagraphContainer = struct {    classes: []const u8,    full_size_image: ?InlineLink = null,};const ParagraphRole = struct {    open: []const u8,    classes: []const u8,};const paragraph_roles = [_]ParagraphRole{    .{        .open = "<span class=\"docs-sidenote zen-role-margin\">",        .classes = "docs-sidenote-container zen-role-margin",    },    .{        .open = "<span class=\"docs-verification-freshness-content\">",        .classes = "docs-verification-freshness",    },    .{        .open = "<span class=\"docs-verification-freshness-content " ++            "docs-verification-freshness-content-local\">",        .classes = "docs-verification-freshness docs-verification-freshness-local",    },    .{        .open = "<span class=\"docs-margin-figure zen-role-margin\">",        .classes = "docs-margin-figure-container zen-role-margin",    },    .{        .open = "<span class=\"zen-role-reading\">",        .classes = "zen-role-container zen-role-reading",    },    .{        .open = "<span class=\"zen-role-wide\">",        .classes = "zen-role-container zen-role-wide",    },    .{        .open = "<span class=\"zen-role-margin\">",        .classes = "zen-role-container zen-role-margin",    },    .{        .open = "<span class=\"zen-role-full\">",        .classes = "zen-role-container zen-role-full",    },};fn paragraphContainer(    allocator: Allocator,    value: []const u8,    mode: Mode,    diag: ?*diagnostic.Diagnostic,) InlineError!?ParagraphContainer {    if (std.mem.endsWith(u8, value, "</span>")) {        for (paragraph_roles) |role| {            if (std.mem.startsWith(u8, value, role.open)) {                return .{ .classes = role.classes };            }        }    }    if (!std.mem.startsWith(u8, value, "![")) return null;    var delimiters = try indexCodeDelimiters(allocator, value, null);    defer delimiters.deinit(allocator);    const link = try parseInlineLink(        value,        value,        0,        0,        true,        diag,        delimiters,    ) orelse return null;    var end = link.end;    const attributes = parseImageAttributes(value, end);    var wide_figure = false;    const role = if (attributes) |image_attributes| role: {        end = image_attributes.end;        wide_figure = hasAttributeClass(            image_attributes.content,            "zen-slide-figure-wide",        );        if (mode == .document and wide_figure) {            break :role "zen-media-block zen-role-wide";        }        if (hasAttributeClass(image_attributes.content, "zen-role-wide")) {            break :role "zen-media-block zen-role-wide";        }        if (hasAttributeClass(image_attributes.content, "zen-role-margin")) {            break :role "zen-media-block zen-role-margin";        }        if (hasAttributeClass(image_attributes.content, "zen-role-full")) {            break :role "zen-media-block zen-role-full";        }        break :role "zen-media-block zen-role-reading";    } else "zen-media-block zen-role-reading";    if (end != value.len) return null;    return .{        .classes = role,        .full_size_image = if (mode == .document and wide_figure and            !std.mem.endsWith(u8, link.target, ".webm")) link else null,    };}fn recordRenderedLink(    report: ?*LinkReport,    origin: InlineOrigin,    base: usize,    start: usize,    value: []const u8,    link: InlineLink,    image: bool,) void {    const sink = report orelse return;    var entry: RenderedLink = .{ .image = image };    if (origin.locate(base + start, base + link.end)) |span| {        entry.start = span.start;        entry.end = span.end;        entry.located = true;    }    if (entry.located) {        const offset = @intFromPtr(link.target.ptr) - @intFromPtr(value.ptr);        if (origin.locate(base + offset, base + offset + link.target.len)) |span| {            entry.target_start = span.start;            entry.target_end = span.end;            entry.contiguous = span.contiguous;        }    }    sink.record(entry);}fn appendNestedInline(    out: *std.ArrayList(u8),    allocator: Allocator,    source: []const u8,    value: []const u8,    footnotes: ?*footnote.Set,    diag: ?*diagnostic.Diagnostic,    depth: usize,    inside_link: bool,    delimiters: CodeDelimiters,    origin: InlineOrigin,    report: ?*LinkReport,) InlineError!void {    if (depth == max_inline_nesting) {        if (diag) |detail| detail.setInline(value, inline_nesting_reason, 0);        return error.InlineNestingCapacityExceeded;    }    try appendInlineIndexed(        out,        allocator,        source,        value,        footnotes,        diag,        depth + 1,        inside_link,        delimiters,        origin,        report,    );}/// One run of an inline value, and where that run started in the source.const SourceSegment = struct {    joined_start: u32,    source_start: u32,    len: u32,};/// A located span of the rendered source, and whether it is one run.const LocatedSpan = struct {    start: u32,    end: u32,    contiguous: bool,};/// How an inline value's own offsets map back onto the rendered source.const InlineOrigin = union(enum) {    direct: u32,    joined: []const SourceSegment,    untracked,    fn locate(self: InlineOrigin, start: usize, end: usize) ?LocatedSpan {        std.debug.assert(start <= end);        switch (self) {            .untracked => return null,            .direct => |base| {                const located_start = std.math.cast(u32, base + start) orelse return null;                const located_end = std.math.cast(u32, base + end) orelse return null;                return .{ .start = located_start, .end = located_end, .contiguous = true };            },            .joined => |segments| {                const first = segmentContaining(segments, start) orelse return null;                const located_start = std.math.cast(                    u32,                    first.source_start + (start - first.joined_start),                ) orelse return null;                const last_index = if (end > start) end - 1 else start;                const last = segmentContaining(segments, last_index) orelse return null;                const same = last.joined_start == first.joined_start;                const located_end = if (same)                    std.math.cast(u32, first.source_start + (end - first.joined_start)) orelse                        return null                else                    std.math.cast(u32, first.source_start + first.len) orelse return null;                if (located_end < located_start) return null;                return .{ .start = located_start, .end = located_end, .contiguous = same };            },        }    }};fn segmentContaining(segments: []const SourceSegment, offset: usize) ?SourceSegment {    for (segments) |segment| {        if (offset < segment.joined_start) continue;        if (offset - segment.joined_start < segment.len) return segment;    }    return null;}/// Reports where `value` starts inside `source`, or null when it is a copy.fn sourceOffset(source: []const u8, value: []const u8) ?u32 {    const base = @intFromPtr(source.ptr);    const start = @intFromPtr(value.ptr);    if (start < base) return null;    const offset = start - base;    if (offset > source.len or source.len - offset < value.len) return null;    return std.math.cast(u32, offset);}fn originWithin(source: []const u8, value: []const u8) InlineOrigin {    return if (sourceOffset(source, value)) |offset| .{ .direct = offset } else .untracked;}/// Accumulates one inline value from trimmed source lines, recording the/// origin of each line only while a link report is attached.const InlineBuffer = struct {    bytes: std.ArrayList(u8) = .empty,    segments: std.ArrayList(SourceSegment) = .empty,    track: bool = false,    fn deinit(self: *InlineBuffer, allocator: Allocator) void {        self.bytes.deinit(allocator);        self.segments.deinit(allocator);    }    fn items(self: *const InlineBuffer) []const u8 {        return self.bytes.items;    }    fn appendLine(        self: *InlineBuffer,        allocator: Allocator,        source: []const u8,        line: []const u8,    ) Allocator.Error!void {        if (self.bytes.items.len != 0) try self.bytes.append(allocator, ' ');        if (self.track) try self.appendSegment(allocator, source, line);        try self.bytes.appendSlice(allocator, line);    }    fn appendSegment(        self: *InlineBuffer,        allocator: Allocator,        source: []const u8,        line: []const u8,    ) Allocator.Error!void {        const source_start = sourceOffset(source, line) orelse return;        const joined_start = std.math.cast(u32, self.bytes.items.len) orelse return;        const len = std.math.cast(u32, line.len) orelse return;        try self.segments.append(allocator, .{            .joined_start = joined_start,            .source_start = source_start,            .len = len,        });    }    fn origin(self: *const InlineBuffer) InlineOrigin {        if (!self.track) return .untracked;        return .{ .joined = self.segments.items };    }    fn clearRetainingCapacity(self: *InlineBuffer) void {        self.bytes.clearRetainingCapacity();        self.segments.clearRetainingCapacity();    }};const CodeSpan = struct {    content: []const u8,    end: usize,};fn indexCodeDelimiters(    allocator: Allocator,    value: []const u8,    visits: ?*usize,) (Allocator.Error || error{InlineDelimiterCapacityExceeded})!CodeDelimiters {    var count: usize = 0;    var index: usize = 0;    while (index < value.len) {        if (visits) |measured| measured.* += 1;        if (value[index] != '`') {            index += 1;            continue;        }        if (count == max_inline_delimiters) return error.InlineDelimiterCapacityExceeded;        count += 1;        index = measuredBacktickRunEnd(value, index, visits);    }    const items = try allocator.alloc(CodeDelimiter, count);    errdefer allocator.free(items);    index = 0;    var cursor: usize = 0;    while (index < value.len) {        if (visits) |measured| measured.* += 1;        if (value[index] != '`') {            index += 1;            continue;        }        const end = measuredBacktickRunEnd(value, index, visits);        items[cursor] = .{ .start = index, .end = end, .length = end - index };        cursor += 1;        index = end;    }    std.debug.assert(cursor == items.len);    pairCodeDelimiters(items);    return .{ .items = items };}fn measuredBacktickRunEnd(    value: []const u8,    start: usize,    visits: ?*usize,) usize {    std.debug.assert(start < value.len);    std.debug.assert(value[start] == '`');    var end = start + 1;    while (end < value.len and value[end] == '`') : (end += 1) {        if (visits) |measured| measured.* += 1;    }    return end;}fn pairCodeDelimiters(items: []CodeDelimiter) void {    if (items.len < 2) return;    std.mem.sort(CodeDelimiter, items, {}, codeDelimiterLessThan);    var run_start: usize = 0;    while (run_start < items.len) {        var run_end = run_start + 1;        while (run_end < items.len and items[run_end].length == items[run_start].length) {            run_end += 1;        }        var index = run_start;        while (index + 1 < run_end) : (index += 1) {            items[index].closer_end = items[index + 1].end;        }        run_start = run_end;    }    std.mem.sort(CodeDelimiter, items, {}, codeDelimiterByStart);}fn codeDelimiterLessThan(_: void, left: CodeDelimiter, right: CodeDelimiter) bool {    if (left.length != right.length) return left.length < right.length;    return left.start < right.start;}fn codeDelimiterByStart(_: void, left: CodeDelimiter, right: CodeDelimiter) bool {    return left.start < right.start;}fn backtickRunEnd(value: []const u8, start: usize) usize {    std.debug.assert(start < value.len);    std.debug.assert(value[start] == '`');    var end = start + 1;    while (end < value.len and value[end] == '`') : (end += 1) {}    return end;}fn adversarialDelimiterSource(out: []u8) []u8 {    var used: usize = 0;    var length: usize = 1;    while (used + length + 1 <= out.len and length <= max_inline_delimiters) : (length += 1) {        @memset(out[used..][0..length], '`');        used += length;        out[used] = 'x';        used += 1;    }    return out[0..used];}fn exerciseNestedIndex(    source: []const u8,    delimiters: CodeDelimiters,    depth: usize,    max_depth: *usize,) void {    std.debug.assert(depth <= max_inline_nesting);    max_depth.* = @max(max_depth.*, depth);    _ = delimiters.span(source, 0, source.len);    if (depth == max_inline_nesting) return;    exerciseNestedIndex(source, delimiters, depth + 1, max_depth);}fn appendMarkdownEscaped(    out: *std.ArrayList(u8),    allocator: Allocator,    value: []const u8,) Allocator.Error!void {    var index: usize = 0;    while (index < value.len) {        if (value[index] == '\\' and index + 1 < value.len and            isAsciiPunctuation(value[index + 1]))        {            index += 1;        }        try html.appendEscapedByte(out, allocator, value[index]);        index += 1;    }}fn isAsciiPunctuation(byte: u8) bool {    return (byte >= '!' and byte <= '/') or        (byte >= ':' and byte <= '@') or        (byte >= '[' and byte <= '`') or        (byte >= '{' and byte <= '~');}fn inlineMathEnd(value: []const u8, start: usize) ?usize {    if (start + 1 >= value.len) return null;    const first = value[start + 1];    if (first == '$' or first == ' ' or first == '\t') return null;    var index = start + 1;    while (index < value.len) : (index += 1) {        if (value[index] == '\\') {            index += 1;            continue;        }        if (value[index] != '$') continue;        if (index == start + 1) return null;        const previous = value[index - 1];        if (previous == ' ' or previous == '\t') return null;        if (index + 1 < value.len and std.ascii.isDigit(value[index + 1])) return null;        return index;    }    return null;}const InlineLink = struct {    label: []const u8,    target: []const u8,    end: usize,};const InlineParseError = error{    InvalidInlineLink,    InlineNestingCapacityExceeded,};const ImageAttributes = struct {    content: []const u8,    end: usize,};const FootnoteReference = struct {    key: []const u8,    end: usize,};fn parseFootnoteReference(value: []const u8, start: usize) ?FootnoteReference {    if (start + 3 > value.len or value[start] != '[' or value[start + 1] != '^') return null;    const key_end = std.mem.indexOfScalarPos(u8, value, start + 2, ']') orelse return null;    const key = std.mem.trim(u8, value[start + 2 .. key_end], " \t");    if (key.len == 0) return null;    return .{ .key = key, .end = key_end + 1 };}fn parseInlineLink(    source: []const u8,    value: []const u8,    base: usize,    start: usize,    image: bool,    diag: ?*diagnostic.Diagnostic,    delimiters: CodeDelimiters,) InlineParseError!?InlineLink {    const label_start = start + if (image) @as(usize, 2) else @as(usize, 1);    const label_end = try scanLinkLabelEnd(        value,        label_start,        diag,        delimiters,        source,        base,    ) orelse return null;    if (label_end + 1 >= value.len or value[label_end + 1] != '(') return null;    const target_start = label_end + 2;    return try scanLinkTarget(value, label_start, label_end, target_start, diag);}fn scanLinkLabelEnd(    value: []const u8,    start: usize,    diag: ?*diagnostic.Diagnostic,    delimiters: CodeDelimiters,    source: []const u8,    base: usize,) InlineParseError!?usize {    var depth: usize = 0;    var index = start;    while (index < value.len) {        if (value[index] == '\\' and index + 1 < value.len) {            index += 2;            continue;        }        if (value[index] == '`') {            const run_end = backtickRunEnd(value, index);            if (delimiters.span(source, base + index, base + value.len)) |span| {                index = span.end - base;            } else {                index = run_end;            }            continue;        }        if (value[index] == '[') {            if (depth == max_inline_nesting) {                if (diag) |detail| detail.setInline(value, label_nesting_reason, index);                return error.InlineNestingCapacityExceeded;            }            depth += 1;        } else if (value[index] == ']') {            if (depth == 0) return index;            depth -= 1;        }        index += 1;    }    return null;}fn scanLinkTarget(    value: []const u8,    label_start: usize,    label_end: usize,    target_start: usize,    diag: ?*diagnostic.Diagnostic,) InlineParseError!InlineLink {    var depth: usize = 1;    var index = target_start;    while (index < value.len) {        if (value[index] == '\\' and index + 1 < value.len) {            index += 2;            continue;        }        if (value[index] == '(') {            if (depth == max_inline_nesting) {                if (diag) |detail| detail.setInline(value, target_nesting_reason, index);                return error.InlineNestingCapacityExceeded;            }            depth += 1;        } else if (value[index] == ')') {            depth -= 1;            if (depth == 0) return .{                .label = value[label_start..label_end],                .target = std.mem.trim(u8, value[target_start..index], " \t"),                .end = index + 1,            };        }        index += 1;    }    if (diag) |detail| {        detail.setInline(value, "link target is missing closing ')'", target_start - 1);    }    return error.InvalidInlineLink;}fn parseImageAttributes(value: []const u8, start: usize) ?ImageAttributes {    if (start >= value.len or value[start] != '{') return null;    const end = std.mem.indexOfScalarPos(u8, value, start + 1, '}') orelse return null;    const content = std.mem.trim(u8, value[start + 1 .. end], " \t\r\n");    if (content.len == 0) return null;    var widget_count: u8 = 0;    var tokens = std.mem.tokenizeAny(u8, content, " \t\r\n");    while (tokens.next()) |token| {        if (token.len >= 2 and token[0] == '.') {            for (token[1..]) |byte| {                if (!isClassByte(byte)) return null;            }            continue;        }        if (widgetAttributeValue(token) == null or widget_count != 0) return null;        widget_count += 1;    }    return .{ .content = content, .end = end + 1 };}fn appendImageAttributes(    out: *std.ArrayList(u8),    allocator: Allocator,    content: []const u8,) Allocator.Error!void {    var class_count: u8 = 0;    var tokens = std.mem.tokenizeAny(u8, content, " \t\r\n");    while (tokens.next()) |token| {        if (token[0] == '.') class_count += 1;    }    if (class_count != 0) try out.appendSlice(allocator, " class=\"");    var first = true;    tokens = std.mem.tokenizeAny(u8, content, " \t\r\n");    while (tokens.next()) |token| {        if (token[0] != '.') continue;        if (!first) try out.append(allocator, ' ');        try html.appendAttributeEscaped(out, allocator, token[1..]);        first = false;    }    if (class_count != 0) try out.append(allocator, '"');    tokens = std.mem.tokenizeAny(u8, content, " \t\r\n");    while (tokens.next()) |token| {        const widget = widgetAttributeValue(token) orelse continue;        try out.appendSlice(allocator, " data-widget=\"");        try html.appendAttributeEscaped(out, allocator, widget);        try out.append(allocator, '"');    }}fn hasAttributeClass(content: []const u8, expected: []const u8) bool {    var tokens = std.mem.tokenizeAny(u8, content, " \t\r\n");    while (tokens.next()) |token| {        if (token[0] != '.') continue;        if (std.mem.eql(u8, token[1..], expected)) return true;    }    return false;}fn motionPosterBase(target: []const u8) ?usize {    const path_end = std.mem.indexOfAny(u8, target, "?#") orelse target.len;    const path = target[0..path_end];    if (!std.mem.endsWith(u8, path, ".svg")) return null;    return path.len - ".svg".len;}fn isClassByte(byte: u8) bool {    return std.ascii.isAlphanumeric(byte) or byte == '-' or byte == '_';}fn widgetAttributeValue(token: []const u8) ?[]const u8 {    const prefix = "data-widget=\"";    if (!std.mem.startsWith(u8, token, prefix) or        token.len <= prefix.len or token[token.len - 1] != '"')    {        return null;    }    const name = token[prefix.len .. token.len - 1];    if (!validWidgetName(name)) return null;    return name;}fn validWidgetName(name: []const u8) bool {    if (name.len == 0 or name[0] == '-' or name[name.len - 1] == '-') return false;    var previous_hyphen = false;    for (name) |byte| {        const hyphen = byte == '-';        if (!std.ascii.isLower(byte) and !std.ascii.isDigit(byte) and !hyphen) {            return false;        }        if (hyphen and previous_hyphen) return false;        previous_hyphen = hyphen;    }    return true;}const TestInspection = struct {    storage: document.Storage,    value: document.Document,    fn init(allocator: Allocator, source: []const u8) !TestInspection {        const heading_plan = try plan(source);        var storage = try document.Storage.init(allocator, heading_plan.exactLimits());        errdefer storage.deinit(allocator);        storage.activate();        const value = try inspect(&storage, source);        return .{ .storage = storage, .value = value };    }    fn deinit(self: *TestInspection, allocator: Allocator) void {        self.storage.reset();        self.storage.deinit(allocator);        self.* = undefined;    }};const heading_witness =    "# Page\n\n" ++    "```zig\n" ++    "# Not a heading\n" ++    "```\n\n" ++    "> # Quote\n\n" ++    "- item\n" ++    "  # Continuation\n\n" ++    "## Section\n";test "markdown renders headings paragraphs emphasis links and escaping" {    var rendered = try render(        std.testing.allocator,        "# Hello <Zen>\n\n" ++            "A **fast** [site](/docs) with `code` & text.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "Hello <Zen>",        rendered.document.firstHeading().?.text,    );    try std.testing.expectEqual(@as(usize, 1), rendered.document.headings.len);    try std.testing.expectEqual(@as(u8, 1), rendered.document.headings[0].level);    try std.testing.expectEqualStrings("hello-zen", rendered.document.headings[0].id);    try std.testing.expectEqualStrings(        "<h1 id=\"hello-zen\">Hello &lt;Zen&gt;</h1>\n" ++            "<p>A <strong>fast</strong> <a href=\"/docs\">site</a> with <code>code</code> &amp; text.</p>\n",        rendered.html,    );}test "markdown renders semantic pipe tables with inline cell spans" {    var rendered = try render(        std.testing.allocator,        "| Name | Detail | Time |\n" ++            "| :--- | :---: | ---: |\n" ++            "| **fast** | [docs](/docs) and `code` | 12 ms |\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<div class=\"content-table zen-role-wide\" tabindex=\"0\">\n" ++            "<table>\n<thead>\n<tr>\n" ++            "<th scope=\"col\" class=\"zen-table-align-left\">Name</th>\n" ++            "<th scope=\"col\" class=\"zen-table-align-center\">Detail</th>\n" ++            "<th scope=\"col\" class=\"zen-table-align-right\">Time</th>\n" ++            "</tr>\n</thead>\n<tbody>\n<tr>\n" ++            "<td class=\"zen-table-align-left\"><strong>fast</strong></td>\n" ++            "<td class=\"zen-table-align-center\">" ++            "<a href=\"/docs\">docs</a> and <code>code</code></td>\n" ++            "<td class=\"zen-table-align-right\">12 ms</td>\n" ++            "</tr>\n</tbody>\n</table>\n</div>\n",        rendered.html,    );}test "markdown applies an explicit semantic role to a generated index list" {    var rendered = try render(        std.testing.allocator,        "{.docs-index-family .zen-role-wide}\n" ++            "- [one](/one)\n" ++            "- [two](/two)\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<ul class=\"docs-index-family zen-role-wide\">\n" ++            "<li><a href=\"/one\">one</a></li>\n" ++            "<li><a href=\"/two\">two</a></li>\n" ++            "</ul>\n",        rendered.html,    );}test "markdown rejects a semantic list role without its artifact" {    try std.testing.expectError(        error.InvalidSemanticList,        render(            std.testing.allocator,            "{.docs-index-module .zen-role-wide}\nNot a list.\n",            .{},        ),    );}test "markdown promotes explicit roles to artifact paragraph containers" {    var rendered = try render(        std.testing.allocator,        "<span class=\"zen-role-wide\">Dense comparison.</span>\n\n" ++            "![Plot](/plot.svg){.zen-role-margin}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p class=\"zen-role-container zen-role-wide\">" ++            "<span class=\"zen-role-wide\">Dense comparison.</span></p>\n" ++            "<p class=\"zen-media-block zen-role-margin\">" ++            "<img src=\"/plot.svg\" alt=\"Plot\" " ++            "class=\"zen-role-margin\"></p>\n",        rendered.html,    );}test "markdown admits documentation presentation tags only" {    var rendered = try render(        std.testing.allocator,        "<span class=\"docs-breadcrumb\" role=\"navigation\" " ++            "aria-label=\"Declaration hierarchy\">[Reference](/reference/) " ++            "<span aria-hidden=\"true\">›</span> " ++            "<span aria-current=\"page\">`tiny.pretty`</span></span>\n\n" ++            "<span class=\"docs-breadcrumb\" role=\"navigation\" " ++            "aria-label=\"Verification hierarchy\">[Reference](/reference/) " ++            "<span aria-hidden=\"true\">›</span> " ++            "<span aria-current=\"page\">Verification</span></span>\n\n" ++            "<span class=\"docs-sidenote zen-role-margin\">" ++            "Evidence **matters**.</span>\n\n" ++            "<span class=\"docs-verification-freshness-content\">" ++            "**Publication-qualified.** " ++            "<span class=\"docs-verification-source\">" ++            "[`0123`](/source)</span>.</span>\n\n" ++            "<table class=\"docs-audit-table zen-role-wide\">" ++            "<tbody><tr><th>Source</th>" ++            "<td>`root.zig`</td></tr></tbody></table>\n\n" ++            "<span class=\"unsafe\">No.</span><script>No.</script>\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<span class=\"docs-breadcrumb\" role=\"navigation\" " ++            "aria-label=\"Declaration hierarchy\"><a href=\"/reference/\">Reference</a> " ++            "<span aria-hidden=\"true\">›</span> " ++            "<span aria-current=\"page\"><code>tiny.pretty</code></span></span>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<span class=\"docs-breadcrumb\" role=\"navigation\" " ++            "aria-label=\"Verification hierarchy\"><a href=\"/reference/\">Reference</a> " ++            "<span aria-hidden=\"true\">›</span> " ++            "<span aria-current=\"page\">Verification</span></span>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<p class=\"docs-verification-freshness\">" ++            "<span class=\"docs-verification-freshness-content\">" ++            "<strong>Publication-qualified.</strong> " ++            "<span class=\"docs-verification-source\">" ++            "<a href=\"/source\"><code>0123</code></a></span>.</span></p>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<p class=\"docs-sidenote-container zen-role-margin\">" ++            "<span class=\"docs-sidenote zen-role-margin\">" ++            "Evidence <strong>matters</strong>.</span></p>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<table class=\"docs-audit-table zen-role-wide\">" ++            "<tbody><tr><th>Source</th><td><code>root.zig</code>",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "class=\"unsafe\"") == null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<script>") == null);}test "markdown admits validated static call map fences" {    const fragment =        "<figure class=\"docs-call-map docs-call-map-primary zen-role-wide\">" ++        "<svg role=\"group\"><a class=\"zen-ego-node\" href=\"./\">" ++        "<rect x=\"0\"/><text class=\"zen-ego-label\">run</text></a></svg>" ++        "<figcaption>Static calls.</figcaption></figure>";    var rendered = try render(        std.testing.allocator,        "```zen-ego\n" ++ fragment ++ "\n```\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(fragment ++ "\n", rendered.html);    try std.testing.expectError(        error.UnsafeDocumentFragment,        render(            std.testing.allocator,            "```zen-ego\n" ++                "<figure class=\"docs-call-map docs-call-map-primary zen-role-wide\">" ++                "<svg onload=\"x\"></svg>" ++                "<figcaption>Static calls.</figcaption></figure>\n```\n",            .{},        ),    );}test "markdown emits one stylesheet for repeated static call maps" {    var svg_output: [diagram.ego.svg.output_bytes_max]u8 = undefined;    const call_map = try diagram.ego.render(&svg_output, .{        .subject = .{            .label = "run",            .context = "tiny.chic",            .href = "#run",        },    }, .wide);    const style_start = std.mem.indexOf(u8, call_map, "<style>") orelse        return error.TestUnexpectedResult;    const style_close = std.mem.indexOfPos(u8, call_map, style_start, "</style>") orelse        return error.TestUnexpectedResult;    const style_end = style_close + "</style>".len;    const figure_open =        "<figure class=\"docs-call-map docs-call-map-primary zen-role-wide\">";    const figure_close = "<figcaption>Static calls.</figcaption></figure>";    var source: [diagram.ego.svg.document_fragment_bytes_max * 2]u8 = undefined;    var writer = std.Io.Writer.fixed(&source);    for (0..2) |_| {        try writer.writeAll("```zen-ego\n");        try writer.writeAll(figure_open);        try writer.writeAll(call_map);        try writer.writeAll(figure_close);        try writer.writeAll("\n```\n");    }    var preserved = try render(std.testing.allocator, writer.buffered(), .{});    defer preserved.deinit(std.testing.allocator);    var rendered = try render(std.testing.allocator, writer.buffered(), .{        .one_call_map_style_per_page = true,    });    defer rendered.deinit(std.testing.allocator);    var preserved_expected_storage: [diagram.ego.svg.document_fragment_bytes_max * 2]u8 = undefined;    var preserved_expected = std.Io.Writer.fixed(&preserved_expected_storage);    for (0..2) |_| {        try preserved_expected.writeAll(figure_open);        try preserved_expected.writeAll(call_map);        try preserved_expected.writeAll(figure_close);        try preserved_expected.writeByte('\n');    }    try std.testing.expectEqualStrings(preserved_expected.buffered(), preserved.html);    var expected_storage: [diagram.ego.svg.document_fragment_bytes_max * 2]u8 = undefined;    var expected = std.Io.Writer.fixed(&expected_storage);    try expected.writeAll(figure_open);    try expected.writeAll(call_map);    try expected.writeAll(figure_close);    try expected.writeByte('\n');    try expected.writeAll(figure_open);    try expected.writeAll(call_map[0..style_start]);    try expected.writeAll(call_map[style_end..]);    try expected.writeAll(figure_close);    try expected.writeByte('\n');    try std.testing.expectEqualStrings(expected.buffered(), rendered.html);    try std.testing.expectEqual(@as(usize, 1), std.mem.count(        u8,        rendered.html,        "<style>",    ));    for ([_][]const u8{ "<svg ", "class=\"zen-ego-node", " href=\"" }) |marker| {        try std.testing.expectEqual(            std.mem.count(u8, call_map, marker) * 2,            std.mem.count(u8, rendered.html, marker),        );    }    try std.testing.expectEqual(        @as(usize, 2),        std.mem.count(u8, rendered.html, figure_close),    );}test "markdown leaves a page without call maps style-free" {    var rendered = try render(std.testing.allocator, "# Page\n\nNo call maps.\n", .{        .one_call_map_style_per_page = true,    });    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(usize, 0), std.mem.count(        u8,        rendered.html,        "<style>",    ));}test "markdown preserves distinct static call-map styles" {    const opening =        "<figure class=\"docs-call-map docs-call-map-primary zen-role-wide\">" ++        "<svg role=\"group\"><style>";    const closing =        "</style><text class=\"node\">run</text></svg>" ++        "<figcaption>Static calls.</figcaption></figure>";    var source: [2048]u8 = undefined;    var writer = std.Io.Writer.fixed(&source);    for ([_][]const u8{ ".node{fill:red}", ".node{fill:blue}" }) |style| {        try writer.writeAll("```zen-ego\n");        try writer.writeAll(opening);        try writer.writeAll(style);        try writer.writeAll(closing);        try writer.writeAll("\n```\n");    }    var rendered = try render(std.testing.allocator, writer.buffered(), .{        .one_call_map_style_per_page = true,    });    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(usize, 2), std.mem.count(        u8,        rendered.html,        "<style>",    ));    try std.testing.expect(        std.mem.indexOf(u8, rendered.html, ".node{fill:red}") != null,    );    try std.testing.expect(        std.mem.indexOf(u8, rendered.html, ".node{fill:blue}") != null,    );}test "markdown preserves variable backtick spans inside link labels" {    var rendered = try render(        std.testing.allocator,        "[``@\"tick`](/wrong)\"``](safe/#anchor)\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p><a href=\"safe/#anchor\"><code>@&quot;tick`](/wrong)&quot;</code></a></p>\n",        rendered.html,    );}test "markdown pairs each code opener after spans consumed by other lengths" {    var rendered = try render(        std.testing.allocator,        "``a ` b`` c `d`\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p><code>a ` b</code> c <code>d</code></p>\n",        rendered.html,    );    var linked = try render(        std.testing.allocator,        "[``a ` ](/wrong) b`` c `d](/still-wrong)`](safe)\n",        .{},    );    defer linked.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p><a href=\"safe\"><code>a ` ](/wrong) b</code> c " ++            "<code>d](/still-wrong)</code></a></p>\n",        linked.html,    );}test "markdown scans escaped labels and balanced link targets" {    var rendered = try render(        std.testing.allocator,        "[Zig \\[](/types/@\"name\"(u8\\))) and `plain ] )` plus $x$.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p><a href=\"/types/@&quot;name&quot;(u8))\">Zig [</a> and " ++            "<code>plain ] )</code> plus <math><mi>x</mi></math>.</p>\n",        rendered.html,    );}test "markdown never emits anchors inside link labels" {    var rendered = try render(        std.testing.allocator,        "[outer [inner](x) and [^note]](y)\n\n[^note]: Note.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p><a href=\"y\">outer [inner](x) and [^note]</a></p>\n",        rendered.html,    );    const first_anchor = std.mem.indexOf(u8, rendered.html, "<a href=").?;    try std.testing.expect(std.mem.indexOfPos(        u8,        rendered.html,        first_anchor + "<a href=".len,        "<a href=",    ) == null);}test "markdown names malformed inline links and fixed nesting excess" {    var diag: Diagnostic = .{};    const malformed = "Read [the source](/missing.\n";    try std.testing.expectError(error.InvalidInlineLink, render(        std.testing.allocator,        malformed,        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings(malformed[0 .. malformed.len - 1], diag.inlineSource());    try std.testing.expectEqualStrings("link target is missing closing ')'", diag.reason);    try std.testing.expectEqual(@as(usize, 17), diag.offset);    diag.reset();    const nested: [max_inline_nesting + 1]u8 = @splat('[');    const excessive = "[" ++ nested ++ "x](safe)\n";    try std.testing.expectError(error.InlineNestingCapacityExceeded, render(        std.testing.allocator,        excessive,        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings(label_nesting_reason, diag.reason);    try std.testing.expectEqual(@as(usize, max_inline_nesting + 1), diag.offset);}test "markdown accepts exact inline scanner boundaries" {    const labels: [max_inline_nesting]u8 = @splat('[');    const label_closes: [max_inline_nesting]u8 = @splat(']');    const target_opens: [max_inline_nesting - 1]u8 = @splat('(');    const target_closes: [max_inline_nesting - 1]u8 = @splat(')');    const source = "[" ++ labels ++ "x" ++ label_closes ++ "](safe) [x](" ++        target_opens ++ "safe" ++ target_closes ++ ")\n";    var rendered = try render(std.testing.allocator, source, .{});    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "href=\"safe\"") != null);    var diag: Diagnostic = .{};    const excessive: [max_inline_nesting]u8 = @splat('(');    try std.testing.expectError(error.InlineNestingCapacityExceeded, render(        std.testing.allocator,        "[x](" ++ excessive ++ "safe\n",        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings(target_nesting_reason, diag.reason);    try std.testing.expectEqual(@as(usize, max_inline_nesting + 3), diag.offset);}test "markdown keeps incomplete ordinary inline delimiters literal" {    var rendered = try render(        std.testing.allocator,        "Use ``unfinished `code and [plain label without a target.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p>Use ``unfinished `code and [plain label without a target.</p>\n",        rendered.html,    );}test "markdown delimiter indexing has a linear byte-visit bound" {    const source_capacity = 8 * 1024 * 1024;    const source = try std.testing.allocator.alloc(u8, source_capacity);    defer std.testing.allocator.free(source);    const adversarial = adversarialDelimiterSource(source);    try std.testing.expect(adversarial.len > 8 * 1024 * 1024 - 8 * 1024);    var visits: usize = 0;    var delimiters = try indexCodeDelimiters(std.testing.allocator, adversarial, &visits);    defer delimiters.deinit(std.testing.allocator);    try std.testing.expect(visits <= 4 * adversarial.len);}test "markdown rejects delimiter run capacity before allocation" {    try std.testing.expectEqual(code_delimiter_bytes, @sizeOf(CodeDelimiter));    try std.testing.expectEqual(@as(usize, 2_621_440), max_inline_delimiter_bytes);    const exact_bytes = max_inline_delimiters * 2;    const source = try std.testing.allocator.alloc(u8, exact_bytes + 2);    defer std.testing.allocator.free(source);    var index: usize = 0;    while (index < source.len) : (index += 2) {        source[index] = '`';        source[index + 1] = 'x';    }    var counting = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var exact = try indexCodeDelimiters(counting.allocator(), source[0..exact_bytes], null);    defer exact.deinit(counting.allocator());    const allocations = counting.alloc_index;    try std.testing.expectEqual(@as(usize, 1), allocations);    try std.testing.expectEqual(        max_inline_delimiter_bytes,        counting.allocated_bytes,    );    try std.testing.expectError(        error.InlineDelimiterCapacityExceeded,        indexCodeDelimiters(counting.allocator(), source, null),    );    try std.testing.expectEqual(allocations, counting.alloc_index);}test "markdown code spans never close outside their recursive subrange" {    const source = "_`inside_ outside`";    var delimiters = try indexCodeDelimiters(std.testing.allocator, source, null);    defer delimiters.deinit(std.testing.allocator);    var out: std.ArrayList(u8) = .empty;    defer out.deinit(std.testing.allocator);    try appendInlineIndexed(        &out,        std.testing.allocator,        source,        source[1..8],        null,        null,        1,        false,        delimiters,        .untracked,        null,    );    try std.testing.expectEqualStrings("`inside", out.items);}test "markdown reuses one delimiter index through maximum recursion" {    const source = "`code`";    var counting = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var delimiters = try indexCodeDelimiters(counting.allocator(), source, null);    defer delimiters.deinit(counting.allocator());    const index_allocations = counting.alloc_index;    var max_depth: usize = 0;    exerciseNestedIndex(source, delimiters, 0, &max_depth);    try std.testing.expectEqual(max_inline_nesting, max_depth);    try std.testing.expectEqual(index_allocations, counting.alloc_index);    var out: std.ArrayList(u8) = .empty;    defer out.deinit(std.testing.allocator);    try out.ensureTotalCapacity(std.testing.allocator, 64);    try appendInlineIndexed(        &out,        counting.allocator(),        source,        source,        null,        null,        0,        false,        delimiters,        .untracked,        null,    );    try std.testing.expectEqualStrings("<code>code</code>", out.items);    try std.testing.expectEqual(index_allocations, counting.alloc_index);}test "markdown variable fences preserve embedded structural spellings" {    const source =        "````````text\n" ++        "```\n" ++        "```````\n" ++        "</code><a href=\"/wrong\">injection</a>\n" ++        "````````\n";    var rendered = try render(        std.testing.allocator,        source,        .{ .code_blocks = .{ .highlighting = false, .line_numbers = false } },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "```</span></span><span class=\"zen-code-line\">",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "```````") != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "&lt;/code&gt;&lt;a href=&quot;/wrong&quot;&gt;injection&lt;/a&gt;",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<a href=\"/wrong\">") == null);}test "markdown reserves explicit anchors and resolves generated collisions" {    const source =        "```zen-toc\n" ++        "scope: document\n" ++        "```\n\n" ++        "# Generated\n\n" ++        "## Generated\n\n" ++        "## Stable API {#generated}\n\n" ++        "### Render {#tiny.zen.render}\n";    var rendered = try render(std.testing.allocator, source, .{});    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings("generated~1", rendered.document.headings[0].id);    try std.testing.expectEqualStrings("generated~2", rendered.document.headings[1].id);    try std.testing.expectEqualStrings("generated", rendered.document.headings[2].id);    try std.testing.expectEqualStrings("tiny.zen.render", rendered.document.headings[3].id);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<a href=\"#generated\">Stable API</a>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<h3 id=\"tiny.zen.render\">Render</h3>",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "{#") == null);}test "markdown preserves typed path anchors" {    var rendered = try render(        std.testing.allocator,        "## Run {#method/Options/run}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "method/Options/run",        rendered.document.headings[0].id,    );    try std.testing.expectEqualStrings(        "<h2 id=\"method/Options/run\">Run</h2>\n",        rendered.html,    );}test "markdown suffixes generated heading collisions in source order" {    var rendered = try render(        std.testing.allocator,        "# Repeat\n\n# Repeat\n\n# Repeat\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings("repeat", rendered.document.headings[0].id);    try std.testing.expectEqualStrings("repeat~2", rendered.document.headings[1].id);    try std.testing.expectEqualStrings("repeat~3", rendered.document.headings[2].id);}test "explicit anchor syntax preserves unanchored heading output" {    var rendered = try render(        std.testing.allocator,        "# Render {#tiny.zen.render}\n",        .{ .heading_anchors = false },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings("tiny.zen.render", rendered.document.headings[0].id);    try std.testing.expectEqualStrings("<h1>Render</h1>\n", rendered.html);}test "explicit anchor syntax accepts case markers" {    var rendered = try render(        std.testing.allocator,        "# Diagnostic {#decl/~c0~Diagnostic}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "decl/~c0~Diagnostic",        rendered.document.headings[0].id,    );}test "markdown reports invalid and duplicate explicit heading anchors" {    var diag: diagnostic.Diagnostic = .{};    const duplicate = "# First {#same}\n\n## Second {#same}\n";    try std.testing.expectError(error.DuplicateHeadingAnchor, render(        std.testing.allocator,        duplicate,        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings("duplicate heading anchor", diag.reason);    try std.testing.expectEqual(        std.mem.lastIndexOf(u8, duplicate, "{#same}").?,        diag.offset,    );    const invalid = "# Symbol {#not safe}\n";    try std.testing.expectError(error.InvalidHeadingAnchor, render(        std.testing.allocator,        invalid,        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings("invalid heading anchor", diag.reason);    try std.testing.expectEqual(std.mem.indexOf(u8, invalid, "{#").?, diag.offset);}test "markdown inspects headings outside inert blocks" {    var inspected = try TestInspection.init(        std.testing.allocator,        heading_witness,    );    defer inspected.deinit(std.testing.allocator);    const doc = inspected.value;    try std.testing.expectEqual(@as(usize, 2), doc.headings.len);    try std.testing.expectEqualStrings("Page", doc.headings[0].text);    try std.testing.expectEqualStrings("page", doc.headings[0].id);    try std.testing.expectEqualStrings("Section", doc.headings[1].text);    try std.testing.expectEqualStrings("section", doc.headings[1].id);}test "heading storage rejects every limit before backing mutation" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./document/root.zig").Storage, "zen_heading_boundaries"),            null,            null,            null,            null,            null,            null,        );    }    var storage = try document.Storage.init(std.testing.allocator, .{        .max_headings = 2,        .max_text_bytes = 10,        .max_id_bytes = 7,    });    defer storage.deinit(std.testing.allocator);    storage.activate();    @memset(storage.bytes, 42);    try std.testing.expectError(        error.HeadingCapacityExceeded,        inspect(&storage, "# A\n## B\n### C\n"),    );    for (storage.bytes) |byte| try std.testing.expectEqual(@as(u8, 42), byte);    try std.testing.expectError(        error.HeadingTextByteCapacityExceeded,        inspect(&storage, "# abcdef\n## ghijkl\n"),    );    for (storage.bytes) |byte| try std.testing.expectEqual(@as(u8, 42), byte);    try std.testing.expectError(        error.HeadingIdByteCapacityExceeded,        inspect(&storage, "# A\n## ?\n"),    );    for (storage.bytes) |byte| try std.testing.expectEqual(@as(u8, 42), byte);    try std.testing.expectEqual(@as(u64, 3), storage.status().rejected_source_count);    try std.testing.expect(!storage.status().in_use);}test "heading storage reuses one region after success and rejection" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./document/root.zig").Storage, "zen_heading_reuse"),            null,            null,            null,            null,            null,            null,        );    }    var storage = try document.Storage.init(std.testing.allocator, .{        .max_headings = 2,        .max_text_bytes = 16,        .max_id_bytes = 16,    });    defer storage.deinit(std.testing.allocator);    storage.activate();    const base = @intFromPtr(storage.bytes.ptr);    const first = try inspect(&storage, "# First\n## Second\n");    try std.testing.expectEqualStrings("First", first.headings[0].text);    try std.testing.expectError(        error.DocumentStorageInUse,        inspect(&storage, "# Other\n"),    );    try std.testing.expectEqualStrings("First", first.headings[0].text);    storage.reset();    try std.testing.expectError(        error.HeadingCapacityExceeded,        inspect(&storage, "# A\n## B\n### C\n"),    );    const second = try inspect(&storage, "# Other\n");    try std.testing.expectEqualStrings("Other", second.headings[0].text);    storage.reset();    try std.testing.expectEqual(base, @intFromPtr(storage.bytes.ptr));    try std.testing.expectEqual(@as(usize, 2), storage.status().high_water_headings);    try std.testing.expectEqual(@as(u64, 2), storage.status().rejected_source_count);}test "activated heading inspection performs no backing allocation" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./document/root.zig").Storage, "zen_heading_sealed"),            null,            null,            null,            null,            null,            null,        );    }    const heading_plan = try plan(heading_witness);    const capacity = try document.Capacity.derive(heading_plan.exactLimits());    var counting = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var storage = try document.Storage.init(counting.allocator(), heading_plan.exactLimits());    defer storage.deinit(counting.allocator());    storage.activate();    const allocations = counting.alloc_index;    const resizes = counting.resize_index;    const bytes = counting.allocated_bytes;    counting.fail_index = allocations;    counting.resize_fail_index = resizes;    const doc = try inspect(&storage, heading_witness);    defer storage.reset();    try std.testing.expectEqual(@as(usize, 2), doc.headings.len);    try std.testing.expectEqual(@as(usize, 1), allocations);    try std.testing.expectEqual(@as(usize, 0), resizes);    try std.testing.expectEqual(capacity.storage_bytes, bytes);    try std.testing.expectEqual(allocations, counting.alloc_index);    try std.testing.expectEqual(resizes, counting.resize_index);    try std.testing.expectEqual(bytes, counting.allocated_bytes);}test "heading storage owns text independently from the Markdown source" {    var source = [_]u8{ '#', ' ', 'P', 'a', 'g', 'e', '\n' };    const heading_plan = try plan(&source);    var storage = try document.Storage.init(std.testing.allocator, heading_plan.exactLimits());    defer storage.deinit(std.testing.allocator);    storage.activate();    const doc = try inspect(&storage, &source);    defer storage.reset();    @memset(&source, 'x');    try std.testing.expectEqualStrings("Page", doc.headings[0].text);    try std.testing.expectEqualStrings("page", doc.headings[0].id);}test "Markdown rendering owns exact heading storage" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./document/root.zig").Storage, "zen_heading_consumer"),            null,            null,            null,            null,            null,            null,        );    }    const source = "# Page\n\n## Section\n";    const heading_plan = try plan(source);    const capacity = try document.Capacity.derive(heading_plan.exactLimits());    var rendered = try render(std.testing.allocator, source, .{});    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqual(capacity.storage_bytes, rendered.document_storage.bytes.len);    try std.testing.expectEqualStrings("Page", rendered.document.firstHeading().?.text);}test "markdown renders generated contents from following headings" {    var rendered = try render(        std.testing.allocator,        "# Page\n\n" ++            "```zen-toc\n" ++            "scope: following\n" ++            "min-level: 2\n" ++            "max-level: 3\n" ++            "```\n\n" ++            "## First\n\n" ++            "### Detail\n\n" ++            "# Next page root\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<h1 id=\"page\">Page</h1>\n" ++            "<nav class=\"zen-contents zen-role-wide\" aria-label=\"Contents\">\n" ++            "<p>Contents:</p>\n" ++            "<ul>\n" ++            "<li class=\"zen-contents-level-2\"><a href=\"#first\">First</a></li>\n" ++            "<li class=\"zen-contents-level-3\" style=\"margin-left:calc(1 * 1.5rem)\"><a href=\"#detail\">Detail</a></li>\n" ++            "</ul>\n" ++            "</nav>\n" ++            "<h2 id=\"first\">First</h2>\n" ++            "<h3 id=\"detail\">Detail</h3>\n" ++            "<h1 id=\"next-page-root\">Next page root</h1>\n",        rendered.html,    );}test "markdown rejects invalid contents directives" {    try std.testing.expectError(error.InvalidContentsDirective, render(        std.testing.allocator,        "```zen-toc\n" ++            "scope: nowhere\n" ++            "```\n",        .{},    ));}test "markdown renders quiz fences with hidden answers" {    var rendered = try render(        std.testing.allocator,        "```zen-quiz\n" ++            "? Which module owns the grammar?\n" ++            "- `markdown.zig`\n" ++            "* `quiz.zig`\n" ++            "! The typed data lives beside the renderer.\n" ++            "```\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<section class=\"zen-quiz\" aria-label=\"Quiz\">\n" ++            "<ol class=\"zen-quiz-questions\">\n" ++            "<li class=\"zen-quiz-question\">\n" ++            "<p class=\"zen-quiz-prompt\">Which module owns the grammar?</p>\n" ++            "<ul class=\"zen-quiz-options\">\n" ++            "<li><code>markdown.zig</code></li>\n" ++            "<li><code>quiz.zig</code></li>\n" ++            "</ul>\n" ++            "<details class=\"zen-quiz-answer\">\n" ++            "<summary>Reveal answer</summary>\n" ++            "<p class=\"zen-quiz-correct\"><strong><code>quiz.zig</code></strong></p>\n" ++            "<p class=\"zen-quiz-explanation\">The typed data lives beside the renderer.</p>\n" ++            "</details>\n" ++            "</li>\n" ++            "</ol>\n" ++            "</section>\n",        rendered.html,    );}test "markdown renders recall quiz questions without options" {    var rendered = try render(        std.testing.allocator,        "```quiz\n" ++            "? What does the reveal block hold?\n" ++            "! The explanation.\n" ++            "```\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<section class=\"zen-quiz\" aria-label=\"Quiz\">\n" ++            "<ol class=\"zen-quiz-questions\">\n" ++            "<li class=\"zen-quiz-question\">\n" ++            "<p class=\"zen-quiz-prompt\">What does the reveal block hold?</p>\n" ++            "<details class=\"zen-quiz-answer\">\n" ++            "<summary>Reveal answer</summary>\n" ++            "<p class=\"zen-quiz-explanation\">The explanation.</p>\n" ++            "</details>\n" ++            "</li>\n" ++            "</ol>\n" ++            "</section>\n",        rendered.html,    );}test "markdown rejects invalid quiz fences" {    try std.testing.expectError(error.InvalidQuizDirective, render(        std.testing.allocator,        "```zen-quiz\n" ++            "? A prompt with one lonely option\n" ++            "* only\n" ++            "```\n",        .{},    ));}test "Markdown reuses one quiz region across fences" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./quiz/root.zig").Storage, "zen_quiz_consumer"),            null,            null,            null,            null,            null,            null,        );    }    const limits = quiz.Limits{        .max_questions = 1,        .max_options = 2,        .max_joined_text_bytes = "First answer continued".len,    };    const capacity = try quiz.Capacity.derive(limits);    var counting = std.testing.FailingAllocator.init(std.testing.allocator, .{});    var owner: QuizOwner = .{};    defer owner.deinit(counting.allocator());    const first = try owner.parse(        counting.allocator(),        "? First\n! First answer\ncontinued\n",        limits,    );    try std.testing.expectEqualStrings("First answer continued", first.questions[0].explanation);    const base = @intFromPtr(owner.storage.?.bytes.ptr);    owner.reset();    try std.testing.expectEqual(@as(usize, 1), counting.alloc_index);    try std.testing.expectEqual(capacity.storage_bytes, counting.allocated_bytes);    counting.fail_index = counting.alloc_index;    counting.resize_fail_index = counting.resize_index;    const second = try owner.parse(        counting.allocator(),        "? Second\n* Correct\n- Other\n",        limits,    );    try std.testing.expectEqualStrings("Second", second.questions[0].prompt);    try std.testing.expectEqual(@as(usize, 2), second.questions[0].options.len);    owner.reset();    try std.testing.expectEqual(base, @intFromPtr(owner.storage.?.bytes.ptr));    try std.testing.expectEqual(@as(usize, 1), counting.alloc_index);    try std.testing.expectEqual(capacity.storage_bytes, counting.allocated_bytes);}test "Markdown exposes quiz limits at the render boundary" {    try std.testing.expectError(error.QuestionCapacityExceeded, render(        std.testing.allocator,        "```quiz\n? Question\n! Answer\n```\n",        .{ .quiz_limits = .{            .max_questions = 0,            .max_options = 0,            .max_joined_text_bytes = 0,        } },    ));}test "Markdown exposes heading limits at the render boundary" {    try std.testing.expectError(error.HeadingCapacityExceeded, render(        std.testing.allocator,        "# Heading\n",        .{ .heading_limits = .{            .max_headings = 0,            .max_text_bytes = 0,            .max_id_bytes = 0,        } },    ));}test "Markdown exposes footnote limits at the render boundary" {    const source = "[^one]: First\n  continued\n";    try std.testing.expectError(error.FootnoteDefinitionCapacityExceeded, render(        std.testing.allocator,        source,        .{ .footnote_limits = .{            .max_definitions = 0,            .max_joined_text_bytes = 0,        } },    ));    try std.testing.expectError(error.FootnoteJoinedTextByteCapacityExceeded, render(        std.testing.allocator,        source,        .{ .footnote_limits = .{            .max_definitions = 1,            .max_joined_text_bytes = "First continued".len - 1,        } },    ));}test "markdown renders explicit slide decks" {    var rendered = try render(        std.testing.allocator,        "# Title\n\n" ++            "---\n\n" ++            "## Second\n\n" ++            "---\n",        .{ .mode = .slides, .slides = .{ .runtime = false } },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<div class=\"zen-slides\" data-zen-slides>\n" ++            "<section class=\"zen-slide\" id=\"slide-1\" aria-label=\"Slide 1\">\n" ++            "<div class=\"zen-slide-frame\">\n" ++            "<h1 id=\"title\">Title</h1>\n" ++            "</div>\n" ++            "</section>\n" ++            "<section class=\"zen-slide\" id=\"slide-2\" aria-label=\"Slide 2\">\n" ++            "<div class=\"zen-slide-frame\">\n" ++            "<h2 id=\"second\">Second</h2>\n" ++            "</div>\n" ++            "</section>\n" ++            "</div>\n" ++            slides.print.stylesheet,        rendered.html,    );}test "markdown renders speaker notes in slide decks" {    var rendered = try render(        std.testing.allocator,        "# Title\n\n" ++            "```notes\n" ++            "Remember the concrete example.\n" ++            "```\n",        .{ .mode = .slides, .slides = .{ .runtime = false } },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<aside class=\"zen-speaker-notes\" data-zen-speaker-notes hidden>") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<p>Remember the concrete example.</p>") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "zen-code-block") == null);}test "markdown drops empty speaker notes in slide decks" {    var rendered = try render(        std.testing.allocator,        "# Title\n\n" ++            "```notes\n" ++            "\n" ++            "```\n",        .{ .mode = .slides, .slides = .{ .runtime = false } },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<aside class=\"zen-speaker-notes\"") == null);}test "markdown leaves notes fences as code outside slide decks" {    var rendered = try render(        std.testing.allocator,        "```notes\n" ++            "ordinary note code\n" ++            "```\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "zen-speaker-notes") == null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "ordinary note code") != null);}test "markdown opens wide document figures at full size" {    var rendered = try render(        std.testing.allocator,        "![Plot](/plot.svg){.zen-slide-figure-wide}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p class=\"zen-media-block zen-role-wide\">" ++            "<a href=\"/plot.svg\" target=\"_blank\" rel=\"noopener\" " ++            "aria-label=\"Open Plot at full size\">" ++            "<img src=\"/plot.svg\" alt=\"Plot\" " ++            "class=\"zen-slide-figure-wide\"></a></p>\n",        rendered.html,    );}test "markdown slide decks preserve media math code and diagrams" {    var rendered = try render(        std.testing.allocator,        "# Media\n\n" ++            "![Plot](/plot.svg){.zen-slide-figure-wide}\n\n" ++            "---\n\n" ++            "## Math and Code\n\n" ++            "$$ E = mc^2 $$\n\n" ++            "```zig\n" ++            "const x = 1 < 2;\n" ++            "```\n\n" ++            "---\n\n" ++            "```zen-diagram\n" ++            "{\"kind\":\"frame\",\"title\":\"Coin\",\"y_min\":0,\"y_max\":1}\n" ++            "{\"kind\":\"bar\",\"x\":\"heads\",\"y\":0.62,\"label\":\"heads\"}\n" ++            "```\n",        .{ .mode = .slides, .diagram_width = 36, .diagram_height = 10 },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<section class=\"zen-slide\" id=\"slide-3\"") != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<p class=\"zen-media-block zen-role-reading\">" ++            "<img src=\"/plot.svg\" alt=\"Plot\" " ++            "class=\"zen-slide-figure-wide\"></p>",    ) != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<a href=\"/plot.svg\"",    ) == null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<math display=\"block\">") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "zen-code-block") != null);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<pre class=\"zen-diagram zen-role-wide\"><code>",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "<hr>") == null);}test "markdown renders webm figures as looping videos with poster fallback" {    var rendered = try render(        std.testing.allocator,        "![Dam break](/assets/sph.webm){.zen-slide-figure-wide}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p class=\"zen-media-block zen-role-wide\">" ++            "<video src=\"/assets/sph.webm\" poster=\"/assets/sph.webp\" " ++            "aria-label=\"Dam break\" autoplay loop muted playsinline " ++            "class=\"zen-slide-figure-wide\"></video></p>\n",        rendered.html,    );}test "markdown renders motion figures as static posters" {    var rendered = try render(        std.testing.allocator,        "![Agent loop](/assets/loop.svg?revision=1){.zen-slide-motion\n.zen-slide-figure-wide}\n",        .{ .mode = .slides, .slides = .{ .runtime = false } },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<img src=\"/assets/loop.poster.svg?revision=1\" data-zen-motion-src=\"/assets/loop.svg?revision=1\" alt=\"Agent loop\" decoding=\"async\" class=\"zen-slide-motion zen-slide-figure-wide\">",    ) != null);}test "markdown renders a bounded widget selector on an image" {    var rendered = try render(        std.testing.allocator,        "![Accy demo](/assets/poster.svg){.demo data-widget=\"accy-wos\"}\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p class=\"zen-media-block zen-role-reading\">" ++            "<img src=\"/assets/poster.svg\" alt=\"Accy demo\" " ++            "class=\"demo\" data-widget=\"accy-wos\"></p>\n",        rendered.html,    );}test "markdown renders lists blockquotes code fences and images" {    var rendered = try render(        std.testing.allocator,        "- one\n" ++            "- two\n\n" ++            "> quoted\n" ++            "> text\n\n" ++            "```zig\n" ++            "const x = 1 < 2;\n" ++            "```\n\n" ++            "![Logo](/logo.svg)\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<ul>\n" ++            "<li>one</li>\n" ++            "<li>two</li>\n" ++            "</ul>\n" ++            "<blockquote><p>quoted text</p></blockquote>\n" ++            "<div class=\"zen-code-block zen-code-wrap zen-code-example " ++            "zen-role-reading\" data-language=\"zig\"><div class=\"zen-code-header\">" ++            "<span class=\"zen-code-language\">zig</span></div>" ++            "<pre class=\"zen-code\"><code class=\"language-zig\">" ++            "<span class=\"zen-code-line\"><span class=\"zen-code-line-number\" " ++            "aria-hidden=\"true\">1</span><span class=\"zen-code-line-source\">" ++            "<span class=\"zen-code-keyword\">const</span> x = " ++            "<span class=\"zen-code-number\">1</span> &lt; " ++            "<span class=\"zen-code-number\">2</span>;</span></span>" ++            "</code></pre></div>\n" ++            "<p class=\"zen-media-block zen-role-reading\">" ++            "<img src=\"/logo.svg\" alt=\"Logo\"></p>\n",        rendered.html,    );}test "markdown renders continued list items and blockquote inline markup" {    var rendered = try render(        std.testing.allocator,        "- first item wraps\n" ++            "  onto the next line\n" ++            "- second _Item_\n\n" ++            "> **John R. Levine, _Linkers &\n" ++            "> Loaders_**\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<ul>\n" ++            "<li>first item wraps onto the next line</li>\n" ++            "<li>second <em>Item</em></li>\n" ++            "</ul>\n" ++            "<blockquote><p><strong>John R. Levine, <em>Linkers &amp; Loaders</em></strong></p></blockquote>\n",        rendered.html,    );}test "markdown renders footnote references and definitions" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./footnote/root.zig").Storage, "zen_footnote_consumer"),            null,            null,            null,            null,            null,            null,        );    }    var rendered = try render(        std.testing.allocator,        "Alpha[^paper] beta[^paper] gamma[^block] missing[^none].\n\n" ++            "[^paper]: A [paper](/paper)\n" ++            "  with `code`.\n" ++            "[^block]:\n" ++            "    Block style.\n" ++            "[^unused]: Hidden.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p>Alpha<sup id=\"fnref-paper\"><a class=\"footnote-ref\" href=\"#fn-paper\">[1]</a></sup> beta<sup id=\"fnref-paper-2\"><a class=\"footnote-ref\" href=\"#fn-paper\">[1]</a></sup> gamma<sup id=\"fnref-block\"><a class=\"footnote-ref\" href=\"#fn-block\">[2]</a></sup> missing[^none].</p>\n" ++            "<section class=\"footnotes\" aria-label=\"References\">\n" ++            "<ol>\n" ++            "<li id=\"fn-paper\">A <a href=\"/paper\">paper</a> with <code>code</code>. <a class=\"footnote-backref\" href=\"#fnref-paper\" aria-label=\"Back to reference\">&#8617;</a></li>\n" ++            "<li id=\"fn-block\">Block style. <a class=\"footnote-backref\" href=\"#fnref-block\" aria-label=\"Back to reference\">&#8617;</a></li>\n" ++            "</ol>\n" ++            "</section>\n",        rendered.html,    );}test "markdown keeps the first duplicate footnote definition" {    var rendered = try render(        std.testing.allocator,        "Use[^same].\n\n" ++            "[^same]: First.\n" ++            "[^same]: Second\n" ++            "  ignored continuation.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "First.") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "Second") == null);}test "markdown renders inline and display math" {    var rendered = try render(        std.testing.allocator,        "Euler saw $e^{i\\pi} + 1 = 0$ here.\n\n" ++            "$$\n" ++            "u(x) = \\mathbb{E}[u(x + R\\omega)]\n" ++            "$$\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p>Euler saw <math><mrow><msup><mi>e</mi><mrow><mi>i</mi><mi>π</mi></mrow></msup>" ++            "<mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn></mrow></math> here.</p>\n" ++            "<math display=\"block\"><mrow><mi>u</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo>" ++            "<mi>𝔼</mi><mo stretchy=\"false\">[</mo><mi>u</mi><mo stretchy=\"false\">(</mo><mi>x</mi><mo>+</mo><mi>R</mi><mi>ω</mi>" ++            "<mo stretchy=\"false\">)</mo><mo stretchy=\"false\">]</mo></mrow></math>\n",        rendered.html,    );}test "markdown renders single line display math" {    var rendered = try render(std.testing.allocator, "$$ E = mc^2 $$\n", .{});    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<math display=\"block\"><mrow><mi>E</mi><mo>=</mo><mi>m</mi>" ++            "<msup><mi>c</mi><mn>2</mn></msup></mrow></math>\n",        rendered.html,    );}test "markdown renders display environments across lines" {    var rendered = try render(        std.testing.allocator,        "$$\n" ++            "\\begin{aligned}\n" ++            "a &= b \\\\\n" ++            "&= c\n" ++            "\\end{aligned}\n" ++            "$$\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<math display=\"block\"><mtable displaystyle=\"true\" class=\"zen-aligned\">" ++            "<mtr><mtd><mi>a</mi></mtd><mtd><mo>=</mo><mi>b</mi></mtd></mtr>" ++            "<mtr><mtd></mtd><mtd><mo>=</mo><mi>c</mi></mtd></mtr>" ++            "</mtable></math>\n",        rendered.html,    );}test "markdown guards prose dollars and honors escapes" {    var rendered = try render(        std.testing.allocator,        "It costs $5 and $10 to run, but \\$x\\$ stays literal.\n",        .{},    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p>It costs $5 and $10 to run, but $x$ stays literal.</p>\n",        rendered.html,    );}test "markdown fails loudly on invalid math" {    try std.testing.expectError(error.InvalidEquation, render(        std.testing.allocator,        "Broken $\\nonesuch$ command.\n",        .{},    ));    try std.testing.expectError(error.InvalidEquation, render(        std.testing.allocator,        "$$\nx = 1\n",        .{},    ));}test "markdown names the offending equation" {    var diag: Diagnostic = .{};    try std.testing.expectError(error.InvalidEquation, render(        std.testing.allocator,        "Broken $\\nonesuch$ command.\n",        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings("\\nonesuch", diag.equation());    try std.testing.expectEqualStrings("unknown command", diag.reason);    try std.testing.expectEqual(@as(usize, 0), diag.offset);    diag.reset();    try std.testing.expectError(error.InvalidEquation, render(        std.testing.allocator,        "$$\nu(x) = \\frac{1}\n$$\n",        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings("u(x) = \\frac{1}", diag.equation());    try std.testing.expectEqualStrings("missing argument", diag.reason);    try std.testing.expectEqual(@as(usize, 15), diag.offset);    diag.reset();    try std.testing.expectError(error.InvalidEquation, render(        std.testing.allocator,        "$$\nx = 1\n",        .{ .diagnostic = &diag },    ));    try std.testing.expectEqualStrings("x = 1", diag.equation());    try std.testing.expectEqualStrings("missing closing '$$'", diag.reason);}test "markdown leaves math inside code spans alone" {    var rendered = try render(std.testing.allocator, "Use `$x$` verbatim.\n", .{});    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(        "<p>Use <code>$x$</code> verbatim.</p>\n",        rendered.html,    );}test "markdown renders diagram fences as ASCII" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./diagram/ascii/root.zig").RenderStorage, "zen_ascii_render_consumer"),            null,            null,            null,            null,            null,            null,        );    }    var rendered = try render(        std.testing.allocator,        "```zen-diagram\n" ++            "{\"kind\":\"frame\",\"title\":\"Coin\",\"y_min\":0,\"y_max\":1}\n" ++            "{\"kind\":\"bar\",\"x\":\"heads\",\"y\":0.62,\"label\":\"heads\"}\n" ++            "```\n",        .{ .diagram_width = 36, .diagram_height = 10 },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(        u8,        rendered.html,        "<pre class=\"zen-diagram zen-role-wide\"><code>",    ) != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "Coin") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "#") != null);    try std.testing.expect(std.mem.indexOf(u8, rendered.html, "{\"kind\"") == null);}test "link reports locate a direct paragraph target" {    const source = "See [the allocator](allocator.zig) for detail.\n";    var storage: [4]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    const links = report.links();    try std.testing.expectEqual(@as(usize, 1), links.len);    try std.testing.expect(links[0].located);    try std.testing.expect(links[0].contiguous);    try std.testing.expect(!links[0].image);    try std.testing.expectEqualStrings(        "allocator.zig",        source[links[0].target_start..links[0].target_end],    );    try std.testing.expectEqualStrings(        "[the allocator](allocator.zig)",        source[links[0].start..links[0].end],    );}test "link reports locate a target carried across joined source lines" {    const source = "See [the\nallocator](allocator.zig) for detail.\n";    var storage: [4]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    const links = report.links();    try std.testing.expectEqual(@as(usize, 1), links.len);    try std.testing.expect(links[0].located);    try std.testing.expect(links[0].contiguous);    try std.testing.expectEqualStrings(        "allocator.zig",        source[links[0].target_start..links[0].target_end],    );}test "link reports emit a nested image after its enclosing link" {    const source = "[![badge](badge.svg)](capacity/root.zig)\n";    var storage: [4]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    const links = report.links();    try std.testing.expectEqual(@as(usize, 2), links.len);    try std.testing.expect(!links[0].image);    try std.testing.expect(links[1].image);    try std.testing.expectEqualStrings(        "capacity/root.zig",        source[links[0].target_start..links[0].target_end],    );    try std.testing.expectEqualStrings(        "badge.svg",        source[links[1].target_start..links[1].target_end],    );    try std.testing.expect(links[1].target_start < links[0].target_start);}test "link reports name the exhausted report capacity" {    var storage: [1]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        "[a](a.zig) and [b](b.zig)\n",        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expect(report.overflowed);    try std.testing.expectEqual(@as(usize, 1), report.count);}test "link reports ignore targets inside fenced and inline code" {    const source = "```\n[a](a.zig)\n```\n\nText `[b](b.zig)` text.\n";    var storage: [4]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    try std.testing.expectEqual(@as(usize, 0), report.links().len);}test "link reporting leaves ordinary rendered output unchanged" {    const source =        "# Title\n\nSee [one](one.zig) and ![two](two.svg).\n\n" ++        "- item [three](three.zig)\n- item two\n\n" ++        "> quoted [four](four.zig)\n\n" ++        "| head | head |\n| :--- | :--- |\n| [five](five.zig) | cell |\n";    var plain = try render(std.testing.allocator, source, .{});    defer plain.deinit(std.testing.allocator);    var storage: [16]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var reported = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer reported.deinit(std.testing.allocator);    try std.testing.expectEqualStrings(plain.html, reported.html);    try std.testing.expectEqual(@as(usize, 5), report.links().len);}test "link reports cover list, blockquote and table blocks" {    const source =        "- item [one](one.zig)\n\n" ++        "> quoted [two](two.zig)\n\n" ++        "| head |\n| :--- |\n| [three](three.zig) |\n";    var storage: [8]RenderedLink = undefined;    var report: LinkReport = .{ .storage = &storage };    var rendered = try render(        std.testing.allocator,        source,        .{ .link_report = &report },    );    defer rendered.deinit(std.testing.allocator);    const links = report.links();    try std.testing.expectEqual(@as(usize, 3), links.len);    for (links, [_][]const u8{ "one.zig", "two.zig", "three.zig" }) |link, expected| {        try std.testing.expect(link.located);        try std.testing.expect(link.contiguous);        try std.testing.expectEqualStrings(            expected,            source[link.target_start..link.target_end],        );    }}

Source: lib/zen/src/root.zig:27

zig
/// Markdown inspection and owned HTML rendering.pub const markdown = @import("markdown.zig");

Audit

Definitions3
Public names3
Members0
Version26.7.0
Revisiondaab053ee433