diff options
| -rw-r--r-- | build.zig | 6 | ||||
| -rw-r--r-- | src/paragraph.zig | 38 | ||||
| -rw-r--r-- | src/parser.zig | 30 | ||||
| -rw-r--r-- | src/title.zig | 40 |
4 files changed, 78 insertions, 36 deletions
@@ -15,7 +15,9 @@ pub fn build(b: *std.Build) void { .linkage = .dynamic, .root_module = mod, }); - b.installArtifact(lib); + const installed_lib = b.addInstallArtifact(lib, .{}); + // when emitting headers will be fixed + //installed_lib.emitted_h = lib.getEmittedH(); const example = b.addExecutable(.{ .name = "example", @@ -29,7 +31,6 @@ pub fn build(b: *std.Build) void { .file = b.path("examples/main.c"), }); example.root_module.linkLibrary(lib); - // manually writing headers because lib.getEmittedH() doesn't work. example.root_module.addIncludePath(b.path("include")); const mod_tests = b.addTest(.{ @@ -41,6 +42,7 @@ pub fn build(b: *std.Build) void { test_step.dependOn(&run_mod_tests.step); const examples_step = b.step("examples", "Run examples"); + examples_step.dependOn(&installed_lib.step); const example_run = b.addRunArtifact(example); examples_step.dependOn(&example_run.step); } diff --git a/src/paragraph.zig b/src/paragraph.zig index 222f376..caee73e 100644 --- a/src/paragraph.zig +++ b/src/paragraph.zig @@ -5,7 +5,7 @@ const Lexer = @import("lexer/Lexer.zig"); const Element = @import("dom/Element.zig"); const parser = @import("parser.zig"); -pub const Error = error{ModifierNotClosed, IllegalPlacement} || Lexer.Error; +pub const Error = error{ ModifierNotClosed, IllegalPlacement } || Lexer.Error; pub fn parse(alloc: Allocator, l: *Lexer) Error!Element { var el = try Element.init(alloc, .content, "p"); @@ -47,7 +47,8 @@ pub fn parseLine(alloc: Allocator, l: *Lexer) Error!Element { fn parseContent(alloc: Allocator, l: *Lexer) Error!Element { var content = Element.initEmpty(alloc); errdefer content.deinit(); - const v = (try l.next(alloc)).?; + var v = (try l.next(alloc)).?; + defer v.deinit(); switch (v.kind) { .literal => { const el = try Element.initLitEscaped(alloc, v.content.items); @@ -76,3 +77,36 @@ fn parseModifier(alloc: Allocator, l: *Lexer, knd: Lexed.Kind, tag: []const u8) } return Error.ModifierNotClosed; } + +fn doTest(alloc: Allocator, t: []const u8, v: []const u8) !void { + var l = try Lexer.init(t); + var p = try parse(alloc, &l); + defer p.deinit(); + const g = try p.render(alloc); + defer alloc.free(g); + std.testing.expect(std.mem.eql(u8, g, v)) catch |err| { + std.debug.print("{s}\n", .{g}); + return err; + }; +} + +fn doTestError(alloc: Allocator, t: []const u8, err: Error) !void { + var l = try Lexer.init(t); + _ = parse(alloc, &l) catch |e| return std.testing.expect(err == e); + return std.testing.expect(false); +} + +test "parse paragraphs" { + var arena = std.heap.DebugAllocator(.{}).init; + defer if (arena.deinit() == .leak) std.debug.print("leaking!\n", .{}); + const alloc = arena.allocator(); + + try doTest(alloc, "hello world", "<p>hello world</p>"); + try doTest(alloc, "*hello* world", "<p><b>hello</b> world</p>"); + try doTest(alloc, "*he_ll_o* world", "<p><b>he<em>ll</em>o</b> world</p>"); + + try doTestError(alloc, "hello *world", Error.ModifierNotClosed); + try doTestError(alloc, "hello *wo_rld*", Error.ModifierNotClosed); + try doTestError(alloc, "*hell*o *wo_rld*", Error.ModifierNotClosed); + try doTestError(alloc, "hello ::: world", Error.IllegalPlacement); +} diff --git a/src/parser.zig b/src/parser.zig index 442d823..f109a88 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -49,20 +49,11 @@ fn doTest(alloc: Allocator, t: []const u8, v: []const u8) !void { }; } -fn doTestError(alloc: Allocator, t: []const u8, err: Error) !void { - _ = parse(alloc, t) catch |e| return std.testing.expect(err == e); - return std.testing.expect(false); -} - -test "parse paragraphs" { +test "parse multilines" { var arena = std.heap.DebugAllocator(.{}).init; defer if (arena.deinit() == .leak) std.debug.print("leaking!\n", .{}); const alloc = arena.allocator(); - try doTest(alloc, "hello world", "<p>hello world</p>"); - try doTest(alloc, "*hello* world", "<p><b>hello</b> world</p>"); - try doTest(alloc, "*he_ll_o* world", "<p><b>he<em>ll</em>o</b> world</p>"); - try doTest(alloc, \\hello \\world @@ -71,29 +62,10 @@ test "parse paragraphs" { \\in new paragraph , "<p>hello world</p><p>foo bar in new paragraph</p>"); - try doTestError(alloc, "hello *world", Error.ModifierNotClosed); - try doTestError(alloc, "hello *wo_rld*", Error.ModifierNotClosed); - try doTestError(alloc, "*hell*o *wo_rld*", Error.ModifierNotClosed); - try doTestError(alloc, "hello ::: world", Error.IllegalPlacement); -} - -test "parse title" { - var arena = std.heap.DebugAllocator(.{}).init; - defer if (arena.deinit() == .leak) std.debug.print("leaking!\n", .{}); - const alloc = arena.allocator(); - - try doTest(alloc, "# hey", "<h1>hey</h1>"); - try doTest(alloc, "## hey", "<h2>hey</h2>"); - try doTest(alloc, "### hey", "<h3>hey</h3>"); - - try doTest(alloc, "# hello *world*", "<h1>hello <b>world</b></h1>"); - try doTest(alloc, \\# title \\hello world ;3 \\## subtitle \\hehe , "<h1>title</h1><p>hello world ;3</p><h2>subtitle</h2><p>hehe</p>"); - - try doTestError(alloc, "# aa :::", Error.InvalidTitleContent); } diff --git a/src/title.zig b/src/title.zig index de88c67..62d7929 100644 --- a/src/title.zig +++ b/src/title.zig @@ -9,6 +9,7 @@ pub const Error = error{InvalidTitleContent} || paragraph.Error || Lexer.Error; pub fn parse(alloc: Allocator, l: *Lexer) Error!Element { var v = (try l.next(alloc)).?; + defer v.deinit(); var el = try Element.init(alloc, .content, switch (v.content.items.len) { 1 => "h1", 2 => "h2", @@ -18,12 +19,45 @@ pub fn parse(alloc: Allocator, l: *Lexer) Error!Element { 6 => "h6", else => unreachable, }); + errdefer el.deinit(); try el.appendContent(paragraph.parseLine(alloc, l) catch |err| switch (err) { paragraph.Error.IllegalPlacement => return Error.InvalidTitleContent, else => return err, }); - v = (try l.next(alloc)) orelse return el; - if (!v.kind.isDelimiter()) return Error.InvalidTitleContent; - v.deinit(); + var next = (try l.next(alloc)) orelse return el; + defer next.deinit(); + if (!next.kind.isDelimiter()) return Error.InvalidTitleContent; return el; } + +fn doTest(alloc: Allocator, t: []const u8, v: []const u8) !void { + var l = try Lexer.init(t); + var p = try parse(alloc, &l); + defer p.deinit(); + const g = try p.render(alloc); + defer alloc.free(g); + std.testing.expect(std.mem.eql(u8, g, v)) catch |err| { + std.debug.print("{s}\n", .{g}); + return err; + }; +} + +fn doTestError(alloc: Allocator, t: []const u8, err: Error) !void { + var l = try Lexer.init(t); + _ = parse(alloc, &l) catch |e| return std.testing.expect(err == e); + return std.testing.expect(false); +} + +test "parse title" { + var arena = std.heap.DebugAllocator(.{}).init; + defer if (arena.deinit() == .leak) std.debug.print("leaking!\n", .{}); + const alloc = arena.allocator(); + + try doTest(alloc, "# hey", "<h1>hey</h1>"); + try doTest(alloc, "## hey", "<h2>hey</h2>"); + try doTest(alloc, "### hey", "<h3>hey</h3>"); + + try doTest(alloc, "# hello *world*", "<h1>hello <b>world</b></h1>"); + + try doTestError(alloc, "# aa :::", Error.InvalidTitleContent); +} |
