From 612b3a26b7a5bb9ace4e668dc8f207b7f2905e4b Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 7 Jan 2026 14:34:35 +0300 Subject: [PATCH] allow other XML MIMEs in `parseFromString` --- src/browser/webapi/DOMParser.zig | 87 ++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/src/browser/webapi/DOMParser.zig b/src/browser/webapi/DOMParser.zig index 46ddd14b..453b83de 100644 --- a/src/browser/webapi/DOMParser.zig +++ b/src/browser/webapi/DOMParser.zig @@ -19,9 +19,13 @@ const std = @import("std"); const js = @import("../js/js.zig"); + const Page = @import("../Page.zig"); +const Parser = @import("../parser/Parser.zig"); + const HTMLDocument = @import("HTMLDocument.zig"); const XMLDocument = @import("XMLDocument.zig"); +const ProcessingInstruction = @import("../webapi/cdata/ProcessingInstruction.zig"); const DOMParser = @This(); @@ -40,46 +44,65 @@ pub fn parseFromString( mime_type: []const u8, page: *Page, ) !HTMLDocumentOrXMLDocument { - if (std.mem.eql(u8, mime_type, "text/html")) { - // Create a new HTMLDocument - const doc = try page._factory.document(HTMLDocument{ - ._proto = undefined, - }); + const maybe_target_mime = std.meta.stringToEnum(enum { + @"text/html", + @"text/xml", + @"application/xml", + @"application/xhtml+xml", + @"image/svg+xml", + }, mime_type); - var normalized = std.mem.trim(u8, html, &std.ascii.whitespace); - if (normalized.len == 0) { - normalized = ""; - } + if (maybe_target_mime) |target_mime| switch (target_mime) { + .@"text/html" => { + // Create a new HTMLDocument + const doc = try page._factory.document(HTMLDocument{ + ._proto = undefined, + }); - // Parse HTML into the document - const Parser = @import("../parser/Parser.zig"); - var parser = Parser.init(page.arena, doc.asNode(), page); - parser.parse(normalized); + var normalized = std.mem.trim(u8, html, &std.ascii.whitespace); + if (normalized.len == 0) { + normalized = ""; + } - if (parser.err) |pe| { - return pe.err; - } + // Parse HTML into the document + var parser = Parser.init(page.arena, doc.asNode(), page); + parser.parse(normalized); - return .{ .html_document = doc }; - } + if (parser.err) |pe| { + return pe.err; + } - if (std.mem.eql(u8, mime_type, "text/xml")) { - // Create a new XMLDocument. - const doc = try page._factory.document(XMLDocument{ - ._proto = undefined, - }); + return .{ .html_document = doc }; + }, + else => { + // Create a new XMLDocument. + const doc = try page._factory.document(XMLDocument{ + ._proto = undefined, + }); - // Parse XML into XMLDocument. - const Parser = @import("../parser/Parser.zig"); - var parser = Parser.init(page.arena, doc.asNode(), page); - parser.parseXML(html); + // Parse XML into XMLDocument. + const doc_node = doc.asNode(); + var parser = Parser.init(page.arena, doc_node, page); + parser.parseXML(html); - if (parser.err) |pe| { - return pe.err; - } + if (parser.err) |pe| { + return pe.err; + } - return .{ .xml_document = doc }; - } + // If first node is a `ProcessingInstruction`, skip it. + const first_child = doc_node.firstChild() orelse { + // Parsing should fail if there aren't any nodes. + unreachable; + }; + + if (first_child.getNodeType() == 7) { + // We're sure that firstChild exist, this cannot fail. + _ = doc_node.removeChild(first_child, page) catch unreachable; + } + + return .{ .xml_document = doc }; + }, + }; return error.NotSupported; }