Skip to documentation
SLOP

tiny.zen.renderMarkdown

Reference tiny.zen renderMarkdown

Defined in markdown.

Renders Markdown and returns an owner that must be deinitialized with the same allocator.

Called byCallsprivate sourcelib.zen.src.markdownappendSpeakerNotestest sourcelib.zen.src.markdowntest: Markdown exposes footnote limit...test sourcelib.zen.src.markdowntest: Markdown exposes heading limits...test sourcelib.zen.src.markdowntest: Markdown exposes quiz limits at...test sourcelib.zen.src.markdowntest: Markdown rendering owns exact h...+58 moreprivate; no linklib.zen.src.footnoteparsehtmlappendAttributeEscapedprivate sourcelib.zen.src.markdown.InlineBufferappendLineprivate sourcelib.zen.src.markdown.InlineBufferdeinitprivate sourcelib.zen.src.markdown.QuizOwnerdeinit+24 moremarkdownrender
Static calls · unresolved targets: 2 · external targets: 22.

Source

Source: lib/zen/src/markdown.zig:340

zig
/// 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,    };}

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

zig
/// Renders Markdown into an owned result; release it with the same allocator.////// Malformed link targets return `InvalidInlineLink`. Inline input beyond/// `max_markdown_inline_delimiters` or `max_markdown_inline_nesting` returns the/// corresponding capacity error with source-local `Diagnostic` repair detail./// The nesting cap covers recursive links/emphasis, label brackets, and target/// parentheses.pub const renderMarkdown = markdown.render;

Complete caller list

63 direct callers.

Complete call list

29 direct calls.

Audit

Definitions1
Public names2
Members0
Version26.7.0
Revisiondaab053ee433