SemanticTree: improve accessibility tree and name calculation

- Add more structural roles (banner, navigation, main, list, etc.).
- Implement fallback for accessible names (SVG titles, image alt text).
- Skip children for leaf-like semantic nodes to reduce redundancy.
- Disable pruning in the default semantic tree view.
This commit is contained in:
Adrià Arrufat
2026-03-09 21:04:47 +09:00
parent 61cba3f6eb
commit 85ebbe8759
3 changed files with 62 additions and 7 deletions

View File

@@ -888,10 +888,12 @@ fn writeName(axnode: AXNode, w: anytype, page: *Page) !?AXSource {
=> {},
else => {
// write text content if exists.
var buf = std.Io.Writer.Allocating.init(page.call_arena);
try el.getInnerText(&buf.writer);
try writeString(buf.written(), w);
return .contents;
var buf: std.Io.Writer.Allocating = .init(page.call_arena);
try writeAccessibleNameFallback(node, &buf.writer, page);
if (buf.written().len > 0) {
try writeString(buf.written(), w);
return .contents;
}
},
}
@@ -915,6 +917,40 @@ fn writeName(axnode: AXNode, w: anytype, page: *Page) !?AXSource {
};
}
fn writeAccessibleNameFallback(node: *DOMNode, writer: *std.Io.Writer, page: *Page) !void {
var it = node.childrenIterator();
while (it.next()) |child| {
switch (child._type) {
.cdata => |cd| switch (cd._type) {
.text => |*text| try writer.writeAll(text.getWholeText()),
else => {},
},
.element => |el| {
if (el.getTag() == .img) {
if (el.getAttributeSafe(.wrap("alt"))) |alt| {
try writer.writeAll(alt);
try writer.writeByte(' ');
}
} else if (el.getTag() == .svg) {
// Try to find a <title> inside SVG
var sit = child.childrenIterator();
while (sit.next()) |s_child| {
if (s_child.is(DOMNode.Element)) |s_el| {
if (std.mem.eql(u8, s_el.getTagNameLower(), "title")) {
try writeAccessibleNameFallback(s_child, writer, page);
try writer.writeByte(' ');
}
}
}
} else {
try writeAccessibleNameFallback(child, writer, page);
}
},
else => {},
}
}
}
fn isHidden(elt: *DOMNode.Element) bool {
if (elt.getAttributeSafe(comptime .wrap("aria-hidden"))) |value| {
if (std.mem.eql(u8, value, "true")) {