Merge pull request #1308 from lightpanda-io/axtree-backport

cdp: add AXTree
This commit is contained in:
Pierre Tachoire
2026-01-16 17:56:40 +01:00
committed by GitHub
6 changed files with 1208 additions and 3 deletions

View File

@@ -1367,7 +1367,7 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const
Element.Html.Quote,
namespace,
attribute_iterator,
.{ ._proto = undefined, ._tag_name = String.init(undefined, "q", .{}) catch unreachable, ._tag = .unknown },
.{ ._proto = undefined, ._tag_name = String.init(undefined, "q", .{}) catch unreachable, ._tag = .quote },
),
's' => return self.createHtmlElementT(
Element.Html.Generic,
@@ -1523,7 +1523,7 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const
Element.Html.TableCol,
namespace,
attribute_iterator,
.{ ._proto = undefined, ._tag_name = String.init(undefined, "col", .{}) catch unreachable, ._tag = .unknown },
.{ ._proto = undefined, ._tag_name = String.init(undefined, "col", .{}) catch unreachable, ._tag = .col },
),
asUint("dir") => return self.createHtmlElementT(
Element.Html.Directory,
@@ -1926,7 +1926,7 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const
Element.Html.TableCol,
namespace,
attribute_iterator,
.{ ._proto = undefined, ._tag_name = String.init(undefined, "colgroup", .{}) catch unreachable, ._tag = .unknown },
.{ ._proto = undefined, ._tag_name = String.init(undefined, "colgroup", .{}) catch unreachable, ._tag = .colgroup },
),
asUint("fieldset") => return self.createHtmlElementT(
Element.Html.FieldSet,
@@ -1952,6 +1952,12 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const
attribute_iterator,
.{ ._proto = undefined },
),
asUint("noscript") => return self.createHtmlElementT(
Element.Html.Generic,
namespace,
attribute_iterator,
.{ ._proto = undefined, ._tag_name = String.init(undefined, "noscript", .{}) catch unreachable, ._tag = .noscript },
),
else => {},
},
10 => switch (@as(u80, @bitCast(name[0..10].*))) {

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<h1>Test Page</h1>
<nav>
<a href="/page1" id="link1">First Link</a>
<a href="/page2" id="link2">Second Link</a>
</nav>
<form id="testForm" action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" placeholder="Enter username">
<label for="email">Email:</label>
<input type="email" id="email" name="email" placeholder="Enter email">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
<button type="submit">Submit</button>
</form>
</body>
</html>

View File

@@ -1219,6 +1219,8 @@ pub const Tag = enum {
caption,
circle,
code,
col,
colgroup,
custom,
data,
datalist,
@@ -1265,20 +1267,26 @@ pub const Tag = enum {
meta,
meter,
nav,
noscript,
object,
ol,
optgroup,
option,
output,
p,
path,
param,
polygon,
polyline,
progress,
quote,
rect,
s,
script,
section,
select,
slot,
source,
span,
strong,
style,
@@ -1298,6 +1306,7 @@ pub const Tag = enum {
thead,
title,
tr,
track,
ul,
video,
unknown,

1130
src/cdp/AXNode.zig Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -289,6 +289,7 @@ pub fn CDPT(comptime TypeProvider: type) type {
pub fn BrowserContext(comptime CDP_T: type) type {
const Node = @import("Node.zig");
const AXNode = @import("AXNode.zig");
return struct {
id: []const u8,
@@ -465,6 +466,16 @@ pub fn BrowserContext(comptime CDP_T: type) type {
};
}
pub fn axnodeWriter(self: *Self, root: *const Node, opts: AXNode.Writer.Opts) !AXNode.Writer {
const page = self.session.currentPage() orelse return error.PageNotLoaded;
_ = opts;
return .{
.page = page,
.root = root,
.registry = &self.node_registry,
};
}
pub fn getURL(self: *const Self) ?[:0]const u8 {
const page = self.session.currentPage() orelse return null;
const url = page.url;

View File

@@ -22,11 +22,13 @@ pub fn processMessage(cmd: anytype) !void {
const action = std.meta.stringToEnum(enum {
enable,
disable,
getFullAXTree,
}, cmd.input.action) orelse return error.UnknownMethod;
switch (action) {
.enable => return enable(cmd),
.disable => return disable(cmd),
.getFullAXTree => return getFullAXTree(cmd),
}
}
fn enable(cmd: anytype) !void {
@@ -36,3 +38,25 @@ fn enable(cmd: anytype) !void {
fn disable(cmd: anytype) !void {
return cmd.sendResult(null, .{});
}
fn getFullAXTree(cmd: anytype) !void {
const params = (try cmd.params(struct {
depth: ?i32 = null,
frameId: ?[]const u8 = null,
})) orelse return error.InvalidParams;
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
if (params.frameId) |frameId| {
const target_id = bc.target_id orelse return error.TargetNotLoaded;
if (std.mem.eql(u8, target_id, frameId) == false) {
return cmd.sendError(-32000, "Frame with the given id does not belong to the target.", .{});
}
}
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
const doc = page.window._document.asNode();
const node = try bc.node_registry.register(doc);
return cmd.sendResult(.{ .nodes = try bc.axnodeWriter(node, .{}) }, .{});
}