diff options
Diffstat (limited to 'src/eval/html/html.zig')
| -rw-r--r-- | src/eval/html/html.zig | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/eval/html/html.zig b/src/eval/html/html.zig new file mode 100644 index 0000000..064ebb1 --- /dev/null +++ b/src/eval/html/html.zig @@ -0,0 +1,47 @@ +const std = @import("std"); +const eql = std.mem.eql; + +pub const Error = error{InvalidUtf8} || std.mem.Allocator.Error; + +pub fn escape(alloc: std.mem.Allocator, v: []const u8) Error![]const u8 { + var acc = try std.ArrayList(u8).initCapacity(alloc, v.len); + errdefer acc.deinit(alloc); + const view = try std.unicode.Utf8View.init(v); + var iter = view.iterator(); + while (iter.nextCodepointSlice()) |rune| { + if (eql(u8, rune, "&")) { + try acc.appendSlice(alloc, "&"); + } else if (eql(u8, rune, "'")) { + try acc.appendSlice(alloc, "'"); + } else if (eql(u8, rune, "<")) { + try acc.appendSlice(alloc, "<"); + } else if (eql(u8, rune, ">")) { + try acc.appendSlice(alloc, ">"); + } else if (eql(u8, rune, "\"")) { + try acc.appendSlice(alloc, """); + } else { + try acc.appendSlice(alloc, rune); + } + } + return acc.toOwnedSlice(alloc); +} + +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" { + const alloc = std.testing.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"); +} |
