diff --git a/src/browser/StyleManager.zig b/src/browser/StyleManager.zig index d3f529d9c..a5ed6f4e7 100644 --- a/src/browser/StyleManager.zig +++ b/src/browser/StyleManager.zig @@ -1303,12 +1303,6 @@ fn foldDeclarations(block: []const u8, customs: ?*CustomSink) !TrackedProperties return slots.props(); } -// The ` []` shorthands the cascade expands into the tracked longhands. -const axis_shorthands = [_]struct { name: []const u8, x: []const u8, y: []const u8 }{ - .{ .name = "overflow", .x = "overflow-x", .y = "overflow-y" }, - .{ .name = "overscroll-behavior", .x = "overscroll-behavior-x", .y = "overscroll-behavior-y" }, -}; - /// One block's winning value per tracked property, folded in declaration /// order. const Slots = struct { @@ -1332,13 +1326,11 @@ const Slots = struct { slots: [property_names.len]Slot = @splat(.{}), fn apply(self: *Slots, name: []const u8, value: []const u8, important: bool) void { - for (axis_shorthands) |shorthand| { - if (std.ascii.eqlIgnoreCase(name, shorthand.name)) { - const values = CssParser.splitAxisPair(value) orelse return; - self.apply(shorthand.x, values.x, important); - self.apply(shorthand.y, values.y, important); - return; - } + if (CssParser.axisShorthand(name)) |shorthand| { + const values = CssParser.splitAxisPair(value) orelse return; + self.apply(shorthand.x, values.x, important); + self.apply(shorthand.y, values.y, important); + return; } for (property_names, &self.slots) |tracked, *slot| { if (std.ascii.eqlIgnoreCase(name, tracked)) { diff --git a/src/browser/css/Parser.zig b/src/browser/css/Parser.zig index 8cda3dcc2..5e7f5c12e 100644 --- a/src/browser/css/Parser.zig +++ b/src/browser/css/Parser.zig @@ -27,6 +27,53 @@ pub const Declaration = struct { pub const AxisPair = struct { x: []const u8, y: []const u8 }; +pub const AxisShorthand = struct { + name: []const u8, + x: []const u8, + y: []const u8, +}; + +// The ` []` shorthands whose longhands the style cascade tracks. Both the +// CSSOM object and the cascade store these expanded: setting one sets both +// longhands, reading or serializing it recombines them. +pub const axis_shorthands = [_]AxisShorthand{ + .{ .name = "overflow", .x = "overflow-x", .y = "overflow-y" }, + .{ .name = "overscroll-behavior", .x = "overscroll-behavior-x", .y = "overscroll-behavior-y" }, +}; + +/// The axis shorthand `name` names, if it names one. +pub fn axisShorthand(name: []const u8) ?AxisShorthand { + for (axis_shorthands) |shorthand| { + if (std.ascii.eqlIgnoreCase(name, shorthand.name)) { + return shorthand; + } + } + return null; +} + +pub const AxisLonghand = struct { + shorthand: AxisShorthand, + is_x: bool, + + /// The longhand on the other axis. + pub fn partner(self: AxisLonghand) []const u8 { + return if (self.is_x) self.shorthand.y else self.shorthand.x; + } +}; + +/// The axis shorthand `name` is a longhand of, if it is one. +pub fn axisLonghand(name: []const u8) ?AxisLonghand { + for (axis_shorthands) |shorthand| { + if (std.ascii.eqlIgnoreCase(name, shorthand.x)) { + return .{ .shorthand = shorthand, .is_x = true }; + } + if (std.ascii.eqlIgnoreCase(name, shorthand.y)) { + return .{ .shorthand = shorthand, .is_x = false }; + } + } + return null; +} + /// An ` []` axis shorthand such as `overflow` or `overscroll-behavior`; /// a single value applies to both axes. More than two values is invalid and /// null, as is an empty declaration. diff --git a/src/browser/tests/element/styles.html b/src/browser/tests/element/styles.html index 043c3c02c..1c30d525d 100644 --- a/src/browser/tests/element/styles.html +++ b/src/browser/tests/element/styles.html @@ -113,6 +113,25 @@ } + +