From 926bd20281b848fbfd08ca241d6cfcc7e7c28a3c Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 9 Feb 2026 15:38:41 +0800 Subject: [PATCH] Add HTMLPictureElement Fix tag mapping for various types (including Source, which is Picture related). --- src/browser/Page.zig | 6 ++ src/browser/js/bridge.zig | 1 + src/browser/tests/element/html/picture.html | 55 +++++++++++++++++++ src/browser/webapi/Element.zig | 32 +++++++---- .../webapi/css/CSSStyleDeclaration.zig | 2 +- src/browser/webapi/element/Html.zig | 2 + src/browser/webapi/element/html/Picture.zig | 30 ++++++++++ src/main_legacy_test.zig | 2 + 8 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 src/browser/tests/element/html/picture.html create mode 100644 src/browser/webapi/element/html/Picture.zig diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 29deac0e..13dfb903 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -2095,6 +2095,12 @@ pub fn createElementNS(self: *Page, namespace: Element.Namespace, name: []const attribute_iterator, .{ ._proto = undefined, ._tag_name = String.init(undefined, "address", .{}) catch unreachable, ._tag = .address }, ), + asUint("picture") => return self.createHtmlElementT( + Element.Html.Picture, + namespace, + attribute_iterator, + .{ ._proto = undefined }, + ), else => {}, }, 8 => switch (@as(u64, @bitCast(name[0..8].*))) { diff --git a/src/browser/js/bridge.zig b/src/browser/js/bridge.zig index 3901d172..5bedc1fb 100644 --- a/src/browser/js/bridge.zig +++ b/src/browser/js/bridge.zig @@ -811,6 +811,7 @@ pub const JsApis = flattenTypes(&.{ @import("../webapi/element/html/Option.zig"), @import("../webapi/element/html/Output.zig"), @import("../webapi/element/html/Paragraph.zig"), + @import("../webapi/element/html/Picture.zig"), @import("../webapi/element/html/Param.zig"), @import("../webapi/element/html/Pre.zig"), @import("../webapi/element/html/Progress.zig"), diff --git a/src/browser/tests/element/html/picture.html b/src/browser/tests/element/html/picture.html new file mode 100644 index 00000000..67dade43 --- /dev/null +++ b/src/browser/tests/element/html/picture.html @@ -0,0 +1,55 @@ + + + + + + + + + Test image + + + + + diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index fe165eaf..71a24a74 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -235,6 +235,7 @@ pub fn getTagNameLower(self: *const Element) []const u8 { .option => "option", .output => "output", .p => "p", + .picture => "picture", .param => "param", .pre => "pre", .progress => "progress", @@ -311,6 +312,7 @@ pub fn getTagNameSpec(self: *const Element, buf: []u8) []const u8 { .option => "OPTION", .output => "OUTPUT", .p => "P", + .picture => "PICTURE", .param => "PARAM", .pre => "PRE", .progress => "PROGRESS", @@ -1221,26 +1223,27 @@ pub fn getTag(self: *const Element) Tag { .data => .data, .datalist => .datalist, .dialog => .dialog, - .directory => .unknown, + .directory => .directory, .iframe => .iframe, .img => .img, .br => .br, .button => .button, .canvas => .canvas, .fieldset => .fieldset, - .font => .unknown, + .font => .font, .heading => |h| h._tag, - .label => .unknown, - .legend => .unknown, + .label => .label, + .legend => .legend, .li => .li, - .map => .unknown, + .map => .map, .ul => .ul, .ol => .ol, - .object => .unknown, + .object => .object, .optgroup => .optgroup, - .output => .unknown, - .param => .unknown, - .pre => .unknown, + .output => .output, + .picture => .picture, + .param => .param, + .pre => .pre, .generic => |g| g._tag, .media => |m| switch (m._type) { .audio => .audio, @@ -1254,7 +1257,7 @@ pub fn getTag(self: *const Element) Tag { .script => .script, .select => .select, .slot => .slot, - .source => .unknown, + .source => .source, .span => .span, .option => .option, .table => .table, @@ -1266,7 +1269,7 @@ pub fn getTag(self: *const Element) Tag { .template => .template, .textarea => .textarea, .time => .time, - .track => .unknown, + .track => .track, .input => .input, .link => .link, .meta => .meta, @@ -1313,6 +1316,7 @@ pub const Tag = enum { dfn, dialog, div, + directory, dl, dt, embed, @@ -1321,6 +1325,7 @@ pub const Tag = enum { fieldset, figure, form, + font, footer, g, h1, @@ -1340,10 +1345,13 @@ pub const Tag = enum { img, input, ins, + label, + legend, li, line, link, main, + map, marquee, media, menu, @@ -1359,8 +1367,10 @@ pub const Tag = enum { p, path, param, + picture, polygon, polyline, + pre, progress, quote, rect, diff --git a/src/browser/webapi/css/CSSStyleDeclaration.zig b/src/browser/webapi/css/CSSStyleDeclaration.zig index d50aed32..fd6217eb 100644 --- a/src/browser/webapi/css/CSSStyleDeclaration.zig +++ b/src/browser/webapi/css/CSSStyleDeclaration.zig @@ -218,7 +218,7 @@ fn getDefaultDisplay(element: *const Element) []const u8 { .html => |html| { return switch (html._type) { .anchor, .br, .span, .label, .time, .font, .mod, .quote => "inline", - .body, .div, .p, .heading, .form, .button, .canvas, .dialog, .embed, .head, .html, .hr, .iframe, .img, .input, .li, .link, .meta, .ol, .option, .script, .select, .slot, .style, .template, .textarea, .title, .ul, .media, .area, .base, .datalist, .directory, .fieldset, .legend, .map, .meter, .object, .optgroup, .output, .param, .pre, .progress, .source, .table, .table_caption, .table_cell, .table_col, .table_row, .table_section, .track => "block", + .body, .div, .p, .heading, .form, .button, .canvas, .dialog, .embed, .head, .html, .hr, .iframe, .img, .input, .li, .link, .meta, .ol, .option, .script, .select, .slot, .style, .template, .textarea, .title, .ul, .media, .area, .base, .datalist, .directory, .fieldset, .legend, .map, .meter, .object, .optgroup, .output, .param, .picture, .pre, .progress, .source, .table, .table_caption, .table_cell, .table_col, .table_row, .table_section, .track => "block", .generic, .custom, .unknown, .data => blk: { const tag = element.getTagNameLower(); if (isInlineTag(tag)) break :blk "inline"; diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index cc20622a..bbb8a050 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -69,6 +69,7 @@ pub const OptGroup = @import("html/OptGroup.zig"); pub const Option = @import("html/Option.zig"); pub const Output = @import("html/Output.zig"); pub const Paragraph = @import("html/Paragraph.zig"); +pub const Picture = @import("html/Picture.zig"); pub const Param = @import("html/Param.zig"); pub const Pre = @import("html/Pre.zig"); pub const Progress = @import("html/Progress.zig"); @@ -145,6 +146,7 @@ pub const Type = union(enum) { option: *Option, output: *Output, p: *Paragraph, + picture: *Picture, param: *Param, pre: *Pre, progress: *Progress, diff --git a/src/browser/webapi/element/html/Picture.zig b/src/browser/webapi/element/html/Picture.zig new file mode 100644 index 00000000..ddc7039c --- /dev/null +++ b/src/browser/webapi/element/html/Picture.zig @@ -0,0 +1,30 @@ +const js = @import("../../../js/js.zig"); +const Node = @import("../../Node.zig"); +const Element = @import("../../Element.zig"); +const HtmlElement = @import("../Html.zig"); + +const Picture = @This(); + +_proto: *HtmlElement, + +pub fn asElement(self: *Picture) *Element { + return self._proto._proto; +} +pub fn asNode(self: *Picture) *Node { + return self.asElement().asNode(); +} + +pub const JsApi = struct { + pub const bridge = js.Bridge(Picture); + + pub const Meta = struct { + pub const name = "HTMLPictureElement"; + pub const prototype_chain = bridge.prototypeChain(); + pub var class_id: bridge.ClassId = undefined; + }; +}; + +const testing = @import("../../../../testing.zig"); +test "WebApi: Picture" { + try testing.htmlRunner("element/html/picture.html", .{}); +} diff --git a/src/main_legacy_test.zig b/src/main_legacy_test.zig index bc59492a..35332863 100644 --- a/src/main_legacy_test.zig +++ b/src/main_legacy_test.zig @@ -38,6 +38,8 @@ pub fn main() !void { .user_agent_suffix = "internal-tester", }, } }); + defer config.deinit(allocator); + var app = try lp.App.init(allocator, &config); defer app.deinit();