feature. See also
. The project being documented here (as the example) is the Zig library itself.
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| {
// 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);
// 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| {
// 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;
}
}
}
// 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) {
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) {
// 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) {
// 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);
}
}
}