tiny.markdown.block
Defined in tiny.markdown.
API (4)
Actions
Public operations.
Types and contracts
Public types and contracts.
Source
Source: lib/markdown/src/block.zig
zig
const std = @import("std");pub const BlockType = enum { paragraph, heading1, heading2, heading3, heading4, code_block, bullet_list, numbered_list, blockquote, horizontal_rule,};pub const Block = struct { block_type: BlockType = .paragraph, content: []const u8, indent: u8 = 0, number: ?u16 = null, language: ?[]const u8 = null,};pub const Parsed = struct { block_type: BlockType, content: []const u8, number: ?u16, indent: u8,};pub fn parseType(line: []const u8) Parsed { const indent = markdownIndent(line); const trimmed = trimLeft(line, " \t"); if (trimmed.len == 0) { return .{ .block_type = .paragraph, .content = "", .number = null, .indent = indent }; } if (trimmed.len >= 3 and (std.mem.startsWith(u8, trimmed, "---") or std.mem.startsWith(u8, trimmed, "***") or std.mem.startsWith(u8, trimmed, "___"))) { var all_same = true; const first = trimmed[0]; for (trimmed) |c| { if (c != first and c != ' ') { all_same = false; break; } } if (all_same) { return .{ .block_type = .horizontal_rule, .content = "", .number = null, .indent = indent }; } } if (std.mem.startsWith(u8, trimmed, "#### ")) { return .{ .block_type = .heading4, .content = trimmed[5..], .number = null, .indent = indent }; } if (std.mem.startsWith(u8, trimmed, "### ")) { return .{ .block_type = .heading3, .content = trimmed[4..], .number = null, .indent = indent }; } if (std.mem.startsWith(u8, trimmed, "## ")) { return .{ .block_type = .heading2, .content = trimmed[3..], .number = null, .indent = indent }; } if (std.mem.startsWith(u8, trimmed, "# ")) { return .{ .block_type = .heading1, .content = trimmed[2..], .number = null, .indent = indent }; } if (std.mem.startsWith(u8, trimmed, "> ")) { return .{ .block_type = .blockquote, .content = trimmed[2..], .number = null, .indent = indent }; } if (std.mem.startsWith(u8, trimmed, ">")) { return .{ .block_type = .blockquote, .content = trimmed[1..], .number = null, .indent = indent }; } if (trimmed.len >= 2 and (trimmed[0] == '-' or trimmed[0] == '*' or trimmed[0] == '+') and trimmed[1] == ' ') { return .{ .block_type = .bullet_list, .content = trimmed[2..], .number = null, .indent = indent }; } if (trimmed.len >= 3) { var num_end: usize = 0; while (num_end < trimmed.len and trimmed[num_end] >= '0' and trimmed[num_end] <= '9') { num_end += 1; } if (num_end > 0 and num_end < trimmed.len and trimmed[num_end] == '.' and num_end + 1 < trimmed.len and trimmed[num_end + 1] == ' ') { const num = std.fmt.parseInt(u16, trimmed[0..num_end], 10) catch 1; return .{ .block_type = .numbered_list, .content = trimmed[num_end + 2 ..], .number = num, .indent = indent }; } } if (std.mem.startsWith(u8, trimmed, "```")) { return .{ .block_type = .code_block, .content = trimmed[3..], .number = null, .indent = indent }; } return .{ .block_type = .paragraph, .content = trimmed, .number = null, .indent = indent };}fn markdownIndent(line: []const u8) u8 { var columns: usize = 0; for (line) |char| { switch (char) { ' ' => columns += 1, '\t' => columns += 4, else => break, } } return @intCast(@min(columns / 2, @as(usize, std.math.maxInt(u8))));}fn trimLeft(bytes: []const u8, values: []const u8) []const u8 { var start: usize = 0; while (start < bytes.len and std.mem.indexOfScalar(u8, values, bytes[start]) != null) start += 1; return bytes[start..];}test "parseType heading" { const h1 = parseType("# Title"); try std.testing.expectEqual(BlockType.heading1, h1.block_type); try std.testing.expectEqualStrings("Title", h1.content); const h2 = parseType("## Subtitle"); try std.testing.expectEqual(BlockType.heading2, h2.block_type); const h3 = parseType("### Section"); try std.testing.expectEqual(BlockType.heading3, h3.block_type);}test "parseType bullet list" { const bullet = parseType("- Item"); try std.testing.expectEqual(BlockType.bullet_list, bullet.block_type); try std.testing.expectEqualStrings("Item", bullet.content); try std.testing.expectEqual(@as(u8, 0), bullet.indent); const star = parseType("* Another"); try std.testing.expectEqual(BlockType.bullet_list, star.block_type); const nested = parseType(" - Nested"); try std.testing.expectEqual(BlockType.bullet_list, nested.block_type); try std.testing.expectEqual(@as(u8, 1), nested.indent);}test "parseType numbered list" { const num = parseType("1. First"); try std.testing.expectEqual(BlockType.numbered_list, num.block_type); try std.testing.expectEqualStrings("First", num.content); try std.testing.expectEqual(@as(?u16, 1), num.number); const num2 = parseType("42. Item"); try std.testing.expectEqual(@as(?u16, 42), num2.number); const nested = parseType("\t3. Nested"); try std.testing.expectEqual(@as(?u16, 3), nested.number); try std.testing.expectEqual(@as(u8, 2), nested.indent);}test "parseType blockquote" { const quote = parseType("> Quote text"); try std.testing.expectEqual(BlockType.blockquote, quote.block_type); try std.testing.expectEqualStrings("Quote text", quote.content);}test "parseType horizontal rule" { const hr1 = parseType("---"); try std.testing.expectEqual(BlockType.horizontal_rule, hr1.block_type); const hr2 = parseType("***"); try std.testing.expectEqual(BlockType.horizontal_rule, hr2.block_type);}test "parseType paragraph" { const para = parseType("Normal text"); try std.testing.expectEqual(BlockType.paragraph, para.block_type); try std.testing.expectEqualStrings("Normal text", para.content);}test "BlockType values" { try std.testing.expectEqual(BlockType.paragraph, BlockType.paragraph); try std.testing.expectEqual(BlockType.heading1, BlockType.heading1); try std.testing.expectEqual(BlockType.code_block, BlockType.code_block);}Source: lib/markdown/src/root.zig:9
zig
pub const block = @import("block.zig");Audit
| Definitions | 1 |
|---|---|
| Public names | 1 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |