Skip to content

Commit 1846345

Browse files
committed
xmlserializer for doctype
1 parent 527579a commit 1846345

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

src/browser/dump.zig

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,32 @@ pub fn writeHTML(doc: *parser.Document, writer: anytype) !void {
2828
try writer.writeAll("\n");
2929
}
3030

31+
// Spec: https://www.w3.org/TR/xml/#sec-prolog-dtd
32+
pub fn writeDocType(doc_type: *parser.DocumentType, writer: anytype) !void {
33+
try writer.writeAll("<!DOCTYPE ");
34+
try writer.writeAll(try parser.documentTypeGetName(doc_type));
35+
36+
const public_id = try parser.documentTypeGetPublicId(doc_type);
37+
const system_id = try parser.documentTypeGetSystemId(doc_type);
38+
if (public_id.len != 0 and system_id.len != 0) {
39+
try writer.writeAll(" PUBLIC \"");
40+
try writeEscapedAttributeValue(writer, public_id);
41+
try writer.writeAll("\" \"");
42+
try writeEscapedAttributeValue(writer, system_id);
43+
try writer.writeAll("\"");
44+
} else if (public_id.len != 0) {
45+
try writer.writeAll(" PUBLIC \"");
46+
try writeEscapedAttributeValue(writer, public_id);
47+
try writer.writeAll("\"");
48+
} else if (system_id.len != 0) {
49+
try writer.writeAll(" SYSTEM \"");
50+
try writeEscapedAttributeValue(writer, system_id);
51+
try writer.writeAll("\"");
52+
}
53+
// Internal subset is not implemented
54+
try writer.writeAll(">");
55+
}
56+
3157
pub fn writeNode(node: *parser.Node, writer: anytype) anyerror!void {
3258
switch (try parser.nodeType(node)) {
3359
.element => {
@@ -88,7 +114,7 @@ pub fn writeNode(node: *parser.Node, writer: anytype) anyerror!void {
88114
.document_fragment => return,
89115
// document will never be called, but required for completeness.
90116
.document => return,
91-
// done globally instead, but required for completeness.
117+
// done globally instead, but required for completeness. Only the outer DOCTYPE should be written
92118
.document_type => return,
93119
// deprecated
94120
.attribute => return,

src/browser/xmlserializer/xmlserializer.zig

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ pub const XMLSerializer = struct {
3535

3636
pub fn _serializeToString(_: *const XMLSerializer, root: *parser.Node, page: *Page) ![]const u8 {
3737
var buf = std.ArrayList(u8).init(page.arena);
38-
if (try parser.nodeType(root) == .document) {
39-
try dump.writeHTML(@as(*parser.Document, @ptrCast(root)), buf.writer());
40-
} else {
41-
try dump.writeNode(root, buf.writer());
38+
switch (try parser.nodeType(root)) {
39+
.document => try dump.writeHTML(@as(*parser.Document, @ptrCast(root)), buf.writer()),
40+
.document_type => try dump.writeDocType(@as(*parser.DocumentType, @ptrCast(root)), buf.writer()),
41+
else => try dump.writeNode(root, buf.writer()),
4242
}
4343
return buf.items;
4444
}
@@ -54,3 +54,12 @@ test "Browser.XMLSerializer" {
5454
.{ "s.serializeToString(document.getElementById('para'))", "<p id=\"para\"> And</p>" },
5555
}, .{});
5656
}
57+
test "Browser.XMLSerializer with DOCTYPE" {
58+
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html = "<!DOCTYPE html><html><head></head><body></body></html>" });
59+
defer runner.deinit();
60+
61+
try runner.testCases(&.{
62+
.{ "new XMLSerializer().serializeToString(document.doctype)", "<!DOCTYPE html>" },
63+
}, .{});
64+
}
65+
test

0 commit comments

Comments
 (0)