const std = @import("std");
const md = @import("./markdown_parser.zig");
+const strings = @import("./string_utils.zig");
const stdC = @cImport({
@cInclude("stdio.h");
}
if (self.opts.template) |t| {
+ const replaced = try strings.replace(alloc, t, "{body}", self.buffer.items);
+ self.buffer.deinit(alloc);
+ self.buffer = std.ArrayList(u8).fromOwnedSlice(replaced);
}
return self.buffer.items;
test "can format empty document with template" {
const alloc = std.testing.allocator;
const template =
- \\<body>%s</body>
+ \\<body>{body}</body>
;
var formatter = HtmlFormatter.init(.{ .template = template });
defer formatter.deinit(alloc);
test "can format empty non-document with template" {
const alloc = std.testing.allocator;
const template =
- \\<body>%s</body>
+ \\<body>{body}</body>
;
var formatter = HtmlFormatter.init(.{ .template = template });
defer formatter.deinit(alloc);
--- /dev/null
+const std = @import("std");
+
+/// Replace target in s by replacement.
+/// Return an owned buffer.
+pub fn replace(alloc: std.mem.Allocator, s: []const u8, target: []const u8, replacement: []const u8) ![]u8 {
+ var buffer = try std.ArrayList(u8).initCapacity(alloc, s.len);
+
+ var i: usize = 0;
+ while (i < s.len) {
+ var j: usize = i;
+ const matched = while (j < s.len and j - i < target.len) {
+ if (s[j] != target[j - i]) break false;
+ j += 1;
+ } else true;
+ if (matched) {
+ try buffer.appendSlice(alloc, replacement);
+ i = j;
+ } else {
+ try buffer.append(alloc, s[i]);
+ i += 1;
+ }
+ }
+
+ return try buffer.toOwnedSlice(alloc);
+}
+
+test "replace can replace single instance of target in string" {
+ var alloc = std.testing.allocator;
+
+ const s = "This is a {target}";
+ const target = "{target}";
+ const replacement = "test";
+
+ const result = try replace(alloc, s, target, replacement);
+ defer alloc.free(result);
+
+ try std.testing.expectEqualStrings("This is a test", result);
+}
+
+test "replace can replace multiple instances of target in string" {
+ var alloc = std.testing.allocator;
+
+ const s = "This is a {target} to {target} {target}s";
+ const target = "{target}";
+ const replacement = "test";
+
+ const result = try replace(alloc, s, target, replacement);
+ defer alloc.free(result);
+
+ try std.testing.expectEqualStrings("This is a test to test tests", result);
+}
+
+test "replace when replacing target with target is a no-op" {
+ var alloc = std.testing.allocator;
+
+ const s = "This is a {target} to {target} {target}s";
+ const target = "{target}";
+ const replacement = "{target}";
+
+ const result = try replace(alloc, s, target, replacement);
+ defer alloc.free(result);
+
+ try std.testing.expectEqualStrings(s, result);
+}