Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

appendBlockStart

Parser.appendBlockStart
fn appendBlockStart(p: *Parser, block_start: BlockStart) !void

File

Code

fn appendBlockStart(p: *Parser, block_start: BlockStart) !void {
    if (p.pending_blocks.getLast()) |last_pending_block| {
        // Close the last block if it is a list and the new block is not a list item
        // or not of the same marker type.
        const should_close_list = last_pending_block.tag == .list and
            (block_start.tag != .list_item or
                block_start.data.list_item.marker != last_pending_block.data.list.marker);
        // The last block should also be closed if the new block is not a table
        // row, which is the only allowed child of a table.
        const should_close_table = last_pending_block.tag == .table and
            block_start.tag != .table_row;
        if (should_close_list or should_close_table) {
            try p.closeLastBlock();
        }
    }

    if (p.pending_blocks.getLast()) |last_pending_block| {
        // If the last block is a list or list item, check for tightness based
        // on the last line.
        const maybe_containing_list = switch (last_pending_block.tag) {
            .list => &p.pending_blocks.items[p.pending_blocks.items.len - 1],
            .list_item => &p.pending_blocks.items[p.pending_blocks.items.len - 2],
            else => null,
        };
        if (maybe_containing_list) |containing_list| {
            if (containing_list.data.list.last_line_blank) {
                containing_list.data.list.tight = false;
            }
        }
    }

    // Start a new list if the new block is a list item and there is no
    // containing list yet.
    if (block_start.tag == .list_item and
        (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .list))
    {
        try p.pending_blocks.append(p.allocator, .{
            .tag = .list,
            .data = .{ .list = .{
                .marker = block_start.data.list_item.marker,
                .start = block_start.data.list_item.number,
                .tight = true,
            } },
            .string_start = p.scratch_string.items.len,
            .extra_start = p.scratch_extra.items.len,
        });
    }

    if (block_start.tag == .table_row) {
        // Likewise, table rows start a table implicitly.
        if (p.pending_blocks.items.len == 0 or p.pending_blocks.getLast().?.tag != .table) {
            try p.pending_blocks.append(p.allocator, .{
                .tag = .table,
                .data = .{ .table = .{
                    .column_alignments_buffer = undefined,
                    .column_alignments_len = 0,
                } },
                .string_start = p.scratch_string.items.len,
                .extra_start = p.scratch_extra.items.len,
            });
        }

        const current_row = p.scratch_extra.items.len - p.pending_blocks.getLast().?.extra_start;
        if (current_row <= 1) {
            var buffer: [max_table_columns]Node.TableCellAlignment = undefined;
            const table_row = &block_start.data.table_row;
            if (parseTableHeaderDelimiter(table_row.cells_buffer[0..table_row.cells_len], &buffer)) |alignments| {
                const table = &p.pending_blocks.items[p.pending_blocks.items.len - 1].data.table;
                @memcpy(table.column_alignments_buffer[0..alignments.len], alignments);
                table.column_alignments_len = alignments.len;
                if (current_row == 1) {
                    // We need to go back and mark the header row and its column
                    // alignments.
                    const datas = p.nodes.items(.data);
                    const header_data = datas[p.scratch_extra.getLast().?];
                    for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| {
                        const alignment = if (i < alignments.len) alignments[i] else .unset;
                        const cell_data = &datas[@backingInt(header_cell)].table_cell;
                        cell_data.info.alignment = alignment;
                        cell_data.info.header = true;
                    }
                }
                return;
            }
        }
    }

    const tag: Block.Tag, const data: Block.Data = switch (block_start.tag) {
        .list_item => .{ .list_item, .{ .list_item = .{
            .continuation_indent = block_start.data.list_item.continuation_indent,
        } } },
        .table_row => .{ .table_row, .{ .none = {} } },
        .heading => .{ .heading, .{ .heading = .{
            .level = block_start.data.heading.level,
        } } },
        .code_block => .{ .code_block, .{ .code_block = .{
            .tag = block_start.data.code_block.tag,
            .fence_len = block_start.data.code_block.fence_len,
            .indent = block_start.data.code_block.indent,
        } } },
        .blockquote => .{ .blockquote, .{ .none = {} } },
        .paragraph => .{ .paragraph, .{ .none = {} } },
        .thematic_break => .{ .thematic_break, .{ .none = {} } },
    };

    try p.pending_blocks.append(p.allocator, .{
        .tag = tag,
        .data = data,
        .string_start = p.scratch_string.items.len,
        .extra_start = p.scratch_extra.items.len,
    });

    if (tag == .table_row) {
        // Table rows are unique, since we already have all the children
        // available in the BlockStart. We can immediately parse and append
        // these children now.
        const containing_table = p.pending_blocks.items[p.pending_blocks.items.len - 2];
        const table = &containing_table.data.table;
        const column_alignments = table.column_alignments_buffer[0..table.column_alignments_len];
        const table_row = &block_start.data.table_row;
        for (table_row.cells_buffer[0..table_row.cells_len], 0..) |cell_content, i| {
            const cell_children = try p.parseInlines(cell_content);
            const alignment = if (i < column_alignments.len) column_alignments[i] else .unset;
            const cell = try p.addNode(.{
                .tag = .table_cell,
                .data = .{ .table_cell = .{
                    .info = .{
                        .alignment = alignment,
                        .header = false,
                    },
                    .children = cell_children,
                } },
            });
            try p.addScratchExtraNode(cell);
        }
    }
}