mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 13:51:47 +00:00
Replace `catch bun.outOfMemory()`, which can accidentally catch non-OOM-related errors, with either `bun.handleOom` or a manual `catch |err| switch (err)`. (For internal tracking: fixes STAB-1070) --------- Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
853 lines
36 KiB
Zig
853 lines
36 KiB
Zig
pub const css = @import("../css_parser.zig");
|
|
const Property = css.Property;
|
|
const PropertyIdTag = css.PropertyIdTag;
|
|
const PropertyCategory = css.logical.PropertyCategory;
|
|
|
|
const LengthPercentageOrAuto = css.css_values.length.LengthPercentageOrAuto;
|
|
|
|
/// A value for the [inset](https://drafts.csswg.org/css-logical/#propdef-inset) shorthand property.
|
|
pub const Inset = struct {
|
|
top: LengthPercentageOrAuto,
|
|
right: LengthPercentageOrAuto,
|
|
bottom: LengthPercentageOrAuto,
|
|
left: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.inset);
|
|
const css_impl = css.DefineRectShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.top = css.PropertyIdTag.top,
|
|
.right = css.PropertyIdTag.right,
|
|
.bottom = css.PropertyIdTag.bottom,
|
|
.left = css.PropertyIdTag.left,
|
|
};
|
|
|
|
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 [inset-block](https://drafts.csswg.org/css-logical/#propdef-inset-block) shorthand property.
|
|
pub const InsetBlock = struct {
|
|
/// The block start value.
|
|
block_start: LengthPercentageOrAuto,
|
|
/// The block end value.
|
|
block_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"inset-block");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.block_start = css.PropertyIdTag.@"inset-block-start",
|
|
.block_end = css.PropertyIdTag.@"inset-block-end",
|
|
};
|
|
|
|
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 [inset-inline](https://drafts.csswg.org/css-logical/#propdef-inset-inline) shorthand property.
|
|
pub const InsetInline = struct {
|
|
/// The inline start value.
|
|
inline_start: LengthPercentageOrAuto,
|
|
/// The inline end value.
|
|
inline_end: LengthPercentageOrAuto,
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.inline_start = css.PropertyIdTag.@"inset-inline-start",
|
|
.inline_end = css.PropertyIdTag.@"inset-inline-end",
|
|
};
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"inset-inline");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
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 [margin-block](https://drafts.csswg.org/css-logical/#propdef-margin-block) shorthand property.
|
|
pub const MarginBlock = struct {
|
|
/// The block start value.
|
|
block_start: LengthPercentageOrAuto,
|
|
/// The block end value.
|
|
block_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"margin-block");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.block_start = css.PropertyIdTag.@"margin-block-start",
|
|
.block_end = css.PropertyIdTag.@"margin-block-end",
|
|
};
|
|
|
|
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 [margin-inline](https://drafts.csswg.org/css-logical/#propdef-margin-inline) shorthand property.
|
|
pub const MarginInline = struct {
|
|
/// The inline start value.
|
|
inline_start: LengthPercentageOrAuto,
|
|
/// The inline end value.
|
|
inline_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"margin-inline");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.inline_start = css.PropertyIdTag.@"margin-inline-start",
|
|
.inline_end = css.PropertyIdTag.@"margin-inline-end",
|
|
};
|
|
|
|
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 [margin](https://drafts.csswg.org/css-box-4/#propdef-margin) shorthand property.
|
|
pub const Margin = struct {
|
|
top: LengthPercentageOrAuto,
|
|
right: LengthPercentageOrAuto,
|
|
bottom: LengthPercentageOrAuto,
|
|
left: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.margin);
|
|
const css_impl = css.DefineRectShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.top = css.PropertyIdTag.@"margin-top",
|
|
.right = css.PropertyIdTag.@"margin-right",
|
|
.bottom = css.PropertyIdTag.@"margin-bottom",
|
|
.left = css.PropertyIdTag.@"margin-left",
|
|
};
|
|
|
|
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 [padding-block](https://drafts.csswg.org/css-logical/#propdef-padding-block) shorthand property.
|
|
pub const PaddingBlock = struct {
|
|
/// The block start value.
|
|
block_start: LengthPercentageOrAuto,
|
|
/// The block end value.
|
|
block_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"padding-block");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.block_start = css.PropertyIdTag.@"padding-block-start",
|
|
.block_end = css.PropertyIdTag.@"padding-block-end",
|
|
};
|
|
|
|
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 [padding-inline](https://drafts.csswg.org/css-logical/#propdef-padding-inline) shorthand property.
|
|
pub const PaddingInline = struct {
|
|
/// The inline start value.
|
|
inline_start: LengthPercentageOrAuto,
|
|
/// The inline end value.
|
|
inline_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"padding-inline");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.inline_start = css.PropertyIdTag.@"padding-inline-start",
|
|
.inline_end = css.PropertyIdTag.@"padding-inline-end",
|
|
};
|
|
|
|
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 [padding](https://drafts.csswg.org/css-box-4/#propdef-padding) shorthand property.
|
|
pub const Padding = struct {
|
|
top: LengthPercentageOrAuto,
|
|
right: LengthPercentageOrAuto,
|
|
bottom: LengthPercentageOrAuto,
|
|
left: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.padding);
|
|
const css_impl = css.DefineRectShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.top = css.PropertyIdTag.@"padding-top",
|
|
.right = css.PropertyIdTag.@"padding-right",
|
|
.bottom = css.PropertyIdTag.@"padding-bottom",
|
|
.left = css.PropertyIdTag.@"padding-left",
|
|
};
|
|
|
|
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 [scroll-margin-block](https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-margin-block) shorthand property.
|
|
pub const ScrollMarginBlock = struct {
|
|
/// The block start value.
|
|
block_start: LengthPercentageOrAuto,
|
|
/// The block end value.
|
|
block_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-margin-block");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.block_start = css.PropertyIdTag.@"scroll-margin-block-start",
|
|
.block_end = css.PropertyIdTag.@"scroll-margin-block-end",
|
|
};
|
|
|
|
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 [scroll-margin-inline](https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-margin-inline) shorthand property.
|
|
pub const ScrollMarginInline = struct {
|
|
/// The inline start value.
|
|
inline_start: LengthPercentageOrAuto,
|
|
/// The inline end value.
|
|
inline_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-margin-inline");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.inline_start = css.PropertyIdTag.@"scroll-margin-inline-start",
|
|
.inline_end = css.PropertyIdTag.@"scroll-margin-inline-end",
|
|
};
|
|
|
|
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 [scroll-margin](https://drafts.csswg.org/css-scroll-snap/#scroll-margin) shorthand property.
|
|
pub const ScrollMargin = struct {
|
|
top: LengthPercentageOrAuto,
|
|
right: LengthPercentageOrAuto,
|
|
bottom: LengthPercentageOrAuto,
|
|
left: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-margin");
|
|
const css_impl = css.DefineRectShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.top = css.PropertyIdTag.@"scroll-margin-top",
|
|
.right = css.PropertyIdTag.@"scroll-margin-right",
|
|
.bottom = css.PropertyIdTag.@"scroll-margin-bottom",
|
|
.left = css.PropertyIdTag.@"scroll-margin-left",
|
|
};
|
|
|
|
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 [scroll-padding-block](https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-padding-block) shorthand property.
|
|
pub const ScrollPaddingBlock = struct {
|
|
/// The block start value.
|
|
block_start: LengthPercentageOrAuto,
|
|
/// The block end value.
|
|
block_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-padding-block");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.block_start = css.PropertyIdTag.@"scroll-padding-block-start",
|
|
.block_end = css.PropertyIdTag.@"scroll-padding-block-end",
|
|
};
|
|
|
|
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 [scroll-padding-inline](https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-padding-inline) shorthand property.
|
|
pub const ScrollPaddingInline = struct {
|
|
/// The inline start value.
|
|
inline_start: LengthPercentageOrAuto,
|
|
/// The inline end value.
|
|
inline_end: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-padding-inline");
|
|
const css_impl = css.DefineSizeShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.inline_start = css.PropertyIdTag.@"scroll-padding-inline-start",
|
|
.inline_end = css.PropertyIdTag.@"scroll-padding-inline-end",
|
|
};
|
|
|
|
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 [scroll-padding](https://drafts.csswg.org/css-scroll-snap/#scroll-padding) shorthand property.
|
|
pub const ScrollPadding = struct {
|
|
top: LengthPercentageOrAuto,
|
|
right: LengthPercentageOrAuto,
|
|
bottom: LengthPercentageOrAuto,
|
|
left: LengthPercentageOrAuto,
|
|
|
|
// TODO: bring this back
|
|
// (old using name space) css.DefineShorthand(@This(), css.PropertyIdTag.@"scroll-padding");
|
|
const css_impl = css.DefineRectShorthand(@This(), LengthPercentageOrAuto);
|
|
pub const toCss = css_impl.toCss;
|
|
pub const parse = css_impl.parse;
|
|
|
|
pub const PropertyFieldMap = .{
|
|
.top = css.PropertyIdTag.@"scroll-padding-top",
|
|
.right = css.PropertyIdTag.@"scroll-padding-right",
|
|
.bottom = css.PropertyIdTag.@"scroll-padding-bottom",
|
|
.left = css.PropertyIdTag.@"scroll-padding-left",
|
|
};
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
pub const MarginHandler = NewSizeHandler(
|
|
PropertyIdTag.@"margin-top",
|
|
PropertyIdTag.@"margin-bottom",
|
|
PropertyIdTag.@"margin-left",
|
|
PropertyIdTag.@"margin-right",
|
|
PropertyIdTag.@"margin-block-start",
|
|
PropertyIdTag.@"margin-block-end",
|
|
PropertyIdTag.@"margin-inline-start",
|
|
PropertyIdTag.@"margin-inline-end",
|
|
PropertyIdTag.margin,
|
|
PropertyIdTag.@"margin-block",
|
|
PropertyIdTag.@"margin-inline",
|
|
PropertyCategory.physical,
|
|
.{
|
|
.feature = css.Feature.logical_margin,
|
|
.shorthand_feature = css.Feature.logical_margin_shorthand,
|
|
},
|
|
);
|
|
|
|
pub const PaddingHandler = NewSizeHandler(
|
|
PropertyIdTag.@"padding-top",
|
|
PropertyIdTag.@"padding-bottom",
|
|
PropertyIdTag.@"padding-left",
|
|
PropertyIdTag.@"padding-right",
|
|
PropertyIdTag.@"padding-block-start",
|
|
PropertyIdTag.@"padding-block-end",
|
|
PropertyIdTag.@"padding-inline-start",
|
|
PropertyIdTag.@"padding-inline-end",
|
|
PropertyIdTag.padding,
|
|
PropertyIdTag.@"padding-block",
|
|
PropertyIdTag.@"padding-inline",
|
|
PropertyCategory.physical,
|
|
.{
|
|
.feature = css.Feature.logical_padding,
|
|
.shorthand_feature = css.Feature.logical_padding_shorthand,
|
|
},
|
|
);
|
|
|
|
pub const ScrollMarginHandler = NewSizeHandler(
|
|
PropertyIdTag.@"scroll-margin-top",
|
|
PropertyIdTag.@"scroll-margin-bottom",
|
|
PropertyIdTag.@"scroll-margin-left",
|
|
PropertyIdTag.@"scroll-margin-right",
|
|
PropertyIdTag.@"scroll-margin-block-start",
|
|
PropertyIdTag.@"scroll-margin-block-end",
|
|
PropertyIdTag.@"scroll-margin-inline-start",
|
|
PropertyIdTag.@"scroll-margin-inline-end",
|
|
PropertyIdTag.@"scroll-margin",
|
|
PropertyIdTag.@"scroll-margin-block",
|
|
PropertyIdTag.@"scroll-margin-inline",
|
|
PropertyCategory.physical,
|
|
null,
|
|
);
|
|
|
|
pub const InsetHandler = NewSizeHandler(
|
|
PropertyIdTag.top,
|
|
PropertyIdTag.bottom,
|
|
PropertyIdTag.left,
|
|
PropertyIdTag.right,
|
|
PropertyIdTag.@"inset-block-start",
|
|
PropertyIdTag.@"inset-block-end",
|
|
PropertyIdTag.@"inset-inline-start",
|
|
PropertyIdTag.@"inset-inline-end",
|
|
PropertyIdTag.inset,
|
|
PropertyIdTag.@"inset-block",
|
|
PropertyIdTag.@"inset-inline",
|
|
PropertyCategory.physical,
|
|
.{
|
|
.feature = css.Feature.logical_inset,
|
|
.shorthand_feature = css.Feature.logical_inset,
|
|
},
|
|
);
|
|
|
|
pub fn NewSizeHandler(
|
|
comptime top_prop: css.PropertyIdTag,
|
|
comptime bottom_prop: css.PropertyIdTag,
|
|
comptime left_prop: css.PropertyIdTag,
|
|
comptime right_prop: css.PropertyIdTag,
|
|
comptime block_start_prop: css.PropertyIdTag,
|
|
comptime block_end_prop: css.PropertyIdTag,
|
|
comptime inline_start_prop: css.PropertyIdTag,
|
|
comptime inline_end_prop: css.PropertyIdTag,
|
|
comptime shorthand_prop: css.PropertyIdTag,
|
|
comptime block_shorthand: css.PropertyIdTag,
|
|
comptime inline_shorthand: css.PropertyIdTag,
|
|
comptime shorthand_category: css.logical.PropertyCategory,
|
|
comptime shorthand_extra: ?struct { feature: css.compat.Feature, shorthand_feature: css.compat.Feature },
|
|
) type {
|
|
return struct {
|
|
top: ?LengthPercentageOrAuto = null,
|
|
bottom: ?LengthPercentageOrAuto = null,
|
|
left: ?LengthPercentageOrAuto = null,
|
|
right: ?LengthPercentageOrAuto = null,
|
|
block_start: ?Property = null,
|
|
block_end: ?Property = null,
|
|
inline_start: ?Property = null,
|
|
inline_end: ?Property = null,
|
|
has_any: bool = false,
|
|
category: css.logical.PropertyCategory = css.logical.PropertyCategory.default(),
|
|
|
|
pub fn handleProperty(
|
|
this: *@This(),
|
|
property: *const Property,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) bool {
|
|
switch (@as(PropertyIdTag, property.*)) {
|
|
top_prop => this.propertyHelper("top", top_prop.valueType(), &@field(property, @tagName(top_prop)), PropertyCategory.physical, dest, context),
|
|
bottom_prop => this.propertyHelper("bottom", bottom_prop.valueType(), &@field(property, @tagName(bottom_prop)), PropertyCategory.physical, dest, context),
|
|
left_prop => this.propertyHelper("left", left_prop.valueType(), &@field(property, @tagName(left_prop)), PropertyCategory.physical, dest, context),
|
|
right_prop => this.propertyHelper("right", right_prop.valueType(), &@field(property, @tagName(right_prop)), PropertyCategory.physical, dest, context),
|
|
block_start_prop => {
|
|
this.flushHelper("block_start", block_start_prop.valueType(), &@field(property, @tagName(block_start_prop)), PropertyCategory.logical, dest, context);
|
|
this.logicalPropertyHelper("block_start", property.deepClone(context.allocator), dest, context);
|
|
},
|
|
block_end_prop => {
|
|
this.flushHelper("block_end", block_end_prop.valueType(), &@field(property, @tagName(block_end_prop)), PropertyCategory.logical, dest, context);
|
|
this.logicalPropertyHelper("block_end", property.deepClone(context.allocator), dest, context);
|
|
},
|
|
inline_start_prop => {
|
|
this.flushHelper("inline_start", inline_start_prop.valueType(), &@field(property, @tagName(inline_start_prop)), PropertyCategory.logical, dest, context);
|
|
this.logicalPropertyHelper("inline_start", property.deepClone(context.allocator), dest, context);
|
|
},
|
|
inline_end_prop => {
|
|
this.flushHelper("inline_end", inline_end_prop.valueType(), &@field(property, @tagName(inline_end_prop)), PropertyCategory.logical, dest, context);
|
|
this.logicalPropertyHelper("inline_end", property.deepClone(context.allocator), dest, context);
|
|
},
|
|
block_shorthand => {
|
|
const val = &@field(property, @tagName(block_shorthand));
|
|
this.flushHelper("block_start", block_start_prop.valueType(), &val.block_start, .logical, dest, context);
|
|
this.flushHelper("block_end", block_end_prop.valueType(), &val.block_end, .logical, dest, context);
|
|
this.logicalPropertyHelper("block_start", @unionInit(Property, @tagName(block_start_prop), val.block_start.deepClone(context.allocator)), dest, context);
|
|
this.logicalPropertyHelper("block_end", @unionInit(Property, @tagName(block_end_prop), val.block_end.deepClone(context.allocator)), dest, context);
|
|
},
|
|
inline_shorthand => {
|
|
const val = &@field(property, @tagName(inline_shorthand));
|
|
this.flushHelper("inline_start", inline_start_prop.valueType(), &val.inline_start, .logical, dest, context);
|
|
this.flushHelper("inline_end", inline_end_prop.valueType(), &val.inline_end, .logical, dest, context);
|
|
this.logicalPropertyHelper("inline_start", @unionInit(Property, @tagName(inline_start_prop), val.inline_start.deepClone(context.allocator)), dest, context);
|
|
this.logicalPropertyHelper("inline_end", @unionInit(Property, @tagName(inline_end_prop), val.inline_end.deepClone(context.allocator)), dest, context);
|
|
},
|
|
shorthand_prop => {
|
|
const val = &@field(property, @tagName(shorthand_prop));
|
|
this.flushHelper("top", top_prop.valueType(), &val.top, shorthand_category, dest, context);
|
|
this.flushHelper("right", right_prop.valueType(), &val.right, shorthand_category, dest, context);
|
|
this.flushHelper("bottom", bottom_prop.valueType(), &val.bottom, shorthand_category, dest, context);
|
|
this.flushHelper("left", left_prop.valueType(), &val.left, shorthand_category, dest, context);
|
|
this.top = val.top.deepClone(context.allocator);
|
|
this.right = val.right.deepClone(context.allocator);
|
|
this.bottom = val.bottom.deepClone(context.allocator);
|
|
this.left = val.left.deepClone(context.allocator);
|
|
this.block_start = null;
|
|
this.block_end = null;
|
|
this.inline_start = null;
|
|
this.inline_end = null;
|
|
this.has_any = true;
|
|
},
|
|
css.PropertyIdTag.unparsed => {
|
|
switch (property.unparsed.property_id) {
|
|
top_prop, bottom_prop, left_prop, right_prop, block_start_prop, block_end_prop, inline_start_prop, inline_end_prop, block_shorthand, inline_shorthand, shorthand_prop => {
|
|
// Even if we weren't able to parse the value (e.g. due to var() references),
|
|
// we can still add vendor prefixes to the property itself.
|
|
switch (property.unparsed.property_id) {
|
|
block_start_prop => this.logicalPropertyHelper("block_start", property.deepClone(context.allocator), dest, context),
|
|
block_end_prop => this.logicalPropertyHelper("block_end", property.deepClone(context.allocator), dest, context),
|
|
inline_start_prop => this.logicalPropertyHelper("inline_start", property.deepClone(context.allocator), dest, context),
|
|
inline_end_prop => this.logicalPropertyHelper("inline_end", property.deepClone(context.allocator), dest, context),
|
|
else => {
|
|
this.flush(dest, context);
|
|
dest.append(context.allocator, property.deepClone(context.allocator)) catch unreachable;
|
|
},
|
|
}
|
|
},
|
|
else => return false,
|
|
}
|
|
},
|
|
else => return false,
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
pub fn finalize(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void {
|
|
this.flush(dest, context);
|
|
}
|
|
|
|
fn flushHelper(
|
|
this: *@This(),
|
|
comptime field: []const u8,
|
|
comptime T: type,
|
|
val: *const T,
|
|
comptime category: PropertyCategory,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
// If the category changes betweet logical and physical,
|
|
// or if the value contains syntax that isn't supported across all targets,
|
|
// preserve the previous value as a fallback.
|
|
if (category != this.category or (@field(this, field) != null and context.targets.browsers != null and !val.isCompatible(context.targets.browsers.?))) {
|
|
this.flush(dest, context);
|
|
}
|
|
}
|
|
|
|
fn propertyHelper(
|
|
this: *@This(),
|
|
comptime field: []const u8,
|
|
comptime T: type,
|
|
val: *const T,
|
|
comptime category: PropertyCategory,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
this.flushHelper(field, T, val, category, dest, context);
|
|
@field(this, field) = val.deepClone(context.allocator);
|
|
this.category = category;
|
|
this.has_any = true;
|
|
}
|
|
|
|
fn logicalPropertyHelper(
|
|
this: *@This(),
|
|
comptime field: []const u8,
|
|
val: css.Property,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
// Assume unparsed properties might contain unsupported syntax that we must preserve as a fallback.
|
|
if (this.category != PropertyCategory.logical or (@field(this, field) != null and val == .unparsed)) {
|
|
this.flush(dest, context);
|
|
}
|
|
|
|
if (@field(this, field)) |*p| p.deinit(context.allocator);
|
|
@field(this, field) = val;
|
|
this.category = PropertyCategory.logical;
|
|
this.has_any = true;
|
|
}
|
|
|
|
fn flush(this: *@This(), dest: *css.DeclarationList, context: *css.PropertyHandlerContext) void {
|
|
if (!this.has_any) return;
|
|
|
|
this.has_any = false;
|
|
|
|
const top = bun.take(&this.top);
|
|
const bottom = bun.take(&this.bottom);
|
|
const left = bun.take(&this.left);
|
|
const right = bun.take(&this.right);
|
|
const logical_supported = if (comptime shorthand_extra != null) !context.shouldCompileLogical(shorthand_extra.?.feature) else true;
|
|
|
|
if ((shorthand_category != .logical or logical_supported) and top != null and bottom != null and left != null and right != null) {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(
|
|
Property,
|
|
@tagName(shorthand_prop),
|
|
.{
|
|
.top = top.?,
|
|
.bottom = bottom.?,
|
|
.left = left.?,
|
|
.right = right.?,
|
|
},
|
|
),
|
|
) catch |err| bun.handleOom(err);
|
|
} else {
|
|
if (top) |t| {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(Property, @tagName(top_prop), t),
|
|
) catch |err| bun.handleOom(err);
|
|
}
|
|
|
|
if (bottom) |b| {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(Property, @tagName(bottom_prop), b),
|
|
) catch |err| bun.handleOom(err);
|
|
}
|
|
|
|
if (left) |b| {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(Property, @tagName(left_prop), b),
|
|
) catch |err| bun.handleOom(err);
|
|
}
|
|
|
|
if (right) |b| {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(Property, @tagName(right_prop), b),
|
|
) catch |err| bun.handleOom(err);
|
|
}
|
|
}
|
|
|
|
var block_start = bun.take(&this.block_start);
|
|
var block_end = bun.take(&this.block_end);
|
|
var inline_start = bun.take(&this.inline_start);
|
|
var inline_end = bun.take(&this.inline_end);
|
|
|
|
if (logical_supported) {
|
|
this.logicalSideHelper(&block_start, &block_end, "block_start", "block_end", block_shorthand, block_start_prop, block_end_prop, logical_supported, dest, context);
|
|
} else {
|
|
this.prop(&block_start, block_start_prop, top_prop, dest, context);
|
|
this.prop(&block_end, block_end_prop, bottom_prop, dest, context);
|
|
}
|
|
|
|
if (logical_supported) {
|
|
this.logicalSideHelper(&inline_start, &inline_end, "inline_start", "inline_end", inline_shorthand, inline_start_prop, inline_end_prop, logical_supported, dest, context);
|
|
} else if (inline_start != null or inline_end != null) {
|
|
if (inline_start != null and inline_start.? == @field(Property, @tagName(inline_start_prop)) and inline_end != null and inline_end.? == @field(Property, @tagName(inline_end_prop)) and
|
|
@field(inline_start.?, @tagName(inline_start_prop)).eql(&@field(inline_end.?, @tagName(inline_end_prop))))
|
|
{
|
|
this.prop(&inline_start, inline_start_prop, left_prop, dest, context);
|
|
this.prop(&inline_end, inline_end_prop, right_prop, dest, context);
|
|
} else {
|
|
this.logicalPropHelper(&inline_start, inline_start_prop, left_prop, right_prop, dest, context);
|
|
this.logicalPropHelper(&inline_end, inline_end_prop, right_prop, left_prop, dest, context);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline fn logicalPropHelper(
|
|
this: *@This(),
|
|
val: *?Property,
|
|
comptime logical: css.PropertyIdTag,
|
|
comptime ltr: css.PropertyIdTag,
|
|
comptime rtl: css.PropertyIdTag,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
_ = this; // autofix
|
|
_ = dest; // autofix
|
|
if (val.*) |*_v| {
|
|
if (@as(css.PropertyIdTag, _v.*) == logical) {
|
|
const v = &@field(_v, @tagName(logical));
|
|
context.addLogicalRule(
|
|
context.allocator,
|
|
@unionInit(Property, @tagName(ltr), v.deepClone(context.allocator)),
|
|
@unionInit(Property, @tagName(rtl), v.deepClone(context.allocator)),
|
|
);
|
|
} else if (_v.* == .unparsed) {
|
|
const v = &_v.unparsed;
|
|
context.addLogicalRule(
|
|
context.allocator,
|
|
Property{
|
|
.unparsed = v.withPropertyId(context.allocator, ltr),
|
|
},
|
|
Property{
|
|
.unparsed = v.withPropertyId(context.allocator, rtl),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline fn logicalSideHelper(
|
|
this: *@This(),
|
|
start: *?Property,
|
|
end: *?Property,
|
|
comptime start_name: []const u8,
|
|
comptime end_name: []const u8,
|
|
comptime shorthand_property: css.PropertyIdTag,
|
|
comptime start_prop: css.PropertyIdTag,
|
|
comptime end_prop: css.PropertyIdTag,
|
|
logical_supported: bool,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
_ = this; // autofix
|
|
const shorthand_supported = logical_supported and if (comptime shorthand_extra != null) !context.shouldCompileLogical(shorthand_extra.?.shorthand_feature) else true;
|
|
|
|
if (start.* != null and @as(PropertyIdTag, start.*.?) == start_prop and
|
|
end.* != null and @as(PropertyIdTag, end.*.?) == end_prop and
|
|
shorthand_supported)
|
|
{
|
|
const ValueType = shorthand_property.valueType();
|
|
var value: ValueType = undefined;
|
|
@field(value, start_name) = @field(start.*.?, @tagName(start_prop)).deepClone(context.allocator);
|
|
@field(value, end_name) = @field(end.*.?, @tagName(end_prop)).deepClone(context.allocator);
|
|
if (std.meta.fields(ValueType).len != 2) {
|
|
@compileError(@typeName(ValueType) ++ " has more than two fields. This could cause undefined memory.");
|
|
}
|
|
|
|
dest.append(context.allocator, @unionInit(
|
|
Property,
|
|
@tagName(shorthand_property),
|
|
value,
|
|
)) catch |err| bun.handleOom(err);
|
|
} else {
|
|
if (start.* != null) {
|
|
bun.handleOom(dest.append(context.allocator, start.*.?));
|
|
}
|
|
if (end.* != null) {
|
|
bun.handleOom(dest.append(context.allocator, end.*.?));
|
|
}
|
|
}
|
|
}
|
|
|
|
inline fn prop(
|
|
this: *@This(),
|
|
val: *?Property,
|
|
comptime logical: css.PropertyIdTag,
|
|
comptime physical: css.PropertyIdTag,
|
|
dest: *css.DeclarationList,
|
|
context: *css.PropertyHandlerContext,
|
|
) void {
|
|
_ = this; // autofix
|
|
if (val.*) |*v| {
|
|
if (@as(css.PropertyIdTag, v.*) == logical) {
|
|
dest.append(
|
|
context.allocator,
|
|
@unionInit(
|
|
Property,
|
|
@tagName(physical),
|
|
@field(v, @tagName(logical)),
|
|
),
|
|
) catch |err| bun.handleOom(err);
|
|
} else if (v.* == .unparsed) {
|
|
dest.append(
|
|
context.allocator,
|
|
Property{
|
|
.unparsed = v.unparsed.withPropertyId(context.allocator, physical),
|
|
},
|
|
) catch |err| bun.handleOom(err);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
const bun = @import("bun");
|
|
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|