diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dom/Element.zig | 6 | ||||
| -rw-r--r-- | src/dom/html.zig | 47 |
2 files changed, 51 insertions, 2 deletions
diff --git a/src/dom/Element.zig b/src/dom/Element.zig index ed7611c..1922a41 100644 --- a/src/dom/Element.zig +++ b/src/dom/Element.zig @@ -1,6 +1,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const eql = std.mem.eql; +const html = @import("html.zig"); pub const Kind = enum { void, @@ -92,8 +93,9 @@ fn renderAttribute(self: *Self, alloc: Allocator) !std.ArrayList(u8) { while (iter.next()) |it| : (i += 1) { try acc.appendSlice(alloc, it.key_ptr.*); try acc.appendSlice(alloc, "=\""); - // MISSING ESCAPING!!! - try acc.appendSlice(alloc, it.value_ptr.*); + const escape = try html.escape(alloc, it.value_ptr.*); + defer alloc.free(escape); + try acc.appendSlice(alloc, escape); try acc.append(alloc, '"'); if (i < iter.len - 1) try acc.append(alloc, ' '); } diff --git a/src/dom/html.zig b/src/dom/html.zig new file mode 100644 index 0000000..bf62fbb --- /dev/null +++ b/src/dom/html.zig @@ -0,0 +1,47 @@ +const std = @import("std"); +const eql = std.mem.eql; + +pub fn escape(gpa: std.mem.Allocator, v: []const u8) ![]const u8 { + var acc = try std.ArrayList(u8).initCapacity(gpa, v.len); + errdefer acc.deinit(gpa); + const view = try std.unicode.Utf8View.init(v); + var iter = view.iterator(); + while (iter.nextCodepointSlice()) |rune| { + if (eql(u8, rune, "&")) { + try acc.appendSlice(gpa, "&"); + } else if (eql(u8, rune, "'")) { + try acc.appendSlice(gpa, "'"); + } else if (eql(u8, rune, "<")) { + try acc.appendSlice(gpa, "<"); + } else if (eql(u8, rune, ">")) { + try acc.appendSlice(gpa, ">"); + } else if (eql(u8, rune, "\"")) { + try acc.appendSlice(gpa, """); + } else { + try acc.appendSlice(gpa, rune); + } + } + return acc.toOwnedSlice(gpa); +} + +fn doTest(alloc: std.mem.Allocator, el: []const u8, exp: []const u8) !void { + const got = try escape(alloc, el); + defer alloc.free(got); + std.testing.expect(eql(u8, got, exp)) catch |err| { + std.debug.print("{s}\n", .{got}); + return err; + }; +} + +test "escaping html" { + var arena = std.heap.DebugAllocator(.{}).init; + defer _ = arena.deinit(); + const alloc = arena.allocator(); + + try doTest(alloc, "hello world", "hello world"); + try doTest(alloc, "hello&world", "hello&world"); + try doTest(alloc, "hello'world", "hello'world"); + try doTest(alloc, "hello<world", "hello<world"); + try doTest(alloc, "hello>world", "hello>world"); + try doTest(alloc, "hello\"world", "hello"world"); +} |
