webapi: implement the translate IDL attribute

Fixes 7 failing files under /html/dom/elements/global-attributes/
(the-translate-attribute-007 through -012 and
translate-enumerated-ascii-case-insensitive, 1 subtest each): the
HTMLElement.translate property was missing entirely.

The getter computes the element's translation mode per the HTML spec:
translate="yes" or "" enables it, "no" disables it (both ASCII
case-insensitively), anything else inherits from the closest ancestor
with a valid value, defaulting to enabled. The setter reflects back as
"yes"/"no".

Coverage: the 7 files above each 0/1 -> 1/1 (fully green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Francis Bouvier
2026-07-12 11:45:10 +02:00
committed by Karl Seguin
parent 5f8e910312
commit d5c57479a8

View File

@@ -345,6 +345,28 @@ pub fn setHidden(self: *HtmlElement, hidden: bool, frame: *Frame) !void {
}
}
// The translate IDL attribute reflects the element's translation mode:
// translate="yes"/"" enables it, "no" disables it, anything else (or no
// attribute) inherits from the parent, defaulting to enabled.
pub fn getTranslate(self: *HtmlElement) bool {
var node: ?*Node = self.asElement().asNode();
while (node) |n| : (node = n.parentNode()) {
const el = n.is(Element) orelse continue;
const value = el.getAttributeSafe(comptime .wrap("translate")) orelse continue;
if (value.len == 0 or std.ascii.eqlIgnoreCase(value, "yes")) {
return true;
}
if (std.ascii.eqlIgnoreCase(value, "no")) {
return false;
}
}
return true;
}
pub fn setTranslate(self: *HtmlElement, translate: bool, frame: *Frame) !void {
try self.asElement().setAttributeSafe(comptime .wrap("translate"), .wrap(if (translate) "yes" else "no"), frame);
}
pub fn getPopover(self: *HtmlElement) ?[]const u8 {
const s = popover.getState(self.asElement()) orelse return null;
return @tagName(s);
@@ -1707,6 +1729,7 @@ pub const JsApi = struct {
pub const autofocus = bridge.accessor(HtmlElement.getAutofocus, HtmlElement.setAutofocus, .{ .ce_reactions = true });
pub const dir = bridge.accessor(HtmlElement.getDir, HtmlElement.setDir, .{ .ce_reactions = true });
pub const hidden = bridge.accessor(HtmlElement.getHidden, HtmlElement.setHidden, .{ .ce_reactions = true });
pub const translate = bridge.accessor(HtmlElement.getTranslate, HtmlElement.setTranslate, .{ .ce_reactions = true });
pub const popover = bridge.accessor(HtmlElement.getPopover, HtmlElement.setPopover, .{ .ce_reactions = true });
pub const showPopover = bridge.function(HtmlElement.showPopover, .{});
pub const hidePopover = bridge.function(HtmlElement.hidePopover, .{});