Files
bun.sh/src/css/properties/align.zig
pfg 97c113d010 remove unused writer type parameters in src/css/ (#24571)
No longer needed after zig upgrade

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-11-11 21:09:50 -08:00

1517 lines
58 KiB
Zig

pub const css = @import("../css_parser.zig");
const Printer = css.Printer;
const PrintErr = css.PrintErr;
const LengthPercentage = css.css_values.length.LengthPercentage;
const VendorPrefix = css.VendorPrefix;
const Property = css.Property;
const Feature = css.prefixes.Feature;
/// A value for the [align-content](https://www.w3.org/TR/css-align-3/#propdef-align-content) property.
pub const AlignContent = union(enum) {
/// Default alignment.
normal: void,
/// A baseline position.
baseline_position: BaselinePosition,
/// A content distribution keyword.
content_distribution: ContentDistribution,
/// A content position keyword.
content_position: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
/// A content position keyword.
value: ContentPosition,
pub fn toInner(this: *const @This()) ContentPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn __generateToCss() void {}
pub fn parse(input: *css.Parser) css.Result(@This()) {
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
const value = switch (ContentPosition.parse(input)) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
return .{ .result = .{ .overflow = overflow, .value = value } };
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
pub const parse = css.DeriveParse(@This()).parse;
pub const toCss = css.DeriveToCss(@This()).toCss;
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A [`<baseline-position>`](https://www.w3.org/TR/css-align-3/#typedef-baseline-position) value,
/// as used in the alignment properties.
pub const BaselinePosition = enum {
/// The first baseline.
first,
/// The last baseline.
last,
pub fn parse(input: *css.Parser) css.Result(@This()) {
const location = input.currentSourceLocation();
const ident = switch (input.expectIdent()) {
.err => |e| return .{ .err = e },
.result => |v| v,
};
const BaselinePositionIdent = enum {
baseline,
first,
last,
};
const BaselinePositionMap = bun.ComptimeEnumMap(BaselinePositionIdent);
if (BaselinePositionMap.getASCIIICaseInsensitive(ident)) |value|
switch (value) {
.baseline => return .{ .result = BaselinePosition.first },
.first => {
if (input.expectIdentMatching("baseline").asErr()) |e| return .{ .err = e };
return .{ .result = BaselinePosition.first };
},
.last => {
if (input.expectIdentMatching("baseline").asErr()) |e| return .{ .err = e };
return .{ .result = BaselinePosition.last };
},
}
else
return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) };
}
pub fn toCss(this: *const BaselinePosition, dest: *css.Printer) css.PrintErr!void {
return switch (this.*) {
.first => try dest.writeStr("baseline"),
.last => try dest.writeStr("last baseline"),
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [justify-content](https://www.w3.org/TR/css-align-3/#propdef-justify-content) property.
pub const JustifyContent = union(enum) {
/// Default justification.
normal,
/// A content distribution keyword.
content_distribution: ContentDistribution,
/// A content position keyword.
content_position: struct {
/// A content position keyword.
value: ContentPosition,
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn toInner(this: *const @This()) ContentPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Justify to the left.
left: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Justify to the right.
right: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
pub fn parse(input: *css.Parser) css.Result(@This()) {
if (input.tryParse(css.Parser.expectIdentMatching, .{"normal"}).isOk()) {
return .{ .result = .normal };
}
if (input.tryParse(ContentDistribution.parse, .{}).asValue()) |val| {
return .{ .result = .{ .content_distribution = val } };
}
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
if (input.tryParse(ContentPosition.parse, .{}).asValue()) |content_position| {
return .{ .result = .{
.content_position = .{
.overflow = overflow,
.value = content_position,
},
} };
}
const location = input.currentSourceLocation();
const ident = switch (input.expectIdent()) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const JustifyContentIdent = enum {
left,
right,
};
const JustifyContentIdentMap = bun.ComptimeEnumMap(JustifyContentIdent);
if (JustifyContentIdentMap.getASCIIICaseInsensitive(ident)) |value|
return switch (value) {
.left => .{ .result = .{ .left = .{ .overflow = overflow } } },
.right => .{ .result = .{ .right = .{ .overflow = overflow } } },
}
else
return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) };
}
pub fn toCss(this: *const @This(), dest: *css.Printer) css.PrintErr!void {
return switch (this.*) {
.normal => dest.writeStr("normal"),
.content_distribution => |value| value.toCss(dest),
.content_position => |*cp| {
if (cp.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
return cp.value.toCss(dest);
},
.left => |*l| {
if (l.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
return dest.writeStr("left");
},
.right => |*r| {
if (r.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
return dest.writeStr("right");
},
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [align-self](https://www.w3.org/TR/css-align-3/#align-self-property) property.
pub const AlignSelf = union(enum) {
/// Automatic alignment.
auto,
/// Default alignment.
normal,
/// Item is stretched.
stretch,
/// A baseline position keyword.
baseline_position: BaselinePosition,
/// A self position keyword.
self_position: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
/// A self position keyword.
value: SelfPosition,
pub fn toInner(this: *const @This()) SelfPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn __generateToCss() void {}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn parse(input: *css.Parser) css.Result(@This()) {
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
const self_position = switch (SelfPosition.parse(input)) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
return .{
.result = .{
.overflow = overflow,
.value = self_position,
},
};
}
},
pub const parse = css.DeriveParse(@This()).parse;
pub const toCss = css.DeriveToCss(@This()).toCss;
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
};
/// A value for the [justify-self](https://www.w3.org/TR/css-align-3/#justify-self-property) property.
pub const JustifySelf = union(enum) {
/// Automatic justification.
auto,
/// Default justification.
normal,
/// Item is stretched.
stretch,
/// A baseline position keyword.
baseline_position: BaselinePosition,
/// A self position keyword.
self_position: struct {
/// A self position keyword.
value: SelfPosition,
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn toInner(this: *const @This()) SelfPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Item is justified to the left.
left: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Item is justified to the right.
right: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
pub fn parse(input: *css.Parser) css.Result(@This()) {
if (input.tryParse(css.Parser.expectIdentMatching, .{"auto"}).isOk()) {
return .{ .result = .auto };
}
if (input.tryParse(css.Parser.expectIdentMatching, .{"normal"}).isOk()) {
return .{ .result = .normal };
}
if (input.tryParse(css.Parser.expectIdentMatching, .{"stretch"}).isOk()) {
return .{ .result = .stretch };
}
if (input.tryParse(BaselinePosition.parse, .{}).asValue()) |val| {
return .{ .result = .{ .baseline_position = val } };
}
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
if (input.tryParse(SelfPosition.parse, .{}).asValue()) |self_position| {
return .{ .result = .{ .self_position = .{ .overflow = overflow, .value = self_position } } };
}
const location = input.currentSourceLocation();
const ident = switch (input.expectIdent()) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const Enum = enum { left, right };
const Map = bun.ComptimeEnumMap(Enum);
if (Map.getASCIIICaseInsensitive(ident)) |val| return .{ .result = switch (val) {
.left => .{ .left = .{ .overflow = overflow } },
.right => .{ .right = .{ .overflow = overflow } },
} };
return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) };
}
pub fn toCss(this: *const JustifySelf, dest: *css.Printer) css.PrintErr!void {
return switch (this.*) {
.auto => try dest.writeStr("auto"),
.normal => try dest.writeStr("normal"),
.stretch => try dest.writeStr("stretch"),
.baseline_position => |*baseline_position| baseline_position.toCss(dest),
.self_position => |*self_position| {
if (self_position.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try self_position.value.toCss(dest);
},
.left => |*left| {
if (left.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try dest.writeStr("left");
},
.right => |*right| {
if (right.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try dest.writeStr("right");
},
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [align-items](https://www.w3.org/TR/css-align-3/#align-items-property) property.
pub const AlignItems = union(enum) {
/// Default alignment.
normal,
/// Items are stretched.
stretch,
/// A baseline position keyword.
baseline_position: BaselinePosition,
/// A self position keyword.
self_position: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
/// A self position keyword.
value: SelfPosition,
pub fn toInner(this: *const @This()) SelfPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn parse(input: *css.Parser) css.Result(@This()) {
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
const self_position = switch (SelfPosition.parse(input)) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
return .{
.result = .{
.overflow = overflow,
.value = self_position,
},
};
}
pub fn __generateToCss() void {}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
pub const parse = css.DeriveParse(@This()).parse;
pub const toCss = css.DeriveToCss(@This()).toCss;
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [justify-items](https://www.w3.org/TR/css-align-3/#justify-items-property) property.
pub const JustifyItems = union(enum) {
/// Default justification.
normal,
/// Items are stretched.
stretch,
/// A baseline position keyword.
baseline_position: BaselinePosition,
/// A self position keyword, with optional overflow position.
self_position: struct {
/// A self position keyword.
value: SelfPosition,
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn toInner(this: *const @This()) SelfPositionInner {
return .{
.overflow = this.overflow,
.value = this.value,
};
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Items are justified to the left, with an optional overflow position.
left: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// Items are justified to the right, with an optional overflow position.
right: struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
},
/// A legacy justification keyword.
legacy: LegacyJustify,
pub fn parse(input: *css.Parser) css.Result(@This()) {
if (input.tryParse(css.Parser.expectIdentMatching, .{"normal"}).isOk()) {
return .{ .result = .normal };
}
if (input.tryParse(css.Parser.expectIdentMatching, .{"stretch"}).isOk()) {
return .{ .result = .stretch };
}
if (input.tryParse(BaselinePosition.parse, .{}).asValue()) |val| {
return .{ .result = .{ .baseline_position = val } };
}
if (input.tryParse(LegacyJustify.parse, .{}).asValue()) |val| {
return .{ .result = .{ .legacy = val } };
}
const overflow = input.tryParse(OverflowPosition.parse, .{}).asValue();
if (input.tryParse(SelfPosition.parse, .{}).asValue()) |self_position| {
return .{ .result = .{ .self_position = .{ .overflow = overflow, .value = self_position } } };
}
const location = input.currentSourceLocation();
const ident = switch (input.expectIdent()) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const Enum = enum { left, right };
const Map = bun.ComptimeEnumMap(Enum);
if (Map.getASCIIICaseInsensitive(ident)) |val| return .{ .result = switch (val) {
.left => .{ .left = .{ .overflow = overflow } },
.right => .{ .right = .{ .overflow = overflow } },
} };
return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) };
}
pub fn toCss(this: *const JustifyItems, dest: *css.Printer) css.PrintErr!void {
switch (this.*) {
.normal => try dest.writeStr("normal"),
.stretch => try dest.writeStr("stretch"),
.baseline_position => |*val| try val.toCss(dest),
.self_position => |*sp| {
if (sp.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try sp.value.toCss(dest);
},
.left => |*l| {
if (l.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try dest.writeStr("left");
},
.right => |*r| {
if (r.overflow) |*overflow| {
try overflow.toCss(dest);
try dest.writeStr(" ");
}
try dest.writeStr("right");
},
.legacy => |l| try l.toCss(dest),
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A legacy justification keyword, as used in the `justify-items` property.
pub const LegacyJustify = enum {
/// Left justify.
left,
/// Right justify.
right,
/// Centered.
center,
pub fn parse(input: *css.Parser) css.Result(@This()) {
const location = input.currentSourceLocation();
const ident = switch (input.expectIdent()) {
.err => |e| return .{ .err = e },
.result => |v| v,
};
const LegacyJustifyIdent = enum {
legacy,
left,
right,
center,
};
const LegacyJustifyMap = bun.ComptimeEnumMap(LegacyJustifyIdent);
if (LegacyJustifyMap.getASCIIICaseInsensitive(ident)) |value| {
switch (value) {
.legacy => {
const inner_location = input.currentSourceLocation();
const inner_ident = switch (input.expectIdent()) {
.err => |e| return .{ .err = e },
.result => |v| v,
};
const InnerEnum = enum { left, right, center };
const InnerLegacyJustifyMap = bun.ComptimeEnumMap(InnerEnum);
if (InnerLegacyJustifyMap.getASCIIICaseInsensitive(inner_ident)) |inner_value| {
return switch (inner_value) {
.left => .{ .result = .left },
.right => .{ .result = .right },
.center => .{ .result = .center },
};
} else {
return .{ .err = inner_location.newUnexpectedTokenError(.{ .ident = inner_ident }) };
}
},
.left => {
if (input.expectIdentMatching("legacy").asErr()) |e| return .{ .err = e };
return .{ .result = .left };
},
.right => {
if (input.expectIdentMatching("legacy").asErr()) |e| return .{ .err = e };
return .{ .result = .right };
},
.center => {
if (input.expectIdentMatching("legacy").asErr()) |e| return .{ .err = e };
return .{ .result = .center };
},
}
}
return .{ .err = location.newUnexpectedTokenError(.{ .ident = ident }) };
}
pub fn toCss(this: *const @This(), dest: *css.Printer) css.PrintErr!void {
try dest.writeStr("legacy ");
switch (this.*) {
.left => try dest.writeStr("left"),
.right => try dest.writeStr("right"),
.center => try dest.writeStr("center"),
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A [gap](https://www.w3.org/TR/css-align-3/#column-row-gap) value, as used in the
/// `column-gap` and `row-gap` properties.
pub const GapValue = union(enum) {
/// Equal to `1em` for multi-column containers, and zero otherwise.
normal,
/// An explicit length.
length_percentage: LengthPercentage,
pub const parse = css.DeriveParse(@This()).parse;
pub const toCss = css.DeriveToCss(@This()).toCss;
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [gap](https://www.w3.org/TR/css-align-3/#gap-shorthand) shorthand property.
pub const Gap = struct {
/// The row gap.
row: GapValue,
/// The column gap.
column: GapValue,
pub const PropertyFieldMap = .{
.row = "row-gap",
.column = "column-gap",
};
pub fn parse(input: *css.Parser) css.Result(@This()) {
const row = switch (@call(.auto, @field(GapValue, "parse"), .{input})) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const column = switch (input.tryParse(@field(GapValue, "parse"), .{})) {
.result => |v| v,
.err => row,
};
return .{ .result = .{ .row = row, .column = column } };
}
pub fn toCss(this: *const Gap, dest: *css.Printer) css.PrintErr!void {
try this.row.toCss(dest);
if (!this.column.eql(&this.row)) {
try dest.writeStr(" ");
try this.column.toCss(dest);
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [place-items](https://www.w3.org/TR/css-align-3/#place-items-property) shorthand property.
pub const PlaceItems = struct {
/// The item alignment.
@"align": AlignItems,
/// The item justification.
justify: JustifyItems,
pub const PropertyFieldMap = .{
.@"align" = "align-items",
.justify = "justify-items",
};
pub const VendorPrefixMap = .{
.@"align" = true,
};
pub fn parse(input: *css.Parser) css.Result(@This()) {
const @"align" = switch (@call(.auto, @field(AlignItems, "parse"), .{input})) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const justify = switch (input.tryParse(@field(JustifyItems, "parse"), .{})) {
.result => |v| v,
.err => switch (@"align") {
.normal => JustifyItems.normal,
.stretch => JustifyItems.stretch,
.baseline_position => |p| JustifyItems{ .baseline_position = p },
.self_position => |sp| JustifyItems{
.self_position = .{
.overflow = if (sp.overflow) |o| o else null,
.value = sp.value,
},
},
},
};
return .{ .result = .{ .@"align" = @"align", .justify = justify } };
}
pub fn toCss(this: *const PlaceItems, dest: *css.Printer) css.PrintErr!void {
try this.@"align".toCss(dest);
const is_equal = switch (this.justify) {
.normal => this.@"align".eql(&AlignItems{ .normal = {} }),
.stretch => this.@"align".eql(&AlignItems{ .stretch = {} }),
.baseline_position => |*p| brk: {
if (this.@"align" == .baseline_position) break :brk p.eql(&this.@"align".baseline_position);
break :brk false;
},
.self_position => |*p| brk: {
if (this.@"align" == .self_position) break :brk p.toInner().eql(&this.@"align".self_position.toInner());
break :brk false;
},
else => false,
};
if (!is_equal) {
try dest.writeStr(" ");
try this.justify.toCss(dest);
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A value for the [place-self](https://www.w3.org/TR/css-align-3/#place-self-property) shorthand property.
pub const PlaceSelf = struct {
/// The item alignment.
@"align": AlignSelf,
/// The item justification.
justify: JustifySelf,
pub const PropertyFieldMap = .{
.@"align" = "align-self",
.justify = "justify-self",
};
pub const VendorPrefixMap = .{
.@"align" = true,
};
pub fn parse(input: *css.Parser) css.Result(@This()) {
const @"align" = switch (@call(.auto, @field(AlignSelf, "parse"), .{input})) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const justify = switch (input.tryParse(@field(JustifySelf, "parse"), .{})) {
.result => |v| v,
.err => switch (@"align") {
.auto => JustifySelf.auto,
.normal => JustifySelf.normal,
.stretch => JustifySelf.stretch,
.baseline_position => |p| JustifySelf{ .baseline_position = p },
.self_position => |sp| JustifySelf{
.self_position = .{
.overflow = if (sp.overflow) |o| o else null,
.value = sp.value,
},
},
},
};
return .{ .result = .{ .@"align" = @"align", .justify = justify } };
}
pub fn toCss(this: *const PlaceSelf, dest: *css.Printer) css.PrintErr!void {
try this.@"align".toCss(dest);
const is_equal = switch (this.justify) {
.auto => true,
.normal => this.@"align" == .normal,
.stretch => this.@"align" == .stretch,
.baseline_position => |p| switch (this.@"align") {
.baseline_position => |p2| p.eql(&p2),
else => false,
},
.self_position => |sp| brk: {
if (this.@"align" == .self_position) break :brk sp.toInner().eql(&this.@"align".self_position.toInner());
break :brk false;
},
else => false,
};
if (!is_equal) {
try dest.writeStr(" ");
try this.justify.toCss(dest);
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A [`<self-position>`](https://www.w3.org/TR/css-align-3/#typedef-self-position) value.
pub const SelfPosition = enum {
/// Item is centered within the container.
center,
/// Item is aligned to the start of the container.
start,
/// Item is aligned to the end of the container.
end,
/// Item is aligned to the edge of the container corresponding to the start side of the item.
@"self-start",
/// Item is aligned to the edge of the container corresponding to the end side of the item.
@"self-end",
/// Item is aligned to the start of the container, within flexbox layouts.
@"flex-start",
/// Item is aligned to the end of the container, within flexbox layouts.
@"flex-end",
const css_impl = css.DefineEnumProperty(@This());
pub const eql = css_impl.eql;
pub const hash = css_impl.hash;
pub const parse = css_impl.parse;
pub const toCss = css_impl.toCss;
pub const deepClone = css_impl.deepClone;
};
/// A value for the [place-content](https://www.w3.org/TR/css-align-3/#place-content) shorthand property.
pub const PlaceContent = struct {
/// The content alignment.
@"align": AlignContent,
/// The content justification.
justify: JustifyContent,
pub const PropertyFieldMap = .{
.@"align" = css.PropertyIdTag.@"align-content",
.justify = css.PropertyIdTag.@"justify-content",
};
pub const VendorPrefixMap = .{
.@"align" = true,
.justify = true,
};
pub fn parse(input: *css.Parser) css.Result(@This()) {
const @"align" = switch (@call(.auto, @field(AlignContent, "parse"), .{input})) {
.result => |v| v,
.err => |e| return .{ .err = e },
};
const justify = switch (@call(.auto, @field(JustifyContent, "parse"), .{input})) {
.result => |v| v,
.err => |_| switch (@"align") {
.baseline_position => JustifyContent{ .content_position = .{
.overflow = null,
.value = .start,
} },
.normal => JustifyContent.normal,
.content_distribution => |value| JustifyContent{ .content_distribution = value },
.content_position => |pos| JustifyContent{ .content_position = .{
.overflow = if (pos.overflow) |*overflow| overflow.deepClone(input.allocator()) else null,
.value = pos.value.deepClone(input.allocator()),
} },
},
};
return .{ .result = .{ .@"align" = @"align", .justify = justify } };
}
pub fn toCss(this: *const PlaceContent, dest: *css.Printer) css.PrintErr!void {
try this.@"align".toCss(dest);
const is_equal = switch (this.justify) {
.normal => brk: {
if (this.@"align" == .normal) break :brk true;
break :brk false;
},
.content_distribution => |*d| brk: {
if (this.@"align" == .content_distribution) break :brk d.eql(&this.@"align".content_distribution);
break :brk false;
},
.content_position => |*p| brk: {
if (this.@"align" == .content_position) break :brk p.toInner().eql(&this.@"align".content_position.toInner());
break :brk false;
},
else => false,
};
if (!is_equal) {
try dest.writeStr(" ");
try this.justify.toCss(dest);
}
}
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
pub fn deepClone(this: *const @This(), allocator: std.mem.Allocator) @This() {
return css.implementDeepClone(@This(), this, allocator);
}
};
/// A [`<content-distribution>`](https://www.w3.org/TR/css-align-3/#typedef-content-distribution) value.
pub const ContentDistribution = enum {
/// Items are spaced evenly, with the first and last items against the edge of the container.
@"space-between",
/// Items are spaced evenly, with half-size spaces at the start and end.
@"space-around",
/// Items are spaced evenly, with full-size spaces at the start and end.
@"space-evenly",
/// Items are stretched evenly to fill free space.
stretch,
const css_impl = css.DefineEnumProperty(@This());
pub const eql = css_impl.eql;
pub const hash = css_impl.hash;
pub const parse = css_impl.parse;
pub const toCss = css_impl.toCss;
pub const deepClone = css_impl.deepClone;
};
/// An [`<overflow-position>`](https://www.w3.org/TR/css-align-3/#typedef-overflow-position) value.
pub const OverflowPosition = enum {
/// If the size of the alignment subject overflows the alignment container,
/// the alignment subject is instead aligned as if the alignment mode were start.
safe,
/// Regardless of the relative sizes of the alignment subject and alignment
/// container, the given alignment value is honored.
unsafe,
const css_impl = css.DefineEnumProperty(@This());
pub const eql = css_impl.eql;
pub const hash = css_impl.hash;
pub const parse = css_impl.parse;
pub const toCss = css_impl.toCss;
pub const deepClone = css_impl.deepClone;
};
/// A [`<content-position>`](https://www.w3.org/TR/css-align-3/#typedef-content-position) value.
pub const ContentPosition = enum {
/// Content is centered within the container.
center,
/// Content is aligned to the start of the container.
start,
/// Content is aligned to the end of the container.
end,
/// Same as `start` when within a flexbox container.
@"flex-start",
/// Same as `end` when within a flexbox container.
@"flex-end",
const css_impl = css.DefineEnumProperty(@This());
pub const eql = css_impl.eql;
pub const hash = css_impl.hash;
pub const parse = css_impl.parse;
pub const toCss = css_impl.toCss;
pub const deepClone = css_impl.deepClone;
};
pub const SelfPositionInner = struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
/// A self position keyword.
value: SelfPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
};
pub const ContentPositionInner = struct {
/// An overflow alignment mode.
overflow: ?OverflowPosition,
/// A content position keyword.
value: ContentPosition,
pub fn eql(lhs: *const @This(), rhs: *const @This()) bool {
return css.implementEql(@This(), lhs, rhs);
}
};
const FlexLinePack = css.css_properties.flex.FlexLinePack;
const BoxPack = css.css_properties.flex.BoxPack;
const FlexPack = css.css_properties.flex.FlexPack;
const BoxAlign = css.css_properties.flex.BoxAlign;
const FlexAlign = css.css_properties.flex.FlexAlign;
const FlexItemAlign = css.css_properties.flex.FlexItemAlign;
pub const AlignHandler = struct {
align_content: ?struct { AlignContent, VendorPrefix } = null,
flex_line_pack: ?struct { FlexLinePack, VendorPrefix } = null,
justify_content: ?struct { JustifyContent, VendorPrefix } = null,
box_pack: ?struct { BoxPack, VendorPrefix } = null,
flex_pack: ?struct { FlexPack, VendorPrefix } = null,
align_self: ?struct { AlignSelf, VendorPrefix } = null,
flex_item_align: ?struct { FlexItemAlign, VendorPrefix } = null,
justify_self: ?JustifySelf = null,
align_items: ?struct { AlignItems, VendorPrefix } = null,
box_align: ?struct { BoxAlign, VendorPrefix } = null,
flex_align: ?struct { FlexAlign, VendorPrefix } = null,
justify_items: ?JustifyItems = null,
row_gap: ?GapValue = null,
column_gap: ?GapValue = null,
has_any: bool = false,
pub fn handleProperty(this: *AlignHandler, property: *const Property, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) bool {
switch (property.*) {
.@"align-content" => |*val| {
this.flex_line_pack = null;
this.handlePropertyHelper(dest, context, "align_content", &val.*[0], val.*[1]);
},
.@"flex-line-pack" => |*val| this.handlePropertyHelper(dest, context, "flex_line_pack", &val.*[0], val.*[1]),
.@"justify-content" => |*val| {
this.box_pack = null;
this.flex_pack = null;
this.handlePropertyHelper(dest, context, "justify_content", &val.*[0], val.*[1]);
},
.@"box-pack" => |*val| this.handlePropertyHelper(dest, context, "box_pack", &val.*[0], val.*[1]),
.@"flex-pack" => |*val| this.handlePropertyHelper(dest, context, "flex_pack", &val.*[0], val.*[1]),
.@"place-content" => |*val| {
this.flex_line_pack = null;
this.box_pack = null;
this.flex_pack = null;
this.handlePropertyMaybeFlush(dest, context, "align_content", &val.@"align", VendorPrefix.NONE);
this.handlePropertyMaybeFlush(dest, context, "justify_content", &val.justify, VendorPrefix.NONE);
this.handlePropertyHelper(dest, context, "align_content", &val.@"align", VendorPrefix.NONE);
this.handlePropertyHelper(dest, context, "justify_content", &val.justify, VendorPrefix.NONE);
},
.@"align-self" => |*val| {
this.flex_item_align = null;
this.handlePropertyHelper(dest, context, "align_self", &val.*[0], val.*[1]);
},
.@"flex-item-align" => |*val| this.handlePropertyHelper(dest, context, "flex_item_align", &val.*[0], val.*[1]),
.@"justify-self" => |*val| {
this.justify_self = css.generic.deepClone(@TypeOf(val.*), val, context.allocator);
this.has_any = true;
},
.@"place-self" => |*val| {
this.flex_item_align = null;
this.handlePropertyHelper(dest, context, "align_self", &val.@"align", VendorPrefix.NONE);
this.justify_self = css.generic.deepClone(@TypeOf(val.justify), &val.justify, context.allocator);
},
.@"align-items" => |*val| {
this.box_align = null;
this.flex_align = null;
this.handlePropertyHelper(dest, context, "align_items", &val.*[0], val.*[1]);
},
.@"box-align" => |*val| this.handlePropertyHelper(dest, context, "box_align", &val.*[0], val.*[1]),
.@"flex-align" => |*val| this.handlePropertyHelper(dest, context, "flex_align", &val.*[0], val.*[1]),
.@"justify-items" => |*val| {
this.justify_items = css.generic.deepClone(@TypeOf(val.*), val, context.allocator);
this.has_any = true;
},
.@"place-items" => |*val| {
this.box_align = null;
this.flex_align = null;
this.handlePropertyHelper(dest, context, "align_items", &val.@"align", VendorPrefix.NONE);
this.justify_items = css.generic.deepClone(@TypeOf(val.justify), &val.justify, context.allocator);
},
.@"row-gap" => |*val| {
this.row_gap = css.generic.deepClone(@TypeOf(val.*), val, context.allocator);
this.has_any = true;
},
.@"column-gap" => |*val| {
this.column_gap = css.generic.deepClone(@TypeOf(val.*), val, context.allocator);
this.has_any = true;
},
.gap => |*val| {
this.row_gap = css.generic.deepClone(@TypeOf(val.row), &val.row, context.allocator);
this.column_gap = css.generic.deepClone(@TypeOf(val.column), &val.column, context.allocator);
this.has_any = true;
},
.unparsed => |*val| {
if (isAlignProperty(val.property_id)) {
this.flush(dest, context);
bun.handleOom(dest.append(context.allocator, property.*));
} else {
return false;
}
},
else => return false,
}
return true;
}
pub fn finalize(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void {
this.flush(dest, context);
}
fn flush(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void {
if (!this.has_any) {
return;
}
this.has_any = false;
var align_content = bun.take(&this.align_content);
var justify_content = bun.take(&this.justify_content);
var align_self = bun.take(&this.align_self);
var justify_self = bun.take(&this.justify_self);
var align_items = bun.take(&this.align_items);
var justify_items = bun.take(&this.justify_items);
const row_gap = bun.take(&this.row_gap);
const column_gap = bun.take(&this.column_gap);
var box_align = bun.take(&this.box_align);
var box_pack = bun.take(&this.box_pack);
var flex_line_pack = bun.take(&this.flex_line_pack);
var flex_pack = bun.take(&this.flex_pack);
var flex_align = bun.take(&this.flex_align);
var flex_item_align = bun.take(&this.flex_item_align);
// 2009 properties
this.flushPrefixedProperty(dest, context, "box-align", bun.take(&box_align));
this.flushPrefixedProperty(dest, context, "box-pack", bun.take(&box_pack));
// 2012 properties
this.flushPrefixedProperty(dest, context, "flex-pack", bun.take(&flex_pack));
this.flushPrefixedProperty(dest, context, "flex-align", bun.take(&flex_align));
this.flushPrefixedProperty(dest, context, "flex-item-align", bun.take(&flex_item_align));
this.flushPrefixedProperty(dest, context, "flex-line-pack", bun.take(&flex_line_pack));
this.flushLegacyProperty(dest, context, Feature.align_content, &align_content, null, .{ FlexLinePack, "flex-line-pack" });
this.flushLegacyProperty(dest, context, Feature.justify_content, &justify_content, .{ BoxPack, "box-pack" }, .{ FlexPack, "flex-pack" });
if (context.targets.isCompatible(.place_content)) {
this.flushShorthandHelper(
dest,
context,
.{ .prop = "place-content", .ty = PlaceContent },
.{ .feature = Feature.align_content, .prop = "align-content" },
&align_content,
&justify_content,
.{ .feature = Feature.justify_content, .prop = "justify-content" },
);
}
this.flushStandardPropertyHelper(dest, context, "align-content", bun.take(&align_content), Feature.align_content);
this.flushStandardPropertyHelper(dest, context, "justify-content", bun.take(&justify_content), Feature.justify_content);
this.flushLegacyProperty(dest, context, Feature.align_self, &align_self, null, .{ FlexItemAlign, "flex-item-align" });
if (context.targets.isCompatible(.place_self)) {
this.flushShorthandHelper(dest, context, .{ .prop = "place-self", .ty = PlaceSelf }, .{ .feature = Feature.align_self, .prop = "align-self" }, &align_self, &justify_self, null);
}
this.flushStandardPropertyHelper(dest, context, "align-self", bun.take(&align_self), Feature.align_self);
this.flushUnprefixProperty(dest, context, "justify-self", bun.take(&justify_self));
this.flushLegacyProperty(dest, context, Feature.align_items, &align_items, .{ BoxAlign, "box-align" }, .{ FlexAlign, "flex-align" });
if (context.targets.isCompatible(css.compat.Feature.place_items)) {
this.flushShorthandHelper(dest, context, .{ .prop = "place-items", .ty = PlaceItems }, .{ .feature = Feature.align_items, .prop = "align-items" }, &align_items, &justify_items, null);
}
this.flushStandardPropertyHelper(dest, context, "align-items", bun.take(&align_items), Feature.align_items);
this.flushUnprefixProperty(dest, context, "justify-items", bun.take(&justify_items));
if (row_gap != null and column_gap != null) {
dest.append(context.allocator, Property{ .gap = Gap{
.row = row_gap.?,
.column = column_gap.?,
} }) catch |err| bun.handleOom(err);
} else {
if (row_gap != null) {
bun.handleOom(dest.append(context.allocator, Property{ .@"row-gap" = row_gap.? }));
}
if (column_gap != null) {
bun.handleOom(dest.append(context.allocator, Property{ .@"column-gap" = column_gap.? }));
}
}
}
fn handlePropertyMaybeFlush(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void {
// If two vendor prefixes for the same property have different
// values, we need to flush what we have immediately to preserve order.
if (@field(this, prop)) |*v| {
if (!val.eql(&v[0]) and !bun.bits.contains(VendorPrefix, v[1], vp)) {
this.flush(dest, context);
}
}
}
fn handlePropertyHelper(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, val: anytype, vp: VendorPrefix) void {
this.handlePropertyMaybeFlush(dest, context, prop, val, vp);
// Otherwise, update the value and add the prefix.
if (@field(this, prop)) |*tuple| {
tuple.*[0] = css.generic.deepClone(@TypeOf(val.*), val, context.allocator);
bun.bits.insert(VendorPrefix, &tuple.*[1], vp);
} else {
@field(this, prop) = .{ css.generic.deepClone(@TypeOf(val.*), val, context.allocator), vp };
this.has_any = true;
}
}
// Gets prefixes for standard properties.
fn flushPrefixesHelper(_: *AlignHandler, context: *css.PropertyHandlerContext, comptime feature: Feature) VendorPrefix {
var prefix = context.targets.prefixes(VendorPrefix.NONE, feature);
// Firefox only implemented the 2009 spec prefixed.
// Microsoft only implemented the 2012 spec prefixed.
prefix.moz = false;
prefix.ms = false;
return prefix;
}
fn flushStandardPropertyHelper(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype, comptime feature: Feature) void {
if (key) |v| {
const val = v[0];
var prefix = v[1];
// If we have an unprefixed property, override necessary prefixes.
prefix = if (prefix.none) flushPrefixesHelper(this, context, feature) else prefix;
bun.handleOom(dest.append(context.allocator, @unionInit(Property, prop, .{ val, prefix })));
}
}
fn flushLegacyProperty(
this: *AlignHandler,
dest: *css.DeclarationList,
context: *css.PropertyHandlerContext,
comptime feature: Feature,
key: anytype,
comptime prop_2009: ?struct { type, []const u8 },
comptime prop_2012: ?struct { type, []const u8 },
) void {
_ = this; // autofix
if (key.*) |v| {
const val = v[0];
var prefix = v[1];
// If we have an unprefixed standard property, generate legacy prefixed versions.
prefix = context.targets.prefixes(prefix, feature);
if (prefix.none) {
if (comptime prop_2009) |p2009| {
// 2009 spec, implemented by webkit and firefox.
if (context.targets.browsers) |targets| {
var prefixes_2009 = VendorPrefix{};
if (Feature.isFlex2009(targets)) {
prefixes_2009.webkit = true;
}
if (prefix.moz) {
prefixes_2009.moz = true;
}
if (!prefixes_2009.isEmpty()) {
const s = brk: {
const T = comptime p2009[0];
if (comptime T == css.css_properties.flex.BoxOrdinalGroup) break :brk @as(?i32, val);
break :brk p2009[0].fromStandard(&val);
};
if (s) |a| {
dest.append(context.allocator, @unionInit(Property, p2009[1], .{
a,
prefixes_2009,
})) catch |err| bun.handleOom(err);
}
}
}
}
}
// 2012 spec, implemented by microsoft.
if (prefix.ms) {
if (comptime prop_2012) |p2012| {
const s = brk: {
const T = comptime p2012[0];
if (comptime T == css.css_properties.flex.BoxOrdinalGroup) break :brk @as(?i32, val);
break :brk p2012[0].fromStandard(&val);
};
if (s) |q| {
dest.append(context.allocator, @unionInit(Property, p2012[1], .{
q,
VendorPrefix.MS,
})) catch |err| bun.handleOom(err);
}
}
}
// Remove Firefox and IE from standard prefixes.
prefix.moz = false;
prefix.ms = false;
}
}
fn flushPrefixedProperty(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype) void {
_ = this; // autofix
if (key) |v| {
const val = v[0];
const prefix = v[1];
bun.handleOom(dest.append(context.allocator, @unionInit(Property, prop, .{ val, prefix })));
}
}
fn flushUnprefixProperty(this: *AlignHandler, dest: *css.DeclarationList, context: *css.PropertyHandlerContext, comptime prop: []const u8, key: anytype) void {
_ = this; // autofix
if (key) |v| {
const val = v;
bun.handleOom(dest.append(context.allocator, @unionInit(Property, prop, val)));
}
}
fn flushShorthandHelper(
this: *AlignHandler,
dest: *css.DeclarationList,
context: *css.PropertyHandlerContext,
comptime prop: struct { prop: []const u8, ty: type },
comptime align_prop: struct {
feature: Feature,
prop: []const u8,
},
align_val: anytype,
justify_val: anytype,
comptime justify_prop: ?struct {
feature: Feature,
prop: []const u8,
},
) void {
// Only use shorthand if both align and justify are present
if (align_val.*) |*__v1| {
const @"align" = &__v1.*[0];
const align_prefix: *css.VendorPrefix = &__v1.*[1];
if (justify_val.*) |*__v2| {
const justify = __v2;
const intersection = align_prefix.bitwiseAnd(if (comptime justify_prop != null) __v2.*[1] else align_prefix.*);
// Only use shorthand if unprefixed.
if (intersection.none) {
// Add prefixed longhands if needed.
align_prefix.* = flushPrefixesHelper(this, context, align_prop.feature);
align_prefix.none = false;
if (!align_prefix.isEmpty()) {
dest.append(
context.allocator,
@unionInit(Property, align_prop.prop, .{ css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator), align_prefix.* }),
) catch |err| bun.handleOom(err);
}
if (comptime justify_prop != null) {
const justify_actual = &__v2.*[0];
const justify_prefix = &__v2.*[1];
justify_prefix.* = this.flushPrefixesHelper(context, justify_prop.?.feature);
justify_prefix.none = false;
if (!justify_prefix.isEmpty()) {
dest.append(
context.allocator,
@unionInit(Property, justify_prop.?.prop, .{ css.generic.deepClone(@TypeOf(justify_actual.*), justify_actual, context.allocator), justify_prefix.* }),
) catch |err| bun.handleOom(err);
}
// Add shorthand.
dest.append(
context.allocator,
@unionInit(Property, prop.prop, prop.ty{
.@"align" = css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator),
.justify = css.generic.deepClone(@TypeOf(justify_actual.*), justify_actual, context.allocator),
}),
) catch |err| bun.handleOom(err);
} else {
// Add shorthand.
dest.append(
context.allocator,
@unionInit(Property, prop.prop, prop.ty{
.@"align" = css.generic.deepClone(@TypeOf(@"align".*), @"align", context.allocator),
.justify = css.generic.deepClone(@TypeOf(justify.*), justify, context.allocator),
}),
) catch |err| bun.handleOom(err);
}
align_val.* = null;
justify_val.* = null;
}
}
}
}
};
fn isAlignProperty(property_id: css.PropertyId) bool {
return switch (property_id) {
.@"align-content",
.@"flex-line-pack",
.@"justify-content",
.@"box-pack",
.@"flex-pack",
.@"place-content",
.@"align-self",
.@"flex-item-align",
.@"justify-self",
.@"place-self",
.@"align-items",
.@"box-align",
.@"flex-align",
.@"justify-items",
.@"place-items",
.@"row-gap",
.@"column-gap",
.gap,
=> true,
else => false,
};
}
const bun = @import("bun");
const std = @import("std");
const Allocator = std.mem.Allocator;