diff --git a/src/browser/dom/document.zig b/src/browser/dom/document.zig index e3bf4f6b..db48497d 100644 --- a/src/browser/dom/document.zig +++ b/src/browser/dom/document.zig @@ -30,6 +30,9 @@ const css = @import("css.zig"); const Element = @import("element.zig").Element; const ElementUnion = @import("element.zig").Union; +const TreeWalker = @import("tree_walker.zig").TreeWalker; + +const Env = @import("../env.zig").Env; const DOMImplementation = @import("implementation.zig").DOMImplementation; @@ -238,6 +241,10 @@ pub const Document = struct { pub fn _replaceChildren(self: *parser.Document, nodes: []const Node.NodeOrText) !void { return Node.replaceChildren(parser.documentToNode(self), nodes); } + + pub fn _createTreeWalker(_: *parser.Document, root: *parser.Node, what_to_show: ?u32, filter: ?Env.Callback) TreeWalker { + return TreeWalker.init(root, what_to_show, filter); + } }; const testing = @import("../../testing.zig"); diff --git a/src/browser/dom/dom.zig b/src/browser/dom/dom.zig index 2cfb521d..b6029392 100644 --- a/src/browser/dom/dom.zig +++ b/src/browser/dom/dom.zig @@ -26,6 +26,7 @@ const Node = @import("node.zig"); const MutationObserver = @import("mutation_observer.zig"); const IntersectionObserver = @import("intersection_observer.zig"); const DOMParser = @import("dom_parser.zig").DOMParser; +const TreeWalker = @import("tree_walker.zig").TreeWalker; pub const Interfaces = .{ DOMException, @@ -39,4 +40,5 @@ pub const Interfaces = .{ MutationObserver.Interfaces, IntersectionObserver.Interfaces, DOMParser, + TreeWalker, }; diff --git a/src/browser/dom/tree_walker.zig b/src/browser/dom/tree_walker.zig new file mode 100644 index 00000000..f14164dc --- /dev/null +++ b/src/browser/dom/tree_walker.zig @@ -0,0 +1,94 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); +const parser = @import("../netsurf.zig"); + +const NodeFilter = @import("node_filter.zig").NodeFilter; +const Env = @import("../env.zig").Env; + +// https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker +pub const TreeWalker = struct { + root: *parser.Node, + current_node: *parser.Node, + what_to_show: u32, + filter: ?Env.Callback, + + pub fn init(node: *parser.Node, what_to_show: ?u32, filter: ?Env.Callback) TreeWalker { + return .{ + .root = node, + .current_node = node, + .what_to_show = what_to_show orelse NodeFilter._SHOW_ALL, + .filter = filter, + }; + } + + pub fn get_root(self: *TreeWalker) *parser.Node { + return self.root; + } + + pub fn get_currentNode(self: *TreeWalker) *parser.Node { + return self.current_node; + } + + pub fn get_whatToShow(self: *TreeWalker) u32 { + return self.what_to_show; + } + + pub fn get_filter(self: *TreeWalker) ?Env.Callback { + return self.filter; + } + + pub fn _firstChild(self: *TreeWalker) ?*parser.Node { + const first_child = parser.nodeFirstChild(self.current_node) catch return null; + self.current_node = first_child orelse return null; + return first_child; + } + + pub fn _lastChild(self: *TreeWalker) ?*parser.Node { + const last_child = parser.nodeLastChild(self.current_node) catch return null; + self.current_node = last_child orelse return null; + return last_child; + } + + pub fn _nextNode(self: *TreeWalker) ?*parser.Node { + return self._firstChild(); + } + + pub fn _nextSibling(self: *TreeWalker) ?*parser.Node { + const next_sibling = parser.nodeNextSibling(self.current_node) catch return null; + self.current_node = next_sibling orelse return null; + return next_sibling; + } + + pub fn _parentNode(self: *TreeWalker) ?*parser.Node { + const parent = parser.nodeParentNode(self.current_node) catch return null; + self.current_node = parent orelse return null; + return parent; + } + + pub fn _previousNode(self: *TreeWalker) ?*parser.Node { + return self._parentNode(); + } + + pub fn _previousSibling(self: *TreeWalker) ?*parser.Node { + const previous_sibling = parser.nodePreviousSibling(self.current_node) catch return null; + self.current_node = previous_sibling orelse return null; + return previous_sibling; + } +};