aboutsummaryrefslogtreecommitdiff
path: root/src/code.zig
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2026-04-26 23:10:17 +0200
committerAnhgelus Morhtuuzh <william@herges.fr>2026-04-26 23:17:26 +0200
commitde948492e8b38a79d5db9c506c1b7b82e86c6b12 (patch)
tree122e4c004d37193c64d6b8b89d9a252f7e237cfa /src/code.zig
parentae6ee68d6f4ef79fef609b4d09b543fc06326e95 (diff)
feat(): support code block
Diffstat (limited to 'src/code.zig')
-rw-r--r--src/code.zig61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/code.zig b/src/code.zig
new file mode 100644
index 0000000..98bba42
--- /dev/null
+++ b/src/code.zig
@@ -0,0 +1,61 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const eql = std.mem.eql;
+const Token = @import("lexer/Token.zig");
+const Lexer = @import("lexer/Lexer.zig");
+const Element = @import("eval/Element.zig");
+const testing = @import("testing.zig");
+const doTest = testing.do;
+const doTestError = testing.doError;
+
+pub const Error = error{InvalidCodeBlock} || Allocator.Error;
+
+pub fn parse(alloc: Allocator, l: *Lexer) Error!Element {
+ _ = l.next();
+ var beg = l.next() orelse return Error.InvalidCodeBlock;
+ var data: ?[]const u8 = null;
+ switch (beg.kind) {
+ .literal => {
+ data = beg.content;
+ beg = l.next() orelse return Error.InvalidCodeBlock;
+ if (!beg.kind.isDelimiter()) return Error.InvalidCodeBlock;
+ },
+ else => if (!beg.kind.isDelimiter()) return Error.InvalidCodeBlock,
+ }
+ const code = try Element.Code.init(alloc);
+ code.attribute = data;
+ const el = try Element.Figure.init(alloc, code.element());
+ errdefer el.deinit(alloc);
+ while (l.next()) |it| {
+ if (it.kind == .code_block) return Error.InvalidCodeBlock;
+ if (it.kind.isDelimiter()) {
+ const next = l.peek() orelse return Error.InvalidCodeBlock;
+ if (next.kind == .code_block) break;
+ }
+ try code.content.append(alloc, (try Element.Literal.init(alloc, it.content)).element());
+ // restore modifications done by the lexer
+ if (it.kind.requiresSpace())
+ try code.content.append(alloc, (try Element.Literal.init(alloc, " ")).element());
+ }
+ var end = l.next() orelse return Error.InvalidCodeBlock;
+ if (end.kind != .code_block) return Error.InvalidCodeBlock;
+ end = l.next() orelse return el.element();
+ if (!end.kind.isDelimiter()) return Error.InvalidCodeBlock;
+ return el.element();
+}
+
+test "code" {
+ const alloc = std.testing.allocator;
+
+ try doTest(parse, alloc,
+ \\```
+ \\hey
+ \\```
+ , "<figure><pre><code>hey</code></pre></figure>");
+ try doTest(parse, alloc,
+ \\```td another
+ \\hey
+ \\```
+ , "<figure><pre data-code=\"td another\"><code>hey</code></pre></figure>");
+ // cannot test content with \n
+}