mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
dom: implement innerHTML setter
This commit is contained in:
@@ -89,6 +89,28 @@ pub const Element = struct {
|
||||
return buf.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn set_innerHTML(self: *parser.Element, str: []const u8) !void {
|
||||
const node = parser.elementToNode(self);
|
||||
const doc = try parser.nodeOwnerDocument(node) orelse return parser.DOMError.WrongDocument;
|
||||
// parse the fragment
|
||||
const fragment = try parser.documentParseFragmentFromStr(doc, str);
|
||||
|
||||
// remove existing children
|
||||
try Node.removeChildren(node);
|
||||
|
||||
// get fragment body children
|
||||
const children = try parser.documentFragmentBodyChildren(fragment) orelse return;
|
||||
|
||||
// append children to the node
|
||||
const ln = try parser.nodeListLength(children);
|
||||
var i: u32 = 0;
|
||||
while (i < ln) {
|
||||
defer i += 1;
|
||||
const child = try parser.nodeListItem(children, i) orelse continue;
|
||||
_ = try parser.nodeAppendChild(node, child);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _hasAttributes(self: *parser.Element) !bool {
|
||||
return try parser.nodeHasAttributes(parser.elementToNode(self));
|
||||
}
|
||||
@@ -435,6 +457,11 @@ pub fn testExecFn(
|
||||
var innerHTML = [_]Case{
|
||||
.{ .src = "document.getElementById('para').innerHTML", .ex = " And" },
|
||||
.{ .src = "document.getElementById('para-empty').innerHTML.trim()", .ex = "<span id=\"para-empty-child\"></span>" },
|
||||
|
||||
.{ .src = "let h = document.getElementById('para-empty')", .ex = "undefined" },
|
||||
.{ .src = "const prev = h.innerHTML", .ex = "undefined" },
|
||||
.{ .src = "h.innerHTML = prev; true", .ex = "true" },
|
||||
.{ .src = "document.getElementById('para-empty').innerHTML.trim()", .ex = "<span id=\"para-empty-child\"></span>" },
|
||||
};
|
||||
try checkCases(js_env, &innerHTML);
|
||||
}
|
||||
|
||||
@@ -1514,6 +1514,22 @@ pub const Video = struct { base: *c.dom_html_element };
|
||||
// Document Fragment
|
||||
pub const DocumentFragment = c.dom_document_fragment;
|
||||
|
||||
pub inline fn documentFragmentToNode(doc: *DocumentFragment) *Node {
|
||||
return @as(*Node, @ptrCast(doc));
|
||||
}
|
||||
|
||||
pub fn documentFragmentBodyChildren(doc: *DocumentFragment) !?*NodeList {
|
||||
const node = documentFragmentToNode(doc);
|
||||
const html = try nodeFirstChild(node) orelse return null;
|
||||
// TODO unref
|
||||
const head = try nodeFirstChild(html) orelse return null;
|
||||
// TODO unref
|
||||
const body = try nodeNextSibling(head) orelse return null;
|
||||
// TODO unref
|
||||
|
||||
return try nodeGetChildNodes(body);
|
||||
}
|
||||
|
||||
// Document Position
|
||||
|
||||
pub const DocumentPosition = enum(u2) {
|
||||
@@ -1859,6 +1875,53 @@ pub fn documentHTMLParse(reader: anytype, enc: ?[:0]const u8) !*DocumentHTML {
|
||||
return @as(*DocumentHTML, @ptrCast(doc.?));
|
||||
}
|
||||
|
||||
pub fn documentParseFragmentFromStr(self: *Document, str: []const u8) !*DocumentFragment {
|
||||
var fbs = std.io.fixedBufferStream(str);
|
||||
return try documentParseFragment(self, fbs.reader(), "UTF-8");
|
||||
}
|
||||
|
||||
pub fn documentParseFragment(self: *Document, reader: anytype, enc: ?[:0]const u8) !*DocumentFragment {
|
||||
var parser: ?*c.dom_hubbub_parser = undefined;
|
||||
var fragment: ?*c.dom_document_fragment = undefined;
|
||||
var err: c.hubbub_error = undefined;
|
||||
|
||||
var params = c.dom_hubbub_parser_params{
|
||||
.enc = null,
|
||||
.fix_enc = true,
|
||||
.msg = null,
|
||||
.script = null,
|
||||
.enable_script = false,
|
||||
.ctx = null,
|
||||
.daf = null,
|
||||
};
|
||||
|
||||
if (enc) |e| params.enc = e;
|
||||
|
||||
err = c.dom_hubbub_fragment_parser_create(¶ms, self, &parser, &fragment);
|
||||
try parserErr(err);
|
||||
defer c.dom_hubbub_parser_destroy(parser);
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var ln = buffer.len;
|
||||
while (ln > 0) {
|
||||
ln = try reader.read(&buffer);
|
||||
err = c.dom_hubbub_parser_parse_chunk(parser, &buffer, ln);
|
||||
// TODO handle encoding change error return.
|
||||
// When the HTML contains a META tag with a different encoding than the
|
||||
// original one, a c.DOM_HUBBUB_HUBBUB_ERR_ENCODINGCHANGE error is
|
||||
// returned.
|
||||
// In this case, we must restart the parsing with the new detected
|
||||
// encoding. The detected encoding is stored in the document and we can
|
||||
// get it with documentGetInputEncoding().
|
||||
try parserErr(err);
|
||||
}
|
||||
|
||||
err = c.dom_hubbub_parser_completed(parser);
|
||||
try parserErr(err);
|
||||
|
||||
return @as(*DocumentFragment, @ptrCast(fragment.?));
|
||||
}
|
||||
|
||||
// documentHTMLClose closes the document.
|
||||
pub fn documentHTMLClose(doc: *DocumentHTML) !void {
|
||||
const err = documentHTMLVtable(doc).close.?(doc);
|
||||
|
||||
Reference in New Issue
Block a user