mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-15 15:58:57 +00:00
implement CData.render
This commit is contained in:
@@ -60,6 +60,57 @@ pub fn getData(self: *const CData) []const u8 {
|
||||
return self._data;
|
||||
}
|
||||
|
||||
pub const RenderOpts = struct {
|
||||
trim_left: bool = true,
|
||||
trim_right: bool = true,
|
||||
};
|
||||
// Replace successives whitespaces with one withespace.
|
||||
// Trims left and right according to the options.
|
||||
pub fn render(self: *const CData, writer: *std.io.Writer, opts: RenderOpts) !void {
|
||||
var start: usize = 0;
|
||||
var prev_w: ?bool = null;
|
||||
var is_w: bool = undefined;
|
||||
const s = self._data;
|
||||
|
||||
for (s, 0..) |c, i| {
|
||||
is_w = std.ascii.isWhitespace(c);
|
||||
|
||||
// Detect the first char type.
|
||||
if (prev_w == null) {
|
||||
prev_w = is_w;
|
||||
}
|
||||
// The current char is the same kind of char, the chunk continues.
|
||||
if (prev_w.? == is_w) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Starting here, the chunk changed.
|
||||
if (is_w) {
|
||||
// We have a chunk of non-whitespaces, we write it as it.
|
||||
try writer.writeAll(s[start..i]);
|
||||
} else {
|
||||
// We have a chunk of whitespaces, replace with one space,
|
||||
// depending the position.
|
||||
if (start > 0 or !opts.trim_left) {
|
||||
try writer.writeByte(' ');
|
||||
}
|
||||
}
|
||||
// Start the new chunk.
|
||||
prev_w = is_w;
|
||||
start = i;
|
||||
}
|
||||
// Write the reminder chunk.
|
||||
if (is_w) {
|
||||
// Last chunk is whitespaces.
|
||||
if (opts.trim_right == false) {
|
||||
try writer.writeByte(' ');
|
||||
}
|
||||
} else {
|
||||
// last chunk is non whitespaces.
|
||||
try writer.writeAll(s[start..]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setData(self: *CData, value: ?[]const u8, page: *Page) !void {
|
||||
const old_value = self._data;
|
||||
|
||||
@@ -223,3 +274,42 @@ const testing = @import("../../testing.zig");
|
||||
test "WebApi: CData" {
|
||||
try testing.htmlRunner("cdata", .{});
|
||||
}
|
||||
|
||||
test "WebApi: CData.render" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const TestCase = struct {
|
||||
value: []const u8,
|
||||
expected: []const u8,
|
||||
opts: RenderOpts = .{},
|
||||
};
|
||||
|
||||
const test_cases = [_]TestCase{
|
||||
.{ .value = "foo bar", .expected = "foo bar" },
|
||||
.{ .value = "foo bar", .expected = "foo bar" },
|
||||
.{ .value = " foo bar", .expected = "foo bar" },
|
||||
.{ .value = "foo bar ", .expected = "foo bar" },
|
||||
.{ .value = " foo bar ", .expected = "foo bar" },
|
||||
.{ .value = "foo\n\tbar", .expected = "foo bar" },
|
||||
.{ .value = "\tfoo bar baz \t\n yeah\r\n", .expected = "foo bar baz yeah" },
|
||||
.{ .value = " foo bar", .expected = " foo bar", .opts = .{ .trim_left = false } },
|
||||
.{ .value = "foo bar ", .expected = "foo bar ", .opts = .{ .trim_right = false } },
|
||||
.{ .value = " foo bar ", .expected = " foo bar ", .opts = .{ .trim_left = false, .trim_right = false } },
|
||||
};
|
||||
|
||||
var buffer = std.io.Writer.Allocating.init(allocator);
|
||||
defer buffer.deinit();
|
||||
for (test_cases) |test_case| {
|
||||
buffer.clearRetainingCapacity();
|
||||
|
||||
const cdata = CData{
|
||||
._type = .{ .text = undefined },
|
||||
._proto = undefined,
|
||||
._data = test_case.value,
|
||||
};
|
||||
|
||||
try cdata.render(&buffer.writer, test_case.opts);
|
||||
|
||||
try std.testing.expectEqualStrings(test_case.expected, buffer.written());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,22 +239,7 @@ pub fn getInnerText(self: *Element, writer: *std.Io.Writer) !void {
|
||||
},
|
||||
.cdata => |c| switch (c._type) {
|
||||
.comment => continue,
|
||||
.text => {
|
||||
const data = c.getData();
|
||||
if (std.mem.trim(u8, data, &std.ascii.whitespace).len != 0) {
|
||||
// Trim all whitespaces except spaces.
|
||||
// TODO this is not the correct way to render text, this is
|
||||
// a temp approximation.
|
||||
const text = std.mem.trim(u8, data, &[_]u8{
|
||||
'\t',
|
||||
'\n',
|
||||
'\r',
|
||||
std.ascii.control_code.vt,
|
||||
std.ascii.control_code.ff,
|
||||
});
|
||||
try writer.writeAll(text);
|
||||
}
|
||||
},
|
||||
.text => try c.render(writer, .{}),
|
||||
},
|
||||
.document => {},
|
||||
.document_type => {},
|
||||
|
||||
Reference in New Issue
Block a user