mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-14 15:28:57 +00:00
DOMParser
This commit is contained in:
@@ -489,6 +489,7 @@ pub const JsApis = flattenTypes(&.{
|
||||
@import("../webapi/DOMTreeWalker.zig"),
|
||||
@import("../webapi/DOMNodeIterator.zig"),
|
||||
@import("../webapi/DOMRect.zig"),
|
||||
@import("../webapi/DOMParser.zig"),
|
||||
@import("../webapi/NodeFilter.zig"),
|
||||
@import("../webapi/Element.zig"),
|
||||
@import("../webapi/element/DOMStringMap.zig"),
|
||||
|
||||
121
src/browser/tests/domparser.html
Normal file
121
src/browser/tests/domparser.html
Normal file
@@ -0,0 +1,121 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="testing.js"></script>
|
||||
|
||||
<!-- <script id=basic>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
testing.expectEqual('object', typeof parser);
|
||||
testing.expectEqual('function', typeof parser.parseFromString);
|
||||
}
|
||||
</script> -->
|
||||
|
||||
<script id=parseSimpleHTML>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('<div>Hello World</div>', 'text/html');
|
||||
|
||||
testing.expectEqual('object', typeof doc);
|
||||
testing.expectEqual('[object HTMLDocument]', doc.toString());
|
||||
|
||||
const div = doc.querySelector('div');
|
||||
testing.expectEqual('DIV', div.tagName);
|
||||
testing.expectEqual('Hello World', div.textContent);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- <script id=parseWithAttributes>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('<div id="test" class="foo">Content</div>', 'text/html');
|
||||
|
||||
const div = doc.querySelector('div');
|
||||
testing.expectEqual('test', div.id);
|
||||
testing.expectEqual('foo', div.className);
|
||||
testing.expectEqual('Content', div.textContent);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=parseMultipleElements>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('<div>First</div><span>Second</span>', 'text/html');
|
||||
|
||||
const div = doc.querySelector('div');
|
||||
const span = doc.querySelector('span');
|
||||
|
||||
testing.expectEqual('DIV', div.tagName);
|
||||
testing.expectEqual('First', div.textContent);
|
||||
testing.expectEqual('SPAN', span.tagName);
|
||||
testing.expectEqual('Second', span.textContent);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=parseNestedElements>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('<div><p><span>Nested</span></p></div>', 'text/html');
|
||||
|
||||
const div = doc.querySelector('div');
|
||||
const p = doc.querySelector('p');
|
||||
const span = doc.querySelector('span');
|
||||
|
||||
testing.expectEqual('DIV', div.tagName);
|
||||
testing.expectEqual('P', p.tagName);
|
||||
testing.expectEqual('SPAN', span.tagName);
|
||||
testing.expectEqual('Nested', span.textContent);
|
||||
testing.expectEqual(p, div.firstChild);
|
||||
testing.expectEqual(span, p.firstChild);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=parseEmptyString>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('', 'text/html');
|
||||
|
||||
testing.expectEqual('object', typeof doc);
|
||||
testing.expectEqual('[object HTMLDocument]', doc.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=parsedDocumentIsIndependent>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString('<div id="parsed">Parsed</div>', 'text/html');
|
||||
|
||||
// The parsed document should be independent from the current document
|
||||
const currentDiv = document.querySelector('div');
|
||||
const parsedDiv = doc.querySelector('div');
|
||||
|
||||
testing.expectEqual(null, currentDiv);
|
||||
testing.expectEqual('parsed', parsedDiv.id);
|
||||
testing.expectEqual('Parsed', parsedDiv.textContent);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=malformedHTMLDoesNotThrow>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
|
||||
// HTML parsers should be forgiving and not throw on malformed HTML
|
||||
const doc1 = parser.parseFromString('<div><p>unclosed', 'text/html');
|
||||
testing.expectEqual('object', typeof doc1);
|
||||
|
||||
const doc2 = parser.parseFromString('<<<invalid>>>', 'text/html');
|
||||
testing.expectEqual('object', typeof doc2);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=unsupportedMimeType>
|
||||
{
|
||||
const parser = new DOMParser();
|
||||
|
||||
// Should throw an error for unsupported MIME types
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual('NotSupported', err.message);
|
||||
}, () => {
|
||||
parser.parseFromString('<div>test</div>', 'application/xml');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
-->
|
||||
57
src/browser/webapi/DOMParser.zig
Normal file
57
src/browser/webapi/DOMParser.zig
Normal file
@@ -0,0 +1,57 @@
|
||||
const std = @import("std");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
const Document = @import("Document.zig");
|
||||
const HTMLDocument = @import("HTMLDocument.zig");
|
||||
|
||||
const DOMParser = @This();
|
||||
// @ZIGDOM support empty structs
|
||||
_: u8 = 0,
|
||||
|
||||
pub fn init() DOMParser {
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn parseFromString(self: *const DOMParser, html: []const u8, mime_type: []const u8, page: *Page) !*HTMLDocument {
|
||||
_ = self;
|
||||
|
||||
// For now, only support text/html
|
||||
if (!std.mem.eql(u8, mime_type, "text/html")) {
|
||||
return error.NotSupported;
|
||||
}
|
||||
|
||||
// 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(html);
|
||||
|
||||
if (parser.err) |pe| {
|
||||
return pe.err;
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(DOMParser);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "DOMParser";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(DOMParser.init, .{});
|
||||
pub const parseFromString = bridge.function(DOMParser.parseFromString, .{});
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "WebApi: DOMParser" {
|
||||
try testing.htmlRunner("domparser.html", .{});
|
||||
}
|
||||
@@ -122,8 +122,11 @@ pub fn querySelectorAll(self: *Document, input: []const u8, page: *Page) !*Selec
|
||||
return Selector.querySelectorAll(self.asNode(), input, page);
|
||||
}
|
||||
|
||||
pub fn className(_: *const Document) []const u8 {
|
||||
return "[object Document]";
|
||||
pub fn className(self: *const Document) []const u8 {
|
||||
return switch (self._type) {
|
||||
.generic => "[object Document]",
|
||||
.html => "[object HTMLDocument]",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getImplementation(_: *const Document) DOMImplementation {
|
||||
|
||||
Reference in New Issue
Block a user