Skip to main content

float_pigment_css/
property.rs

1#![allow(
2    clippy::unused_unit,
3    clippy::needless_question_mark,
4    clippy::type_complexity
5)]
6
7//! The list of supported CSS properties.
8
9use alloc::{
10    string::{String, ToString},
11    vec::Vec,
12};
13
14use cssparser::{ParseError, Parser, SourcePosition};
15
16use super::parser::{property_value::*, CustomError, ParseState};
17use super::resolve_font_size::ResolveFontSize;
18use super::sheet::borrow::Array;
19pub use super::sheet::{str_store::StrRef, PropertyMeta};
20use super::typing::*;
21use float_pigment_css_macro::*;
22
23property_list! (PropertyValueWithGlobal, {
24    // basic positioning
25    0x01 Display: DisplayType as Initial default Display::Inline;
26    0x02 Position: PositionType as Initial default Position::Static;
27    0x03 OverflowX: OverflowType as Initial default Overflow::Visible;
28    0x04 OverflowY: OverflowType as Initial default Overflow::Visible;
29    0x05 PointerEvents: PointerEventsType as Inherit default PointerEvents::Auto;
30    0x06 WxEngineTouchEvent: WxEngineTouchEventType as Inherit default WxEngineTouchEvent::Gesture;
31    0x07 WxPartialZIndex: NumberType as Initial default Number::F32(0.);
32    0x08 BoxSizing: BoxSizingType as Initial default BoxSizing::ContentBox;
33    0x09 Transform: TransformType as Initial default Transform::Series(Array::empty());
34    0x0a WxLineClamp: NumberType as Initial default Number::F32(0.);
35    0x0b Float: FloatType as Initial default Float::None;
36    0x0c OverflowWrap: OverflowWrapType as Inherit default OverflowWrap::Normal;
37    0x0d Resize: ResizeType as Initial default Resize::None;
38    0x0e ZIndex: ZIndexType as Initial default ZIndex::Auto;
39    0x0f WxPointerEventRoot: PointerEventsType as Initial default PointerEvents::None;
40
41    // color and visibility related
42    0x10 Visibility: VisibilityType as Inherit default Visibility::Visible;
43    0x11 Color: ColorType as Inherit default Color::Specified(0, 0, 0, 255);
44    0x12 Opacity: NumberType as Initial default Number::F32(1.);
45    0x13 CaretColor: ColorType as Inherit default Color::Undefined;
46
47    // flex
48    0x20 FlexDirection: FlexDirectionType as Initial default FlexDirection::Row;
49    0x21 FlexWrap: FlexWrapType as Initial default FlexWrap::NoWrap;
50    0x22 AlignItems: AlignItemsType as Initial default AlignItems::Stretch;
51    0x23 AlignSelf: AlignSelfType as Initial default AlignSelf::Auto;
52    0x24 AlignContent: AlignContentType as Initial default AlignContent::Stretch;
53    0x25 JustifyContent: JustifyContentType as Initial default JustifyContent::Normal;
54    0x26 FlexGrow: NumberType as Initial default Number::F32(0.);
55    0x27 FlexShrink: NumberType as Initial default Number::F32(1.);
56    0x28 FlexBasis: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em;
57    0x29 JustifyItems: JustifyItemsType as Initial default JustifyItems::Stretch;
58    0x2a Order: NumberType as Initial default Number::I32(0);
59    0x2b RowGap: GapType as Initial default Gap::Normal;
60    0x2c ColumnGap: GapType as Initial default Gap::Normal;
61
62    // background
63    0x30 BackgroundColor: ColorType as Initial default Color::Specified(0, 0, 0, 0);
64    0x31 BackgroundImage: BackgroundImageType as Initial default BackgroundImage::List(Array::empty());
65    0x32 BackgroundSize: BackgroundSizeType as Initial default BackgroundSize::List(vec![BackgroundSizeItem::Auto].into());
66    0x33 BackgroundPosition: BackgroundPositionType as Initial deprecated default BackgroundPosition::List(vec![BackgroundPositionItem::Pos(BackgroundPositionValue::Left(Length::Ratio(0.)), BackgroundPositionValue::Top(Length::Ratio(0.)))].into());
67    0x34 BackgroundRepeat: BackgroundRepeatType as Initial default BackgroundRepeat::List(vec![BackgroundRepeatItem::Pos(BackgroundRepeatValue::Repeat, BackgroundRepeatValue::Repeat)].into());
68    0x35 BackgroundAttachment: BackgroundAttachmentType as Initial default BackgroundAttachment::List(vec![BackgroundAttachmentItem::Scroll].into());
69    0x36 BackgroundClip: BackgroundClipType as Initial default BackgroundClip::List(vec![BackgroundClipItem::BorderBox].into());
70    0x37 BackgroundOrigin: BackgroundOriginType as Initial default BackgroundOrigin::List(vec![BackgroundOriginItem::PaddingBox].into());
71    0x38 BackgroundPositionX: BackgroundPositionType as Initial default BackgroundPosition::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.)))].into());
72    0x39 BackgroundPositionY: BackgroundPositionType as Initial default BackgroundPosition::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.)))].into());
73
74    // mask-*
75    0x3a MaskSize: BackgroundSizeType as Initial default BackgroundSize::List(vec![BackgroundSizeItem::Auto].into());
76    0x3b MaskRepeat: BackgroundRepeatType as Initial default BackgroundRepeat::List(vec![BackgroundRepeatItem::Pos(BackgroundRepeatValue::NoRepeat, BackgroundRepeatValue::NoRepeat)].into());
77    0x3c MaskOrigin: BackgroundOriginType as Initial default BackgroundOrigin::List(vec![BackgroundOriginItem::BorderBox].into());
78    0x3d MaskClip: BackgroundClipType as Initial default BackgroundClip::List(vec![BackgroundClipItem::BorderBox].into());
79    0x3e MaskPosition: BackgroundPositionType as Initial deprecated default BackgroundPosition::List(vec![BackgroundPositionItem::Pos(BackgroundPositionValue::Left(Length::Ratio(0.5)), BackgroundPositionValue::Top(Length::Ratio(0.5)))].into());
80    0x3f MaskMode: MaskModeType as Initial default MaskMode::List(vec![MaskModeItem::MatchSource].into());
81
82    // basic sizing
83    0x40 Width: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
84    0x41 Height: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
85    0x42 MinWidth: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
86    0x43 MinHeight: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
87    0x44 MaxWidth: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em;
88    0x45 MaxHeight: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em;
89    0x46 Left: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
90    0x47 Right: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
91    0x48 Top: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
92    0x49 Bottom: LengthType as Initial default Length::Auto, resolver = Length::resolve_em;
93
94    // padding and margin
95    0x50 PaddingLeft: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
96    0x51 PaddingRight: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
97    0x52 PaddingTop: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
98    0x53 PaddingBottom: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
99    0x54 MarginLeft: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
100    0x55 MarginRight: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
101    0x56 MarginTop: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
102    0x57 MarginBottom: LengthType as Initial default Length::Px(0.), resolver = Length::resolve_em;
103
104    // other
105    0x58 MaskPositionX: BackgroundPositionType as Initial default BackgroundPosition::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.)))].into());
106    0x59 MaskPositionY: BackgroundPositionType as Initial default BackgroundPosition::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.)))].into());
107
108    // border
109    0x60 BorderLeftWidth: LengthType as Initial default Length::Px(3.), resolver = Length::resolve_em;
110    0x61 BorderLeftStyle: BorderStyleType as Initial default BorderStyle::None;
111    0x62 BorderLeftColor: ColorType as Initial default Color::CurrentColor;
112    0x63 BorderRightWidth: LengthType as Initial default Length::Px(3.), resolver = Length::resolve_em;
113    0x64 BorderRightStyle: BorderStyleType as Initial default BorderStyle::None;
114    0x65 BorderRightColor: ColorType as Initial default Color::CurrentColor;
115    0x66 BorderTopWidth: LengthType as Initial default Length::Px(3.), resolver = Length::resolve_em;
116    0x67 BorderTopStyle: BorderStyleType as Initial default BorderStyle::None;
117    0x68 BorderTopColor: ColorType as Initial default Color::CurrentColor;
118    0x69 BorderBottomWidth: LengthType as Initial default Length::Px(3.), resolver = Length::resolve_em;
119    0x6a BorderBottomStyle: BorderStyleType as Initial default BorderStyle::None;
120    0x6b BorderBottomColor: ColorType as Initial default Color::CurrentColor;
121    0x6c BoxShadow: BoxShadowType as Initial default BoxShadow::None;
122
123    // border radius
124    0x70 BorderTopLeftRadius: BorderRadiusType as Initial default BorderRadius::Pos(Length::Px(0.), Length::Px(0.));
125    0x71 BorderTopRightRadius: BorderRadiusType as Initial default BorderRadius::Pos(Length::Px(0.), Length::Px(0.));
126    0x72 BorderBottomRightRadius: BorderRadiusType as Initial default BorderRadius::Pos(Length::Px(0.), Length::Px(0.));
127    0x73 BorderBottomLeftRadius: BorderRadiusType as Initial default BorderRadius::Pos(Length::Px(0.), Length::Px(0.));
128
129    // transition
130    0x80 TransitionProperty: TransitionPropertyType as Initial default TransitionProperty::List(Array::empty());
131    0x81 TransitionDuration: TransitionTimeType as Initial default TransitionTime::List(Array::empty());
132    0x82 TransitionTimingFunction: TransitionTimingFnType as Initial default TransitionTimingFn::List(Array::empty());
133    0x83 TransitionDelay: TransitionTimeType as Initial default TransitionTime::ListI32(Array::empty());
134
135    // animation
136    0x84 AnimationDuration: TransitionTimeType as Initial default TransitionTime::List(Array::empty());
137    0x85 AnimationTimingFunction: TransitionTimingFnType as Initial default TransitionTimingFn::List(Array::empty());
138    0x86 AnimationDelay: TransitionTimeType as Initial default TransitionTime::ListI32(Array::empty());
139    0x87 AnimationIterationCount: AnimationIterationCountType as Initial default AnimationIterationCount::List(Array::empty());
140    0x88 AnimationDirection: AnimationDirectionType as Initial default AnimationDirection::List(Array::empty());
141    0x89 AnimationFillMode: AnimationFillModeType as Initial default AnimationFillMode::List(Array::empty());
142    0x8a AnimationPlayState: AnimationPlayStateType as Initial default AnimationPlayState::List(Array::empty());
143    0x8b AnimationName: AnimationNameType as Initial default AnimationName::List(Array::empty());
144    0x8c WillChange: WillChangeType as Initial default WillChange::Auto;
145
146    // typography
147    0x90 FontSize: LengthType as Inherit default Length::Undefined, resolver = Length::resolve_set;
148    0x91 Direction: DirectionType as Inherit default Direction::Auto;
149    0x92 WritingMode: WritingModeType as Inherit default WritingMode::HorizontalTb;
150    0x93 LineHeight: LineHeightType as Inherit default LineHeight::Normal;
151    0x94 TextAlign: TextAlignType as Inherit default TextAlign::Start;
152    0x95 FontWeight: FontWeightType as Inherit default FontWeight::Normal;
153    0x96 WordBreak: WordBreakType as Inherit default WordBreak::BreakWord;
154    0x97 WhiteSpace: WhiteSpaceType as Inherit default WhiteSpace::Normal;
155    0x98 TextOverflow: TextOverflowType as Inherit default TextOverflow::Clip;
156    0x99 TextIndent: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em_and_ratio;
157    0x9a VerticalAlign: VerticalAlignType as Initial default VerticalAlign::Baseline;
158    0x9b LetterSpacing: LetterSpacingType as Inherit default LetterSpacing::Normal;
159    0x9c WordSpacing: WordSpacingType as Inherit default WordSpacing::Normal;
160    0x9d FontFamily: FontFamilyType as Inherit default FontFamily::Names(Array::empty());
161    0x9e FontStyle: FontStyleType as Inherit default FontStyle::Normal;
162    0x9f TextShadow: TextShadowType as Inherit default TextShadow::None;
163    0xa0 TextDecorationLine: TextDecorationLineType as Initial default TextDecorationLine::None;
164    0xa1 TextDecorationStyle: TextDecorationStyleType as Initial default TextDecorationStyle::Solid;
165    0xa2 TextDecorationColor: ColorType as Initial default Color::CurrentColor;
166    0xa3 TextDecorationThickness: TextDecorationThicknessType as Initial default TextDecorationThickness::Auto;
167    0xa4 FontFeatureSettings: FontFeatureSettingsType as Inherit default FontFeatureSettings::Normal;
168
169    // grid
170    0xa5 GridTemplateRows: GridTemplateType as Initial default GridTemplate::None;
171    0xa6 GridTemplateColumns: GridTemplateType as Initial default GridTemplate::None;
172    0xa7 GridAutoFlow: GridAutoFlowType as Initial default GridAutoFlow::Row;
173    0xa8 JustifySelf: JustifySelfType as Initial default JustifySelf::Auto;
174    0xa9 GridAutoRows: GridAutoType as Initial default GridAuto::List(vec![TrackSize::Length(Length::Auto)].into());
175    0xaa GridAutoColumns: GridAutoType as Initial default GridAuto::List(vec![TrackSize::Length(Length::Auto)].into());
176
177    // misc
178    0xd0 ListStyleType: ListStyleTypeType as Inherit default ListStyleType::Disc;
179    0xd1 ListStyleImage: ListStyleImageType as Inherit default ListStyleImage::None;
180    0xd2 ListStylePosition: ListStylePositionType as Inherit default ListStylePosition::Outside;
181    0xd3 BackdropFilter: BackdropFilterType as Initial default BackdropFilter::None;
182    0xd4 Filter: FilterType as Initial default Filter::None;
183    0xd5 TransformOrigin: TransformOriginType as Initial default TransformOrigin::LengthTuple(Length::Ratio(0.5), Length::Ratio(0.5), Length::Px(0.));
184    0xd6 MaskImage: BackgroundImageType as Initial default BackgroundImage::List(Array::empty());
185    0xd7 AspectRatio: AspectRatioType as Initial default AspectRatio::Auto;
186    0xd8 Contain: ContainType as Initial default Contain::None;
187    0xd9 Content: ContentType as Initial default Content::None;
188    0xda TouchAction: TouchActionType as Initial default TouchAction::Auto;
189
190    // wx-spec special properties
191    0xe0 WxScrollbarX: ScrollbarType as Initial default Scrollbar::Auto;
192    0xe1 WxScrollbarXColor: ColorType as Initial default Color::Undefined;
193    0xe2 WxScrollbarY: ScrollbarType as Initial default Scrollbar::Auto;
194    0xe3 WxScrollbarYColor: ColorType as Initial default Color::Undefined;
195    0xe4 WxContain: ContainType as Initial default Contain::None;
196
197    0xfa CustomProperty: CustomPropertyType as Initial default CustomProperty::None;
198    // considering bincode performance, the max value should be 0xfa
199});
200
201property_value_format! (PropertyValueWithGlobal, {
202    display: {{ Display
203        = "none" => DisplayType::None
204        | "block" => DisplayType::Block
205        | "inline" => DisplayType::Inline
206        | "inline-block" => DisplayType::InlineBlock
207        | "flex" => DisplayType::Flex
208        | "grid" => DisplayType::Grid
209        | "flow-root" => DisplayType::FlowRoot
210        | "inline-flex" => DisplayType::InlineFlex
211        | "inline-grid" => DisplayType::InlineGrid
212    }};
213    position: {{ Position
214        = "static" => PositionType::Static
215        | "relative" => PositionType::Relative
216        | "absolute" => PositionType::Absolute
217        | "fixed" => PositionType::Fixed
218        | "sticky" => PositionType::Sticky
219    }};
220    float: {{ Float
221        = "none" => FloatType::None
222        | "left" => FloatType::Left
223        | "right" => FloatType::Right
224        | "inline-start" => FloatType::InlineStart
225        | "inline-end" => FloatType::InlineEnd
226    }};
227    overflow_x: {{ OverflowX
228        = "visible" => OverflowType::Visible
229        | "hidden" => OverflowType::Hidden
230        | "auto" => OverflowType::Auto
231        | "scroll" => OverflowType::Scroll
232    }};
233    overflow_y: {{ OverflowY
234        = "visible" => OverflowType::Visible
235        | "hidden" => OverflowType::Hidden
236        | "auto" => OverflowType::Auto
237        | "scroll" => OverflowType::Scroll
238    }};
239    overflow: {{ (OverflowX, OverflowY)
240        = [
241            "visible" => OverflowType::Visible
242            | "hidden" => OverflowType::Hidden
243            | "auto" => OverflowType::Auto
244            | "scroll" => OverflowType::Scroll
245        ]{1, 2} -> split_hv
246    }};
247    overflow_wrap: {{ OverflowWrap
248        = "normal" => OverflowWrapType::Normal
249        | "break-word" => OverflowWrapType::BreakWord
250    }};
251    pointer_events: {{ PointerEvents
252        = "auto" => PointerEventsType::Auto
253        | "none" => PointerEventsType::None
254    }};
255    _wx_pointer_event_root: {{ WxPointerEventRoot
256        = "auto" => PointerEventsType::Auto
257        | "root" => PointerEventsType::WxRoot
258    }};
259    _wx_engine_touch_event: {{ WxEngineTouchEvent
260        = "gesture" => WxEngineTouchEventType::Gesture
261        | "click" => WxEngineTouchEventType::Click
262        | "none" => WxEngineTouchEventType::None
263    }};
264    visibility: {{ Visibility
265        = "visible" => VisibilityType::Visible
266        | "hidden" => VisibilityType::Hidden
267        | "collapse" => VisibilityType::Collapse
268    }};
269    flex_direction: {{ FlexDirection
270        ="row" => FlexDirection::Row
271        | "row-reverse" => FlexDirection::RowReverse
272        | "column" => FlexDirection::Column
273        | "column-reverse" => FlexDirection::ColumnReverse
274    }};
275    flex_wrap: {{ FlexWrap
276        =  "nowrap" => FlexWrap::NoWrap
277        | "wrap" => FlexWrap::Wrap
278        | "wrap-reverse" => FlexWrap::WrapReverse
279    }};
280    align_items: {{ AlignItems
281        = "stretch" => AlignItems::Stretch
282        | "center" => AlignItems::Center
283        | "flex-start" => AlignItems::FlexStart
284        | "flex-end" => AlignItems::FlexEnd
285        | "baseline" => AlignItems::Baseline
286        | "normal" => AlignItems::Normal
287        | "start" => AlignItems::Start
288        | "end" => AlignItems::End
289        | "self-start" => AlignItems::SelfStart
290        | "self-end" => AlignItems::SelfEnd
291    }};
292    align_self: {{ AlignSelf
293        = "auto" => AlignSelf::Auto
294        | "stretch" => AlignSelf::Stretch
295        | "center" => AlignSelf::Center
296        | "flex-start" => AlignSelf::FlexStart
297        | "flex-end" => AlignSelf::FlexEnd
298        | "baseline" => AlignSelf::Baseline
299        | "start" => AlignSelf::Start
300        | "end" => AlignSelf::End
301        | "self-start" => AlignSelf::SelfStart
302        | "self-end" => AlignSelf::SelfEnd
303        | "normal" => AlignSelf::Normal
304    }};
305    align_content: {{ AlignContent
306        = "stretch" => AlignContent::Stretch
307        | "center" => AlignContent::Center
308        | "flex-start" => AlignContent::FlexStart
309        | "flex-end" => AlignContent::FlexEnd
310        | "space-between" => AlignContent::SpaceBetween
311        | "space-around" => AlignContent::SpaceAround
312        | "normal" => AlignContent::Normal
313        | "start" => AlignContent::Start
314        | "end" => AlignContent::End
315        | "space-evenly" => AlignContent::SpaceEvenly
316        | "baseline" => AlignContent::Baseline
317    }};
318
319    justify_content: {{ JustifyContent
320        = "normal" => JustifyContent::Normal
321        | "center" => JustifyContent::Center
322        | "flex-start" => JustifyContent::FlexStart
323        | "flex-end" => JustifyContent::FlexEnd
324        | "space-between" => JustifyContent::SpaceBetween
325        | "space-around" => JustifyContent::SpaceAround
326        | "space-evenly" => JustifyContent::SpaceEvenly
327        | "start" => JustifyContent::Start
328        | "end" => JustifyContent::End
329        | "left" => JustifyContent::Left
330        | "right" => JustifyContent::Right
331        | "baseline" => JustifyContent::Baseline
332        | "stretch" => JustifyContent::Stretch
333    }};
334    justify_items: {{JustifyItems
335        = "stretch" => JustifyItems::Stretch
336        | "center" => JustifyItems::Center
337        | "flex-start" => JustifyItems::FlexStart
338        | "flex-end" => JustifyItems::FlexEnd
339        | "start" => JustifyItems::Start
340        | "end" => JustifyItems::End
341        | "self-start" => JustifyItems::SelfStart
342        | "self-end" => JustifyItems::SelfEnd
343        | "left" => JustifyItems::Left
344        | "right" => JustifyItems::Right
345        | "normal" => JustifyItems::Normal
346    }};
347    justify_self: {{JustifySelf
348        = "auto" => JustifySelf::Auto
349        | "normal" => JustifySelf::Normal
350        | "stretch" => JustifySelf::Stretch
351        | "center" => JustifySelf::Center
352        | "flex-start" => JustifySelf::FlexStart
353        | "flex-end" => JustifySelf::FlexEnd
354        | "start" => JustifySelf::Start
355        | "end" => JustifySelf::End
356        | "self-start" => JustifySelf::SelfStart
357        | "self-end" => JustifySelf::SelfEnd
358        | "left" => JustifySelf::Left
359        | "right" => JustifySelf::Right
360    }};
361    order: {{ Order = <number> -> |x: Number| Number::I32(x.to_i32()); }};
362    <gap_repr: Gap>:
363        "normal" => Gap::Normal
364        | <non_negative_length_percentage> -> |length| Gap::Length(length);
365    ;
366    column_gap: {{ ColumnGap = <gap_repr> }};
367    row_gap: {{ RowGap = <gap_repr> }};
368    gap: {{ (RowGap, ColumnGap)
369        = [ <gap_repr> <gap_repr>? ] -> |(row_gap, column_gap): (Gap, Option<Gap>)| {
370            if let Some(column_gap) = column_gap {
371                return (row_gap, column_gap);
372            }
373            (row_gap.clone(), row_gap)
374        };
375    }};
376    flex_grow: {{ FlexGrow = <number> }};
377    flex_shrink: {{ FlexShrink = <number> }};
378    flex_basis: {{ FlexBasis = <length_percentage_auto> }};
379    flex_flow: <flex_direction> || <flex_wrap>;
380    flex: {{ (FlexGrow, FlexShrink, FlexBasis)
381        = "auto" -> |_| (Number::F32(1.), Number::F32(1.), Length::Auto);
382        | "none" -> |_| (Number::F32(0.), Number::F32(0.), Length::Auto);
383        | [ <number> <number>? || <length_percentage_auto> ] -> |(gs, b): (Option<(Number, Option<Number>)>, Option<Length>)| -> _ {
384            let (g, s) = gs.unwrap_or((Number::F32(0.), None));
385            let s = s.unwrap_or(Number::F32(1.));
386            let b = b.unwrap_or(Length::Ratio(0.));
387            (g, s, b)
388        };
389    }};
390
391    direction: {{ Direction
392        = "ltr" => Direction::LTR
393        | "rtl" => Direction::RTL
394    }};
395    writing_mode: {{ WritingMode
396        = "horizontal-tb" => WritingMode::HorizontalTb
397        | "vertical-lr" => WritingMode::VerticalLr
398        | "vertical-rl" => WritingMode::VerticalRl
399    }};
400
401    color: {{ Color = <color_repr> }};
402    caret_color: {{ CaretColor = <color_repr> }};
403    opacity: {{ Opacity = <number> }};
404    z_index: {{ ZIndex
405        =  "auto" => ZIndexType::Auto
406        | <number> -> |x: Number| ZIndexType::Num(Number::I32(x.to_i32()));
407    }};
408    _wx_partial_z_index: {{ WxPartialZIndex = <number> }};
409    font_size: {{ FontSize = <non_negative_length_percentage> }};
410    <line_height_repr: LineHeightType>:
411        "normal" => LineHeightType::Normal
412        | <non_negative_number> -> |x: Number| LineHeightType::Num(x);
413        | <non_negative_length_percentage> -> |x: Length| LineHeightType::Length(x);
414    ;
415    line_height: {{ LineHeight = <line_height_repr> }};
416    text_align: {{ TextAlign
417        = "left" => TextAlignType::Left
418        | "center" => TextAlignType::Center
419        | "right" => TextAlignType::Right
420        | "justify" => TextAlignType::Justify
421        | "justify-all" => TextAlignType::JustifyAll
422        | "start" => TextAlignType::Start
423        | "end" => TextAlignType::End
424        | "match-parent" => TextAlignType::MatchParent
425    }};
426    <font_weight_repr: FontWeightType>:
427        "normal" => FontWeightType::Normal
428        | "bold" => FontWeightType::Bold
429        | "bolder" => FontWeightType::Bolder
430        | "lighter" => FontWeightType::Lighter
431        | <number> -> |x: Number| FontWeightType::Num(x);
432    ;
433    font_weight: {{ FontWeight = <font_weight_repr> }};
434    word_break: {{ WordBreak
435        = "normal" => WordBreakType::BreakWord
436        | "break-word" => WordBreakType::BreakWord
437        | "break-all" => WordBreakType::BreakAll
438        | "keep-all" => WordBreakType::KeepAll
439    }};
440    white_space: {{ WhiteSpace
441        = "normal" => WhiteSpaceType::Normal
442        | "nowrap" => WhiteSpaceType::NoWrap
443        | "pre" => WhiteSpaceType::Pre
444        | "pre-wrap" => WhiteSpaceType::PreWrap
445        | "pre-line" => WhiteSpaceType::PreLine
446        | "-wx-pre-edit" => WhiteSpaceType::WxPreEdit
447    }};
448    text_overflow: {{ TextOverflow
449        = "clip" => TextOverflowType::Clip
450        | "ellipsis" => TextOverflowType::Ellipsis
451    }};
452    text_indent: {{ TextIndent = <length_percentage> }};
453    vertical_align: {{ VerticalAlign
454        = "baseline" => VerticalAlignType::Baseline
455        | "top" => VerticalAlignType::Top
456        | "middle" => VerticalAlignType::Middle
457        | "bottom" => VerticalAlignType::Bottom
458        | "text-top" => VerticalAlignType::TextTop
459        | "text-bottom" => VerticalAlignType::TextBottom
460    }};
461    letter_spacing: {{ LetterSpacing =
462        "normal" => LetterSpacingType::Normal
463        | <length_only> -> |x: Length| LetterSpacingType::Length(x);
464    }};
465    word_spacing: {{ WordSpacing =
466        "normal" => WordSpacingType::Normal
467        | <length_only> -> |x: Length| WordSpacingType::Length(x);
468    }};
469    font_family: {{ FontFamily = <font::font_family_repr> }};
470    <font_style_repr: FontStyleType>:
471        "normal" -> |_| { FontStyleType::Normal };
472        | "italic" -> |_| { FontStyleType::Italic };
473        | ["oblique" <angle>?] -> |x: ((), Option<Angle>)| {
474            let mut angle = Angle::Deg(14.);
475            if let Some(_angle) = x.1 {
476                angle = _angle
477            }
478            FontStyleType::Oblique(angle)
479        };
480    ;
481    font_style: {{ FontStyle = <font_style_repr>}};
482
483    <background_repeat_single: BackgroundRepeatItem>:
484        "repeat-x" -> |_| {
485          BackgroundRepeatItem::Pos(BackgroundRepeatValue::Repeat, BackgroundRepeatValue::NoRepeat)
486        };
487        | "repeat-y" -> |_| {
488          BackgroundRepeatItem::Pos(BackgroundRepeatValue::NoRepeat, BackgroundRepeatValue::Repeat)
489        };
490        | [
491            "no-repeat" => BackgroundRepeatValue::NoRepeat
492            | "repeat" => BackgroundRepeatValue::Repeat
493            | "space" => BackgroundRepeatValue::Space
494            | "round" => BackgroundRepeatValue::Round
495        ]{1, 2} -> split_hv -> |(a, b): (_, _)| {
496            BackgroundRepeatItem::Pos(a, b)
497        };
498    ;
499    <background_position_single: BackgroundPositionItem>:
500        <background::bg_pos_four_value>
501        | <background::bg_pos_three_value>
502        |<background::bg_pos_two_value>
503        | <background::bg_pos_single_value>
504    ;
505    <background_position_single_without_extra_check: BackgroundPositionItem>:
506        <background::bg_pos_four_value>
507        | <background::bg_pos_three_value_without_extra_check>
508        |<background::bg_pos_two_value_without_extra_check>
509        | <background::bg_pos_single_value_without_extra_check>
510    ;
511
512    <background_size_single: BackgroundSizeItem>:
513        "cover" => BackgroundSizeItem::Cover
514        | "contain" => BackgroundSizeItem::Contain
515        | [ <length_percentage_auto> ]{1, 2} -> |v: Vec<_>| {
516            let len = v.len();
517            let mut v = v.into_iter();
518            let a = v.next().unwrap_or(Length::Auto);
519            let b = v.next().unwrap_or_else(|| a.clone());
520            if len == 1 {
521                BackgroundSizeItem::Length(a, Length::Auto)
522            } else {
523                BackgroundSizeItem::Length(a, b)
524            }
525        };
526    ;
527    <background_clip_single: BackgroundClipItem>:
528        "border-box" => BackgroundClipItem::BorderBox
529        | "padding-box" => BackgroundClipItem::PaddingBox
530        | "content-box" => BackgroundClipItem::ContentBox
531        | "text" => BackgroundClipItem::Text
532    ;
533    <background_attachment_single: BackgroundAttachmentItem>:
534        "scroll" => BackgroundAttachmentItem::Scroll
535        | "fixed" => BackgroundAttachmentItem::Fixed
536        | "local" => BackgroundAttachmentItem::Local
537    ;
538    <background_origin_single: BackgroundOriginItem>:
539        "border-box" => BackgroundOriginItem::BorderBox
540        | "padding-box" => BackgroundOriginItem::PaddingBox
541        | "content-box" => BackgroundOriginItem::ContentBox
542    ;
543    <image_single: BackgroundImageItem>:
544        "none" => BackgroundImageItem::None
545        | <image_func_repr>
546        | <url_str> -> |x: String| BackgroundImageItem::Url(x.into());
547        | <gradient::gradient_repr>
548        | <element_func_repr>
549    ;
550    font: {{ (FontSize, FontFamily, FontStyle, FontWeight, LineHeight)
551        = [
552            [ <font_style_repr> || <font_weight_repr> ]? <non_negative_length_percentage> [ '/' <line_height_repr> ]? <font::font_family_repr>
553        ] -> |x: (Option<(Option<FontStyleType>, Option<FontWeightType>)>, Length, Option<((), LineHeightType)>, FontFamilyType)| {
554            let mut font_style = FontStyleType::Normal;
555            let mut font_weight = FontWeightType::Normal;
556            let mut line_height = LineHeightType::Normal;
557            if let Some((style, weight)) = x.0 {
558                if let Some(style) = style {
559                    font_style = style;
560                }
561                if let Some(weight) = weight {
562                    font_weight = weight;
563                }
564            }
565            let font_size = x.1;
566            if let Some(((), lh)) = x.2 {
567                line_height = lh;
568            }
569            let font_family = x.3;
570            (font_size, font_family, font_style, font_weight, line_height)
571        };
572    }};
573    background: {{ (BackgroundColor, BackgroundImage, BackgroundRepeat, BackgroundPosition, BackgroundPositionX, BackgroundPositionY, BackgroundSize, BackgroundAttachment, BackgroundOrigin, BackgroundClip)
574        ="none" -> |_| (
575            Color::Specified(0, 0, 0, 0),
576            BackgroundImageType::List(vec![BackgroundImageItem::None].into()),
577            BackgroundRepeatType::List(vec![BackgroundRepeatItem::Pos(BackgroundRepeatValue::Repeat, BackgroundRepeatValue::Repeat)].into()),
578            BackgroundPositionType::List(vec![BackgroundPositionItem::Pos(BackgroundPositionValue::Left(Length::Ratio(0.)), BackgroundPositionValue::Top(Length::Ratio(0.)))].into()),
579            BackgroundPositionType::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.)))].into()),
580            BackgroundPositionType::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.)))].into()),
581            BackgroundSizeType::List(vec![BackgroundSizeItem::Auto].into()),
582            BackgroundAttachmentType::List(vec![BackgroundAttachmentItem::Scroll].into()),
583            BackgroundOriginType::List(vec![BackgroundOriginItem::PaddingBox].into()),
584            BackgroundClipType::List(vec![BackgroundClipItem::BorderBox].into()),
585        );
586        | [
587            <color_repr>
588            || <image_single>
589            || <background_repeat_single>
590            || [<background_position_single_without_extra_check> [ '/' <background_size_single>]?]
591            || <background_attachment_single>
592            || <background_origin_single>
593            || <background_clip_single>
594        ]# -> ResultClosure |x: Vec<(
595                Option<Color>,
596                Option<_>,
597                Option<_>,
598                Option<(_, Option<(_, _)>)>,
599                Option<BackgroundAttachmentItem>,
600                Option<BackgroundOriginItem>,
601                Option<BackgroundClipItem>
602            )>, parser: &mut Parser<'i, 't> | -> Result<(_, BackgroundImageType, BackgroundRepeatType, BackgroundPositionType, BackgroundPositionType, BackgroundPositionType, BackgroundSizeType, BackgroundAttachmentType, BackgroundOriginType, BackgroundClipType), ParseError<'i, CustomError>> {
603                let mut img = Vec::with_capacity(x.len());
604                let mut rep = Vec::with_capacity(x.len());
605                let mut pos = Vec::with_capacity(x.len());
606                let mut pos_x = Vec::with_capacity(x.len());
607                let mut pos_y = Vec::with_capacity(x.len());
608                let mut size = Vec::with_capacity(x.len());
609                let mut attach = Vec::with_capacity(x.len());
610                let mut origin = Vec::with_capacity(x.len());
611                let mut clip = Vec::with_capacity(x.len());
612                let mut color = Color::Undefined;
613                let len = x.len();
614                for (index, v) in x.into_iter().enumerate() {
615                    if let Some(_color) = v.0 {
616                        if index < len - 1 { Err(parser.new_custom_error::<_, CustomError>(CustomError::Unmatched))?; }
617                        color = _color;
618                    }
619                    match v.1 {
620                        Some(x) => {
621                            img.push(x);
622
623                        }
624                        None => {
625                            img.push(BackgroundImageItem::None);
626                        }
627                    }
628                    match v.2 {
629                        Some(x) => {
630                            rep.push(x);
631                        }
632                        None => {
633                            rep.push(BackgroundRepeatItem::Pos(
634                                BackgroundRepeatValue::Repeat,
635                                BackgroundRepeatValue::Repeat
636                            ));
637                        }
638                    }
639                    match v.3 {
640                        Some(pos_size) => {
641                            let (__pos, __size) = pos_size;
642                            {
643                                if let BackgroundPositionItem::Pos(x, y) = &__pos {
644                                    pos_x.push(BackgroundPositionItem::Value(x.clone()));
645                                    pos_y.push(BackgroundPositionItem::Value(y.clone()));
646                                }
647                            }
648                            pos.push(__pos);
649                            match __size {
650                            Some(s) => {
651                                size.push(s.1);
652                            },
653                            None => {
654                                size.push(BackgroundSizeItem::Auto);
655                            }
656                        }
657                    }
658                        None=> {
659                            pos.push(
660                                BackgroundPositionItem::Pos(
661                                    BackgroundPositionValue::Left(Length::Ratio(0.)),
662                                    BackgroundPositionValue::Top(Length::Ratio(0.))
663                                )
664                            );
665                            pos_x.push(BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.))));
666                            pos_y.push(BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.))));
667                            size.push(BackgroundSizeItem::Auto);
668                        }
669                    }
670                    match v.4 {
671                        Some(__attach) => {
672                            attach.push(__attach);
673                        },
674                        None => {
675                            attach.push(BackgroundAttachmentItem::Scroll);
676                        }
677                    }
678                    if v.5.is_some() && v.6.is_some() {
679                        if let Some(__origin) = v.5 {
680                            origin.push(__origin);
681                        }
682                        if let Some(__clip) = v.6 {
683                            clip.push(__clip);
684                        }
685                    } else if v.5.is_some() || v.6.is_some() {
686                        if let Some(__origin) = v.5 {
687                            origin.push(__origin.clone());
688                            match __origin {
689                                BackgroundOriginItem::PaddingBox => {
690                                    clip.push(BackgroundClipItem::PaddingBox);
691                                },
692                                BackgroundOriginItem::BorderBox => {
693                                    clip.push(BackgroundClipItem::BorderBox);
694                                },
695                                BackgroundOriginItem::ContentBox => {
696                                    clip.push(BackgroundClipItem::ContentBox);
697                                },
698                            };
699                        }
700                        if let Some(__clip) = v.6 {
701                            clip.push(__clip.clone());
702                            match __clip {
703                                BackgroundClipItem::PaddingBox => {
704                                    origin.push(BackgroundOriginItem::PaddingBox);
705                                },
706                                BackgroundClipItem::BorderBox => {
707                                    origin.push(BackgroundOriginItem::BorderBox);
708                                },
709                                BackgroundClipItem::ContentBox => {
710                                    origin.push(BackgroundOriginItem::ContentBox);
711                                },
712                                _ => {},
713                            };
714                        }
715                    } else {
716                        origin.push(BackgroundOriginItem::PaddingBox);
717                        clip.push(BackgroundClipItem::BorderBox);
718                    }
719                }
720                Ok((
721                    color,
722                    BackgroundImageType::List(img.into()),
723                    BackgroundRepeatType::List(rep.into()),
724                    BackgroundPositionType::List(pos.into()),
725                    BackgroundPositionType::List(pos_x.into()),
726                    BackgroundPositionType::List(pos_y.into()),
727                    BackgroundSizeType::List(size.into()),
728                    BackgroundAttachmentType::List(attach.into()),
729                    BackgroundOriginType::List(origin.into()),
730                    BackgroundClipType::List(clip.into()),
731                ))
732        };
733    }};
734    background_color: {{ BackgroundColor = <color_repr> }};
735    background_image: {{ BackgroundImage
736        = [<image_single>]# -> |x: Vec<BackgroundImageItem>| BackgroundImageType::List(x.into());
737    }};
738    background_repeat: {{ BackgroundRepeat
739        = [<background_repeat_single>]# -> |x: Vec<BackgroundRepeatItem>| BackgroundRepeatType::List(x.into());
740    }};
741    background_size: {{ BackgroundSize
742        = [<background_size_single>]# -> |x: Vec<BackgroundSizeItem>| BackgroundSizeType::List(x.into());
743    }};
744    background_attachment: {{ BackgroundAttachment
745        = [<background_attachment_single>]# -> |x: Vec<BackgroundAttachmentItem>| BackgroundAttachmentType::List(x.into());
746    }};
747    background_position: {{ (BackgroundPosition, BackgroundPositionX, BackgroundPositionY)
748        = [<background_position_single>]# -> |arr: Vec<_>| {
749            let mut x = vec![];
750            let mut y = vec![];
751            arr.iter().for_each(|item| {
752                if let BackgroundPositionItem::Pos(_x, _y) = item {
753                    x.push(BackgroundPositionItem::Value(_x.clone()));
754                    y.push(BackgroundPositionItem::Value(_y.clone()));
755                }
756            });
757
758            (BackgroundPositionType::List(arr.into()), BackgroundPositionType::List(x.into()), BackgroundPositionType::List(y.into()))
759        };
760    }};
761    background_position_x: {{ BackgroundPositionX = <background::background_position_x_value> }};
762    background_position_y: {{ BackgroundPositionY = <background::background_position_y_value> }};
763
764    background_clip: {{ BackgroundClip
765        = [<background_clip_single>]# -> |x: Vec<_>| {
766            BackgroundClipType::List(x.into())
767        };
768    }};
769    background_origin: {{ BackgroundOrigin
770        = [<background_origin_single>]# -> |x: Vec<_>| {
771            BackgroundOriginType::List(x.into())
772        };
773    }};
774
775    box_sizing: {{ BoxSizing
776        = "border-box" => BoxSizingType::BorderBox
777        | "padding-box" => BoxSizingType::PaddingBox
778        | "content-box" => BoxSizingType::ContentBox
779    }};
780    width: {{ Width = <length_percentage_auto> }};
781    height: {{ Height = <length_percentage_auto> }};
782    min_width: {{ MinWidth = <length_percentage_auto> }};
783    min_height: {{ MinHeight = <length_percentage_auto> }};
784    max_width: {{ MaxWidth = <length_percentage_auto> }};
785    max_height: {{ MaxHeight = <length_percentage_auto> }};
786    left: {{ Left = <length_percentage_auto> }};
787    right: {{ Right = <length_percentage_auto> }};
788    top: {{ Top = <length_percentage_auto> }};
789    bottom: {{ Bottom = <length_percentage_auto> }};
790
791    padding_left: {{ PaddingLeft = <length_percentage> }};
792    padding_right: {{ PaddingRight = <length_percentage> }};
793    padding_top: {{ PaddingTop = <length_percentage> }};
794    padding_bottom: {{ PaddingBottom = <length_percentage> }};
795    padding: {{ (PaddingTop, PaddingRight, PaddingBottom, PaddingLeft)
796        = <length_percentage>{1, 4} -> split_edges
797    }};
798
799    margin_left: {{ MarginLeft = <length_percentage_auto> }};
800    margin_right: {{ MarginRight = <length_percentage_auto> }};
801    margin_top: {{ MarginTop = <length_percentage_auto> }};
802    margin_bottom: {{ MarginBottom = <length_percentage_auto> }};
803    margin:{{ (MarginTop, MarginRight, MarginBottom, MarginLeft)
804        = <length_percentage_auto>{1, 4} -> split_edges
805    }};
806
807    <border_style_repr: BorderStyle>:
808        "none" => BorderStyle::None
809        | "solid" => BorderStyle::Solid
810        | "dotted" => BorderStyle::Dotted
811        | "dashed" => BorderStyle::Dashed
812        | "hidden" => BorderStyle::Hidden
813        | "double" => BorderStyle::Double
814        | "groove" => BorderStyle::Groove
815        | "ridge" => BorderStyle::Ridge
816        | "inset" => BorderStyle::Inset
817        | "outset" => BorderStyle::Outset
818    ;
819    border_left_width: {{ BorderLeftWidth = <line_width> }};
820    border_left_style: {{ BorderLeftStyle = <border_style_repr> }};
821    border_left_color: {{ BorderLeftColor = <color_repr> }};
822    border_left: <border_left_width> || <border_left_style> || <border_left_color>;
823    border_right_width: {{ BorderRightWidth = <line_width> }};
824    border_right_style: {{ BorderRightStyle = <border_style_repr> }};
825    border_right_color: {{ BorderRightColor = <color_repr> }};
826    border_right: <border_right_width> || <border_right_style> || <border_right_color>;
827    border_top_width: {{ BorderTopWidth = <line_width> }};
828    border_top_style: {{ BorderTopStyle = <border_style_repr> }};
829    border_top_color: {{ BorderTopColor = <color_repr> }};
830    border_top: <border_top_width> || <border_top_style> || <border_top_color>;
831    border_bottom_width: {{ BorderBottomWidth = <line_width> }};
832    border_bottom_style: {{ BorderBottomStyle = <border_style_repr> }};
833    border_bottom_color: {{ BorderBottomColor = <color_repr> }};
834    border_bottom: <border_bottom_width> || <border_bottom_style> || <border_bottom_color>;
835    border_width: {{ (BorderTopWidth, BorderRightWidth, BorderBottomWidth, BorderLeftWidth)
836        = <line_width>{1, 4} -> split_edges
837    }};
838    border_style: {{ (BorderTopStyle, BorderRightStyle, BorderBottomStyle, BorderLeftStyle)
839        = <border_style_repr>{1, 4} -> split_edges
840    }};
841    border_color: {{ (BorderTopColor, BorderRightColor, BorderBottomColor, BorderLeftColor)
842        = <color_repr>{1, 4} -> split_edges
843    }};
844    border: {{
845      (
846          BorderTopWidth,
847          BorderRightWidth,
848          BorderBottomWidth,
849          BorderLeftWidth,
850          BorderTopStyle,
851          BorderRightStyle,
852          BorderBottomStyle,
853          BorderLeftStyle,
854          BorderTopColor,
855          BorderRightColor,
856          BorderBottomColor,
857          BorderLeftColor,
858      ) = [
859            <line_width> || <border_style_repr> || <color_repr>
860          ] -> |x: (Option<Length>, Option<BorderStyle>, Option<Color>)| {
861              let width = x.0;
862              let style = x.1;
863              let color = x.2;
864              let mut w = LengthType::Initial;
865              let mut s = BorderStyle::None;
866              let mut c = ColorType::Initial;
867              // for border: 'none'
868              if let Some(style) = style {
869                s = style;
870              }
871              if let Some(width) = width {
872                  w = width.into();
873              }
874              if let Some(color) = color {
875                  c = color.into();
876              }
877              (
878                  w.clone(), w.clone(), w.clone(), w,
879                  s.clone(), s.clone(), s.clone(), s,
880                  c.clone(), c.clone(), c.clone(), c,
881              )
882          };
883    }};
884    border_top_left_radius: {{ BorderTopLeftRadius =
885        <length_percentage>{1, 2} -> split_hv -> |(a, b)| {
886            BorderRadius::Pos(a, b)
887        };
888    }};
889    border_top_right_radius: {{ BorderTopRightRadius =
890        <length_percentage>{1, 2} -> split_hv -> |(a, b)| {
891            BorderRadius::Pos(a, b)
892        };
893    }};
894    border_bottom_right_radius: {{ BorderBottomRightRadius =
895        <length_percentage>{1, 2} -> split_hv -> |(a, b)| {
896            BorderRadius::Pos(a, b)
897        };
898    }};
899    border_bottom_left_radius: {{ BorderBottomLeftRadius =
900        <length_percentage>{1, 2} -> split_hv -> |(a, b)| {
901            BorderRadius::Pos(a, b)
902        };
903    }};
904    border_radius:{{ (BorderTopLeftRadius, BorderTopRightRadius, BorderBottomRightRadius, BorderBottomLeftRadius)
905        = [<length_percentage>{1, 4} ['/' <length_percentage>{1, 4}]?] -> |(a, b): (Vec<_>, Option<(_, Vec<_>)>)| {
906            let horizontal = split_edges(a);
907            let mut vertical =horizontal.clone();
908            if let Some(v) = b {
909                vertical = split_edges(v.1);
910            }
911            (
912                BorderRadius::Pos(horizontal.0, vertical.0),
913                BorderRadius::Pos(horizontal.1, vertical.1),
914                BorderRadius::Pos(horizontal.2, vertical.2),
915                BorderRadius::Pos(horizontal.3, vertical.3)
916            )
917        };
918    }};
919    box_shadow: {{ BoxShadow =
920        "none" => BoxShadow::None
921        | [
922            "inset"? && <length_only>{2, 4} && <color_repr>?
923        ]# -> ResultClosure |x: Vec<(Option<Option<_>>, Option<Vec<Length>>, Option<Option<Color>>)>, parser: &mut Parser<'i, 't> | -> Result<BoxShadow, ParseError<'i, CustomError>> {
924            let mut ret = Vec::with_capacity(x.len());
925            let mut error = false;
926            x.into_iter().for_each(|item| {
927                let mut r = vec![];
928                let inset = item.0.unwrap();
929                if inset.is_some() {
930                    r.push(ShadowItemType::Inset)
931                }
932                if let Some(len) = item.1 {
933                    let offset_x = len.get(0).unwrap();
934                    let offset_y = len.get(1).unwrap();
935                    r.push(ShadowItemType::OffsetX(offset_x.clone()));
936                    r.push(ShadowItemType::OffsetY(offset_y.clone()));
937                    let blur_radius = len.get(2);
938
939                    let spread_radius = len.get(3);
940                    if let Some(br) = blur_radius {
941                        if !is_non_negative_length(br) {
942                            error = true;
943                        }
944                        r.push(ShadowItemType::BlurRadius(br.clone()));
945                    } else {
946                        r.push(ShadowItemType::BlurRadius(Length::Px(0.)));
947                    }
948                    if let Some(sr) = spread_radius {
949                        r.push(ShadowItemType::SpreadRadius(sr.clone()));
950                    } else {
951                        r.push(ShadowItemType::SpreadRadius(Length::Px(0.)));
952
953                    }
954                }
955                let color = item.2.unwrap();
956                if let Some(color) = color {
957                    r.push(ShadowItemType::Color(color));
958                } else {
959                    r.push(ShadowItemType::Color(Color::CurrentColor));
960                }
961                ret.push(BoxShadowItem::List(r.into()));
962            });
963            if error {
964                Err(parser.new_custom_error::<_, CustomError>(CustomError::Unsupported))?;
965            }
966            Ok(BoxShadow::List(ret.into()))
967        };
968    }};
969    backdrop_filter: {{ BackdropFilter =
970        "none" => BackdropFilter::None
971        | <filter::filter_repr> -> |x: Vec<_>| { BackdropFilter::List(x.into()) };
972    }};
973    filter: {{ Filter =
974        "none" => Filter::None
975        | <filter::filter_repr> -> |x: Vec<_>| { Filter::List(x.into()) };
976    }};
977    transform: {{ Transform =
978        "none" -> |_| { Transform::Series(Array::empty()) };
979        | <transform_repr>
980    }};
981    transform_origin: {{ TransformOrigin =
982        [
983            [
984                "center" => TransformOrigin::Center
985                | "left" => TransformOrigin::Left
986                | "right" => TransformOrigin::Right
987                | <length_percentage> -> |x: Length| { TransformOrigin::Length(x) };
988            ] && [
989                "top" => TransformOrigin::Top
990                | "center" => TransformOrigin::Center
991                | "bottom" => TransformOrigin::Bottom
992                | <length_percentage> -> |y: Length| { TransformOrigin::Length(y) };
993            ] && [<length_only>?]
994        ] -> |item: (Option<TransformOrigin>, Option<TransformOrigin>, Option<Option<_>>)| {
995            let x = item.0;
996            let y = item.1;
997            let z = item.2;
998            let x = match x.unwrap() {
999                TransformOrigin::Center => Length::Ratio(0.5),
1000                TransformOrigin::Left => Length::Ratio(0.),
1001                TransformOrigin::Right => Length::Ratio(1.0),
1002                TransformOrigin::Length(x) => x,
1003                _ => Length::Ratio(0.5),
1004            };
1005            let y = match y.unwrap() {
1006                TransformOrigin::Center => Length::Ratio(0.5),
1007                TransformOrigin::Top => Length::Ratio(0.),
1008                TransformOrigin::Bottom => Length::Ratio(1.0),
1009                TransformOrigin::Length(y) => y,
1010                _ => Length::Ratio(0.5),
1011            };
1012            let z = match z.unwrap() {
1013                Some(z) => z,
1014                None => Length::Px(0.)
1015            };
1016            TransformOrigin::LengthTuple(x, y, z)
1017        };
1018        | [
1019            "left" -> |_| { TransformOrigin::LengthTuple(Length::Ratio(0.), Length::Ratio(0.5), Length::Px(0.)) };
1020            | "center" -> |_| { TransformOrigin::LengthTuple(Length::Ratio(0.5), Length::Ratio(0.5), Length::Px(0.)) };
1021            | "right" -> |_| { TransformOrigin::LengthTuple(Length::Ratio(1.), Length::Ratio(0.5), Length::Px(0.)) };
1022            | "top" -> |_| { TransformOrigin::LengthTuple(Length::Ratio(0.5), Length::Ratio(0.), Length::Px(0.)) };
1023            | "bottom" -> |_| { TransformOrigin::LengthTuple(Length::Ratio(0.5), Length::Ratio(1.), Length::Px(0.)) };
1024            | <length_percentage> -> |x: Length| { TransformOrigin::LengthTuple(x, Length::Ratio(0.5), Length::Px(0.)) };
1025        ]
1026    }};
1027    <transition_property_single: TransitionPropertyItem>:
1028        "none" => TransitionPropertyItem::None
1029        | "transform" => TransitionPropertyItem::Transform
1030        | "transform-origin" => TransitionPropertyItem::TransformOrigin
1031        | "line-height" => TransitionPropertyItem::LineHeight
1032        | "opacity" => TransitionPropertyItem::Opacity
1033        | "all" => TransitionPropertyItem::All
1034        | "height" => TransitionPropertyItem::Height
1035        | "width" => TransitionPropertyItem::Width
1036        | "min-height" => TransitionPropertyItem::MinHeight
1037        | "max-height" => TransitionPropertyItem::MaxHeight
1038        | "min-width" => TransitionPropertyItem::MinWidth
1039        | "max-width" => TransitionPropertyItem::MaxWidth
1040        | "margin-top" => TransitionPropertyItem::MarginTop
1041        | "margin-right" => TransitionPropertyItem::MarginRight
1042        | "margin-bottom" => TransitionPropertyItem::MarginBottom
1043        | "margin-left" => TransitionPropertyItem::MarginLeft
1044        | "margin" => TransitionPropertyItem::Margin
1045        | "padding-top" => TransitionPropertyItem::PaddingTop
1046        | "padding-right" => TransitionPropertyItem::PaddingRight
1047        | "padding-bottom" => TransitionPropertyItem::PaddingBottom
1048        | "padding-left" => TransitionPropertyItem::PaddingLeft
1049        | "padding" => TransitionPropertyItem::Padding
1050        | "top" => TransitionPropertyItem::Top
1051        | "right" => TransitionPropertyItem::Right
1052        | "bottom" => TransitionPropertyItem::Bottom
1053        | "left" => TransitionPropertyItem::Left
1054        | "flex-grow" => TransitionPropertyItem::FlexGrow
1055        | "flex-shrink" => TransitionPropertyItem::FlexShrink
1056        | "flex-basis" => TransitionPropertyItem::FlexBasis
1057        | "border-top-width" => TransitionPropertyItem::BorderTopWidth
1058        | "border-right-width" => TransitionPropertyItem::BorderRightWidth
1059        | "border-bottom-width" => TransitionPropertyItem::BorderBottomWidth
1060        | "border-left-width" => TransitionPropertyItem::BorderLeftWidth
1061        | "border-top-color" => TransitionPropertyItem::BorderTopColor
1062        | "border-right-color" => TransitionPropertyItem::BorderRightColor
1063        | "border-bottom-color" => TransitionPropertyItem::BorderBottomColor
1064        | "border-left-color" => TransitionPropertyItem::BorderLeftColor
1065        | "border-top-left-radius" => TransitionPropertyItem::BorderTopLeftRadius
1066        | "border-top-right-radius" => TransitionPropertyItem::BorderTopRightRadius
1067        | "border-bottom-left-radius" => TransitionPropertyItem::BorderBottomLeftRadius
1068        | "border-bottom-right-radius" => TransitionPropertyItem::BorderBottomRightRadius
1069        | "border" => TransitionPropertyItem::Border
1070        | "border-width" => TransitionPropertyItem::BorderWidth
1071        | "border-radius" => TransitionPropertyItem::BorderRadius
1072        | "border-color" => TransitionPropertyItem::BorderColor
1073        | "border-left" => TransitionPropertyItem::BorderLeft
1074        | "border-top" => TransitionPropertyItem::BorderTop
1075        | "border-right" => TransitionPropertyItem::BorderRight
1076        | "border-bottom" => TransitionPropertyItem::BorderBottom
1077        | "z-index" => TransitionPropertyItem::ZIndex
1078        | "filter" => TransitionPropertyItem::Filter
1079        | "backdrop-filter" => TransitionPropertyItem::BackdropFilter
1080        | "box-shadow" => TransitionPropertyItem::BoxShadow
1081        | "color" => TransitionPropertyItem::Color
1082        | "text-decoration-color" => TransitionPropertyItem::TextDecorationColor
1083        | "text-decoration-thickness" => TransitionPropertyItem::TextDecorationThickness
1084        | "font-size" => TransitionPropertyItem::FontSize
1085        | "font-weight" => TransitionPropertyItem::FontWeight
1086        | "letter-spacing" => TransitionPropertyItem::LetterSpacing
1087        | "word-spacing" => TransitionPropertyItem::WordSpacing
1088        | "background-color" => TransitionPropertyItem::BackgroundColor
1089        | "background-position" => TransitionPropertyItem::BackgroundPosition
1090        | "background-size" => TransitionPropertyItem::BackgroundSize
1091        | "background" => TransitionPropertyItem::Background
1092        | "flex" => TransitionPropertyItem::Flex
1093        | "background-position-x" => TransitionPropertyItem::BackgroundPositionX
1094        | "background-position-y" => TransitionPropertyItem::BackgroundPositionY
1095        | "mask-size" => TransitionPropertyItem::MaskSize
1096        | "mask-position-x" => TransitionPropertyItem::MaskPositionX
1097        | "mask-position-y" => TransitionPropertyItem::MaskPositionY
1098        | "mask-position" => TransitionPropertyItem::MaskPosition
1099        | "mask" => TransitionPropertyItem::Mask;
1100    transition_property: {{ TransitionProperty
1101        = <transition_property_single># -> |x: Vec<_>| TransitionPropertyType::List(x.into());
1102    }};
1103    transition_duration: {{ TransitionDuration
1104        = <time_u32_ms># -> |x: Vec<_>| TransitionTimeType::List(x.into());
1105    }};
1106    <step_position_repr: StepPosition>:
1107        "end" => StepPosition::End
1108        | "start" => StepPosition::Start
1109        | "jump-start" => StepPosition::JumpStart
1110        | "jump-end" => StepPosition::JumpEnd
1111        | "jump-none" => StepPosition::JumpNone;
1112    <timing_function_single: TransitionTimingFnItem>:
1113        "linear" => TransitionTimingFnItem::Linear
1114        | "ease" => TransitionTimingFnItem::Ease
1115        | "ease-in" => TransitionTimingFnItem::EaseIn
1116        | "ease-out" => TransitionTimingFnItem::EaseOut
1117        | "ease-in-out" => TransitionTimingFnItem::EaseInOut
1118        | "linear" => TransitionTimingFnItem::Linear
1119        | "step-start" => TransitionTimingFnItem::StepStart
1120        | "step-end" => TransitionTimingFnItem::StepEnd
1121        | steps(<float_repr> [',' <step_position_repr>]?) // TODO use number type
1122            -> |x: (f32, Option<(_, StepPosition)>)| {
1123                let a = x.0 as i32;
1124                let mut b = StepPosition::End;
1125                if let Some((_, step_position)) = x.1 {
1126                    b = step_position;
1127                }
1128                TransitionTimingFnItem::Steps(a, b)
1129            };
1130        | cubic_bezier(<float_repr> ',' <float_repr> ',' <float_repr> ',' <float_repr>) // TODO use number type
1131            -> |(a, _, b, _, c, _, d)| {
1132                TransitionTimingFnItem::CubicBezier(a, b, c, d)
1133            };
1134        ;
1135    transition_timing_function: {{ TransitionTimingFunction
1136        = <timing_function_single># -> |x: Vec<_>| TransitionTimingFnType::List(x.into());
1137    }};
1138    transition_delay: {{ TransitionDelay
1139        = <time_i32_ms># -> |x: Vec<_>| TransitionTimeType::ListI32(x.into());
1140    }};
1141    transition: {{ (TransitionProperty, TransitionDuration, TransitionTimingFunction, TransitionDelay)
1142        = [
1143            <transition_property_single>
1144            || <time_u32_ms>
1145            || <timing_function_single>
1146            || <time_i32_ms>
1147        ]# -> |x: Vec<(_, _, _, _)>| {
1148            let mut properties = Vec::with_capacity(x.len());
1149            let mut duration: Vec<u32> = Vec::with_capacity(x.len());
1150            let mut timing_fn: Vec<TransitionTimingFnItem> = Vec::with_capacity(x.len());
1151            let mut delay: Vec<i32> = Vec::with_capacity(x.len());
1152            for v in x {
1153                match v.0 {
1154                    Some(v) => properties.push(v),
1155                    None => properties.push(TransitionPropertyItem::All)
1156                }
1157                match v.1 {
1158                    Some(v) => duration.push(v),
1159                    None => duration.push(0)
1160                }
1161                match v.2 {
1162                    Some(v) => timing_fn.push(v),
1163                    None => timing_fn.push(TransitionTimingFnItem::Ease)
1164                }
1165                match v.3 {
1166                    Some(v) => delay.push(v),
1167                    None => delay.push(0)
1168                }
1169            }
1170            (
1171                TransitionPropertyType::List(properties.into()),
1172                TransitionTimeType::List(duration.into()),
1173                TransitionTimingFnType::List(timing_fn.into()),
1174                TransitionTimeType::ListI32(delay.into()),
1175            )
1176        };
1177    }};
1178    animation: {{ (AnimationDuration, AnimationTimingFunction, AnimationDelay, AnimationIterationCount, AnimationDirection, AnimationFillMode, AnimationPlayState, AnimationName)
1179        = [
1180            <time_u32_ms>
1181            || <timing_function_single>
1182            || <time_i32_ms>
1183            || <animation_iteration_count_single>
1184            || <animation_direction_single>
1185            || <animation_fill_mode_single>
1186            || <animation_play_state_single>
1187            || <animation_name_single>
1188        ]# -> |x: Vec<(_, _, _, _, _, _, _, _)>| {
1189            let len = x.len();
1190            let mut duration: Vec<u32> = Vec::with_capacity(len);
1191            let mut timing_fn: Vec<TransitionTimingFnItem> = Vec::with_capacity(len);
1192            let mut delay: Vec<i32> = Vec::with_capacity(len);
1193            let mut iteration_count: Vec<AnimationIterationCountItem> = Vec::with_capacity(len);
1194            let mut direction: Vec<AnimationDirectionItem> = Vec::with_capacity(len);
1195            let mut fill_mode: Vec<AnimationFillModeItem> = Vec::with_capacity(len);
1196            let mut play_state: Vec<AnimationPlayStateItem> = Vec::with_capacity(len);
1197            let mut name: Vec<AnimationNameItem> = Vec::with_capacity(len);
1198            for item in x {
1199                match item.0 {
1200                    Some(v) => duration.push(v),
1201                    None => duration.push(0)
1202                }
1203                match item.1 {
1204                    Some(v) => timing_fn.push(v),
1205                    None => timing_fn.push(TransitionTimingFnItem::Ease)
1206                }
1207                match item.2 {
1208                    Some(v) => delay.push(v),
1209                    None => delay.push(0)
1210                }
1211                match item.3 {
1212                    Some(v) => iteration_count.push(v),
1213                    None => iteration_count.push(AnimationIterationCountItem::Number(1.))
1214                }
1215                match item.4 {
1216                    Some(v) => direction.push(v),
1217                    None => direction.push(AnimationDirectionItem::Normal)
1218                }
1219                match item.5 {
1220                    Some(v) => fill_mode.push(v),
1221                    None => fill_mode.push(AnimationFillModeItem::None)
1222                }
1223                match item.6 {
1224                    Some(v) => play_state.push(v),
1225                    None => play_state.push(AnimationPlayStateItem::Running)
1226                }
1227                match item.7 {
1228                    Some(v) => name.push(v),
1229                    None => name.push(AnimationNameItem::None)
1230                }
1231            }
1232            (
1233                TransitionTimeType::List(duration.into()),
1234                TransitionTimingFnType::List(timing_fn.into()),
1235                TransitionTimeType::ListI32(delay.into()),
1236                AnimationIterationCountType::List(iteration_count.into()),
1237                AnimationDirectionType::List(direction.into()),
1238                AnimationFillModeType::List(fill_mode.into()),
1239                AnimationPlayStateType::List(play_state.into()),
1240                AnimationName::List(name.into())
1241            )
1242        };
1243    }};
1244    animation_duration: {{ AnimationDuration
1245        = <time_u32_ms># -> |x: Vec<_>| TransitionTimeType::List(x.into());
1246    }};
1247    animation_delay: {{ AnimationDelay
1248        = <time_i32_ms># -> |x: Vec<_>| TransitionTimeType::ListI32(x.into());
1249    }};
1250    animation_timing_function: {{ AnimationTimingFunction
1251        = <timing_function_single># -> |x: Vec<_>| TransitionTimingFnType::List(x.into());
1252    }};
1253    animation_iteration_count: {{ AnimationIterationCount
1254        = <animation_iteration_count_single># -> |x: Vec<_>| AnimationIterationCountType::List(x.into());
1255    }};
1256    <animation_iteration_count_single: AnimationIterationCountItem>:
1257        "infinite" => AnimationIterationCountItem::Infinite
1258        | <float_repr> -> |x: _| AnimationIterationCountItem::Number(x);
1259    ;
1260    animation_direction: {{ AnimationDirection
1261        = <animation_direction_single># -> |x: Vec<_>| AnimationDirectionType::List(x.into());
1262    }};
1263    <animation_direction_single: AnimationDirectionItem>:
1264        "normal" => AnimationDirectionItem::Normal
1265        | "reverse" => AnimationDirectionItem::Reverse
1266        | "alternate" => AnimationDirectionItem::Alternate
1267        | "alternate-reverse" => AnimationDirectionItem::AlternateReverse;
1268    animation_fill_mode: {{ AnimationFillMode
1269        = <animation_fill_mode_single># -> |x: Vec<_>| AnimationFillModeType::List(x.into());
1270    }};
1271    <animation_fill_mode_single: AnimationFillModeItem>:
1272        "none" => AnimationFillModeItem::None
1273        | "forwards" => AnimationFillModeItem::Forwards
1274        | "backwards" => AnimationFillModeItem::Backwards
1275        | "both" => AnimationFillModeItem::Both;
1276    animation_play_state: {{ AnimationPlayState
1277        = <animation_play_state_single># -> |x: Vec<_>| AnimationPlayStateType::List(x.into());
1278    }};
1279    <animation_play_state_single: AnimationPlayStateItem>:
1280        "running" => AnimationPlayStateItem::Running
1281        | "paused" => AnimationPlayStateItem::Paused;
1282    animation_name: {{ AnimationName
1283        = <animation_name_single># -> |x: Vec<_>| AnimationNameType::List(x.into());
1284    }};
1285    <animation_name_single: AnimationNameItem>:
1286        "none" => AnimationNameItem::None
1287        | <string> -> |custom_ident: String| AnimationNameItem::CustomIdent(custom_ident.into());
1288    ;
1289    will_change: {{ WillChange
1290        = "auto" => WillChange::Auto
1291       | <animateable_feature_single># -> |x: Vec<_>| WillChange::List(x.into());
1292    }};
1293    <animateable_feature_single: AnimateableFeature>:
1294        "contents" => AnimateableFeature::Contents
1295        | "scroll-position" => AnimateableFeature::ScrollPosition
1296        | <string> ->  |custom_ident: String| AnimateableFeature::CustomIdent(custom_ident.into());
1297    ;
1298    aspect_ratio: {{ AspectRatio
1299        = "auto" => AspectRatioType::Auto
1300        | [ <number> ['/' <number>]?] -> |r: (Number, Option<(_, Number)>)| {
1301            let width = r.0;
1302            let height = match r.1 {
1303                Some(h) => h.1,
1304                None => Number::F32(1.)
1305            };
1306            AspectRatioType::Ratio(width, height)
1307        };
1308    }};
1309    contain: {{ Contain
1310        = "none" => ContainType::None
1311        | "strict" => ContainType::Strict
1312        | "content" => ContainType::Content
1313        | ["size" || "layout" || "style" || "paint"] -> |x: (Option<()>, Option<()>, Option<()>, Option<()>)| {
1314            let mut v = vec![];
1315            if x.0.is_some() {
1316                v.push(ContainKeyword::Size);
1317            }
1318            if x.1.is_some() {
1319                v.push(ContainKeyword::Layout);
1320            }
1321            if x.2.is_some() {
1322                v.push(ContainKeyword::Style);
1323            }
1324            if x.3.is_some() {
1325                v.push(ContainKeyword::Paint);
1326            }
1327            ContainType::Multiple(v.into())
1328        };
1329    }};
1330    _wx_scrollbar_x: {{ WxScrollbarX
1331        = "hidden" => ScrollbarType::Hidden
1332        | "auto-hide" => ScrollbarType::AutoHide
1333        | "always-show" => ScrollbarType::AlwaysShow
1334    }};
1335    _wx_scrollbar_x_color: {{ WxScrollbarXColor = <color_repr> }};
1336    _wx_scrollbar_y: {{ WxScrollbarY
1337        = "hidden" => ScrollbarType::Hidden
1338        | "auto-hide" => ScrollbarType::AutoHide
1339        | "always-show" => ScrollbarType::AlwaysShow
1340    }};
1341    _wx_scrollbar_y_color: {{ WxScrollbarYColor = <color_repr> }};
1342    _wx_scrollbar_color: {{ (WxScrollbarXColor, WxScrollbarYColor)
1343        = <color_repr>{1, 2} -> split_hv
1344    }};
1345    _wx_line_clamp: {{ WxLineClamp = <number> }};
1346    _wx_contain: {{ WxContain
1347        = "none" => ContainType::None
1348        | "strict" => ContainType::Strict
1349        | "content" => ContainType::Content
1350        | ["size" || "layout" || "style" || "paint"] -> |x: (Option<()>, Option<()>, Option<()>, Option<()>)| {
1351            let mut v = vec![];
1352            if x.0.is_some() {
1353                v.push(ContainKeyword::Size);
1354            }
1355            if x.1.is_some() {
1356                v.push(ContainKeyword::Layout);
1357            }
1358            if x.2.is_some() {
1359                v.push(ContainKeyword::Style);
1360            }
1361            if x.3.is_some() {
1362                v.push(ContainKeyword::Paint);
1363            }
1364            ContainType::Multiple(v.into())
1365        };
1366    }};
1367    content: {{ Content
1368        = "none" => ContentType::None
1369        | "normal" => ContentType::Normal
1370        | <url_str> -> |x: String| ContentType::Url(x.into());
1371        | <string> -> |x: String| ContentType::Str(x.into());
1372    }};
1373    list_style_type: {{ ListStyleType
1374        = "none" => ListStyleType::None
1375        | "disc" => ListStyleType::Disc
1376        | "circle" => ListStyleType::Circle
1377        | "square" => ListStyleType::Square
1378        | "decimal" => ListStyleType::Decimal
1379        | "cjk-decimal" => ListStyleType::CjkDecimal
1380        | "decimal-leading-zero" => ListStyleType::DecimalLeadingZero
1381        | "lower-roman" => ListStyleType::LowerRoman
1382        | "upper-roman" => ListStyleType::UpperRoman
1383        | "lower-greek" => ListStyleType::LowerGreek
1384        | "lower-alpha" => ListStyleType::LowerAlpha
1385        | "lower-latin" => ListStyleType::LowerLatin
1386        | "upper-alpha" => ListStyleType::UpperAlpha
1387        | "upper-latin" => ListStyleType::UpperLatin
1388        | "armenian" => ListStyleType::Armenian
1389        | "georgian" => ListStyleType::Georgian
1390      // | <custom_ident_repr> -> |x: String| ListStyleType::CustomIdent(x.into());
1391    }};
1392    list_style_image: {{ ListStyleImage
1393        = "none" => ListStyleImage::None
1394        | <url_str> -> |x: String| ListStyleImage::Url(x.into());
1395    }};
1396    list_style_position: {{ ListStylePosition
1397        = "outside" => ListStylePosition::Outside
1398        | "inside" => ListStylePosition::Inside
1399    }};
1400    list_style: <list_style_type> || <list_style_position> || <list_style_image>;
1401
1402    resize: {{ Resize
1403        = "none" => ResizeType::None
1404        | "both" => ResizeType::Both
1405        | "horizontal" => ResizeType::Horizontal
1406        | "vertical" => ResizeType::Vertical
1407        | "block" => ResizeType::Block
1408        | "inline" => ResizeType::Inline
1409    }};
1410
1411    text_shadow: {{ TextShadow
1412        = "none" => TextShadowType::None
1413        | [
1414            [ <length_only>{2, 3} && <color_repr>? ]
1415        ]# -> |x: Vec<(Option<Vec<Length>>, Option<Option<Color>>)>| {
1416            let mut t = Vec::with_capacity(x.len());
1417            for item in x.into_iter() {
1418                let a = item.0.unwrap();
1419                let offset_x = a.get(0).unwrap().clone();
1420                let offset_y = a.get(1).unwrap().clone();
1421                let blur_radius = a.get(2);
1422                let blur_radius = match blur_radius {
1423                    Some(v) => v.clone(),
1424                    None => Length::Undefined
1425                };
1426                let b = item.1.unwrap();
1427                let color = match b {
1428                    Some(v) => v.clone(),
1429                    None => Color::Undefined
1430                };
1431                t.push(
1432                    TextShadowItem::TextShadowValue(
1433                        offset_x,
1434                        offset_y,
1435                        blur_radius,
1436                        color
1437                    )
1438                );
1439            }
1440            TextShadowType::List(t.into())
1441        };
1442    }};
1443
1444    text_decoration_line: {{TextDecorationLine
1445        = "none" => TextDecorationLine::None
1446        | "spelling-error" => TextDecorationLine::SpellingError
1447        | "grammar-error" => TextDecorationLine::GrammarError
1448        | ["underline" || "overline" || "line-through" || "blink"] -> |x: (Option<()>, Option<()>, Option<()>, Option<()>)| {
1449            let mut v = vec![];
1450            if let Some(_underline) = x.0 {
1451                v.push(TextDecorationLineItem::Underline);
1452            }
1453            if let Some(_overline) = x.1 {
1454                v.push(TextDecorationLineItem::Overline);
1455            }
1456            if let Some(_line_through) = x.2 {
1457                v.push(TextDecorationLineItem::LineThrough);
1458            }
1459            if let Some(_blink) = x.3 {
1460                v.push(TextDecorationLineItem::Blink);
1461            }
1462            TextDecorationLine::List(v.into())
1463        };
1464    }};
1465    text_decoration_style: {{ TextDecorationStyle
1466        = "solid" => TextDecorationStyleType::Solid
1467        | "double" => TextDecorationStyleType::Double
1468        | "dotted" => TextDecorationStyleType::Dotted
1469        | "dashed" => TextDecorationStyleType::Dashed
1470        | "wavy" => TextDecorationStyleType::Wavy
1471    }};
1472    text_decoration_color: {{ TextDecorationColor = <color_repr> }};
1473    text_decoration_thickness: {{ TextDecorationThickness
1474        = "from-font" => TextDecorationThicknessType::FromFont
1475        | <length_percentage_auto> -> |x: Length| { TextDecorationThicknessType::Length(x)};
1476    }};
1477    text_decoration: <text_decoration_style> || <text_decoration_color> || <text_decoration_thickness> || <text_decoration_line>;
1478    font_feature_settings: {{ FontFeatureSettings
1479        = "normal" => FontFeatureSettingsType::Normal
1480        | [<string> <font_feature_tag_value_repr>?]# -> |tags: Vec<(String, Option<Number>)>| {
1481            let ret: Vec<FeatureTag> = tags.into_iter().map(|item| {
1482                FeatureTag {
1483                    opentype_tag: item.0.into(),
1484                    value: item.1.unwrap_or_else(|| Number::F32(1.)),
1485                }
1486            }).collect();
1487            FontFeatureSettingsType::FeatureTags(ret.into())
1488        };
1489    }};
1490    <font_feature_tag_value_repr: Number>:
1491        "on" -> |_| {Number::F32(1.)};
1492        | "off" -> |_| {Number::F32(0.)};
1493        | <non_negative_number>
1494    ;
1495    mask_image: {{ MaskImage
1496        = [<image_single>]# -> |x: Vec<BackgroundImageItem>| BackgroundImageType::List(x.into());
1497    }};
1498    mask_size: {{ MaskSize
1499        = [<background_size_single>]# -> |x: Vec<BackgroundSizeItem>| BackgroundSizeType::List(x.into());
1500    }};
1501    mask_repeat: {{ MaskRepeat
1502      = [<background_repeat_single>]# -> |x: Vec<BackgroundRepeatItem>| BackgroundRepeatType::List(x.into());
1503    }};
1504    mask_origin: {{ MaskOrigin
1505        = [<background_origin_single>]# -> |x: Vec<_>| {
1506            BackgroundOriginType::List(x.into())
1507        };
1508    }};
1509    mask_clip: {{ MaskClip
1510        = [<background_clip_single>]# -> |x: Vec<_>| {
1511            BackgroundClipType::List(x.into())
1512        };
1513    }};
1514    mask_position: {{ (MaskPosition, MaskPositionX, MaskPositionY)
1515        = [<background_position_single>]# -> |arr: Vec<_>| {
1516            let mut x = vec![];
1517            let mut y = vec![];
1518            arr.iter().for_each(|item| {
1519                if let BackgroundPositionItem::Pos(_x, _y) = item {
1520                    x.push(BackgroundPositionItem::Value(_x.clone()));
1521                    y.push(BackgroundPositionItem::Value(_y.clone()));
1522                }
1523            });
1524
1525            (BackgroundPositionType::List(arr.into()), BackgroundPositionType::List(x.into()), BackgroundPositionType::List(y.into()))
1526        };
1527    }};
1528    mask_position_x: {{ MaskPositionX = <background::background_position_x_value> }};
1529    mask_position_y: {{ MaskPositionY = <background::background_position_y_value> }};
1530
1531    <mask_mode_single: MaskModeItem>:
1532        "match-source" => MaskModeItem::MatchSource
1533        | "luminance" => MaskModeItem::Luminance
1534        | "alpha" => MaskModeItem::Alpha
1535    ;
1536    mask_mode: {{ MaskMode
1537      = [<mask_mode_single>]# -> |x: Vec<_>| MaskModeType::List(x.into());
1538    }};
1539    mask: {{ (MaskImage, MaskRepeat, MaskPosition, MaskPositionX, MaskPositionY, MaskSize, BackgroundOrigin, BackgroundClip)
1540        = "none" -> |_| (
1541            BackgroundImageType::List(vec![BackgroundImageItem::None].into()),
1542            BackgroundRepeatType::List(vec![BackgroundRepeatItem::Pos(BackgroundRepeatValue::Repeat, BackgroundRepeatValue::Repeat)].into()),
1543            BackgroundPositionType::List(vec![BackgroundPositionItem::Pos(BackgroundPositionValue::Left(Length::Ratio(0.)), BackgroundPositionValue::Top(Length::Ratio(0.)))].into()),
1544            BackgroundPositionType::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.)))].into()),
1545            BackgroundPositionType::List(vec![BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.)))].into()),
1546            BackgroundSizeType::List(vec![BackgroundSizeItem::Auto].into()),
1547            BackgroundOriginType::List(vec![BackgroundOriginItem::BorderBox].into()),
1548            BackgroundClipType::List(vec![BackgroundClipItem::BorderBox].into()),
1549        );
1550        | [
1551            <image_single>
1552            || <background_repeat_single>
1553            || [<background_position_single_without_extra_check> [ '/' <background_size_single>]?]
1554            || <background_origin_single>
1555            || <background_clip_single>
1556        ]# -> |x: Vec<(
1557                Option<_>,
1558                Option<_>,
1559                Option<(_, Option<(_, _)>)>,
1560                Option<BackgroundOriginItem>,
1561                Option<BackgroundClipItem>
1562            )>| -> (BackgroundImageType, BackgroundRepeatType, BackgroundPositionType, BackgroundPositionType, BackgroundPositionType, BackgroundSizeType, BackgroundOriginType, BackgroundClipType) {
1563                let mut img = Vec::with_capacity(x.len());
1564                let mut rep = Vec::with_capacity(x.len());
1565                let mut pos = Vec::with_capacity(x.len());
1566                let mut pos_x = Vec::with_capacity(x.len());
1567                let mut pos_y = Vec::with_capacity(x.len());
1568                let mut size = Vec::with_capacity(x.len());
1569                let mut origin = Vec::with_capacity(x.len());
1570                let mut clip = Vec::with_capacity(x.len());
1571                for v in x.into_iter() {
1572                    match v.0 {
1573                        Some(x) => {
1574                            img.push(x);
1575
1576                        }
1577                        None => {
1578                            img.push(BackgroundImageItem::None);
1579                        }
1580                    }
1581                    match v.1 {
1582                        Some(x) => {
1583                            rep.push(x);
1584                        }
1585                        None => {
1586                            rep.push(BackgroundRepeatItem::Pos(
1587                                BackgroundRepeatValue::Repeat,
1588                                BackgroundRepeatValue::Repeat
1589                            ));
1590                        }
1591                    }
1592                    match v.2 {
1593                        Some(pos_size) => {
1594                            let (__pos, __size) = pos_size;
1595                            {
1596                                if let BackgroundPositionItem::Pos(x, y) = &__pos {
1597                                    pos_x.push(BackgroundPositionItem::Value(x.clone()));
1598                                    pos_y.push(BackgroundPositionItem::Value(y.clone()));
1599                                }
1600                            }
1601                            pos.push(__pos);
1602                            match __size {
1603                            Some(s) => {
1604                                size.push(s.1);
1605                            },
1606                            None => {
1607                                size.push(BackgroundSizeItem::Auto);
1608                            }
1609                        }
1610                    }
1611                        None=> {
1612                            pos.push(
1613                                BackgroundPositionItem::Pos(
1614                                    BackgroundPositionValue::Left(Length::Ratio(0.)),
1615                                    BackgroundPositionValue::Top(Length::Ratio(0.))
1616                                )
1617                            );
1618                            pos_x.push(BackgroundPositionItem::Value(BackgroundPositionValue::Left(Length::Ratio(0.))));
1619                            pos_y.push(BackgroundPositionItem::Value(BackgroundPositionValue::Top(Length::Ratio(0.))));
1620                            size.push(BackgroundSizeItem::Auto);
1621                        }
1622                    }
1623                    if v.3.is_some() && v.4.is_some() {
1624                        if let Some(__origin) = v.3 {
1625                            origin.push(__origin);
1626                        }
1627                        if let Some(__clip) = v.4 {
1628                            clip.push(__clip);
1629                        }
1630                    } else if v.3.is_some() || v.4.is_some() {
1631                        if let Some(__origin) = v.3 {
1632                            origin.push(__origin.clone());
1633                            match __origin {
1634                                BackgroundOriginItem::PaddingBox => {
1635                                    clip.push(BackgroundClipItem::PaddingBox);
1636                                },
1637                                BackgroundOriginItem::BorderBox => {
1638                                    clip.push(BackgroundClipItem::BorderBox);
1639                                },
1640                                BackgroundOriginItem::ContentBox => {
1641                                    clip.push(BackgroundClipItem::ContentBox);
1642                                },
1643                            };
1644                        }
1645                        if let Some(__clip) = v.4 {
1646                            clip.push(__clip.clone());
1647                            match __clip {
1648                                BackgroundClipItem::PaddingBox => {
1649                                    origin.push(BackgroundOriginItem::PaddingBox);
1650                                },
1651                                BackgroundClipItem::BorderBox => {
1652                                    origin.push(BackgroundOriginItem::BorderBox);
1653                                },
1654                                BackgroundClipItem::ContentBox => {
1655                                    origin.push(BackgroundOriginItem::ContentBox);
1656                                },
1657                                _ => {},
1658                            };
1659                        }
1660                    } else {
1661                        origin.push(BackgroundOriginItem::PaddingBox);
1662                        clip.push(BackgroundClipItem::BorderBox);
1663                    }
1664                }
1665                (
1666                    BackgroundImageType::List(img.into()),
1667                    BackgroundRepeatType::List(rep.into()),
1668                    BackgroundPositionType::List(pos.into()),
1669                    BackgroundPositionType::List(pos_x.into()),
1670                    BackgroundPositionType::List(pos_y.into()),
1671                    BackgroundSizeType::List(size.into()),
1672                    BackgroundOriginType::List(origin.into()),
1673                    BackgroundClipType::List(clip.into()),
1674                )
1675        };
1676    }};
1677
1678    <track_breadth: TrackSize>:
1679        "auto" -> |_| TrackSize::Length(Length::Auto);
1680        | <non_negative_length_percentage> -> |x: Length| TrackSize::Length(x);
1681        | "min-content" -> |_| TrackSize::MinContent;
1682        | "max-content" -> |_| TrackSize::MaxContent;
1683        | <fr_repr> -> |x: f32| TrackSize::Fr(x);
1684    ;
1685
1686    <track_size: TrackSize>:
1687        <track_breadth> -> |x: TrackSize| x;
1688    ;
1689
1690    <track_list: Vec<TrackListItem>>:
1691        [ [ <line_names>? [ <track_size> ] ]+ <line_names>? ] -> |x: (Vec<(Option<Vec<String>>, TrackSize)>, Option<Vec<String>>)| {
1692            let mut ret = vec![];
1693            for item in x.0.into_iter() {
1694                if let Some(line_names) = item.0 {
1695                    ret.push(TrackListItem::LineNames(line_names.iter().map(|x| x.into()).collect::<Vec<StrRef>>().into()));
1696                }
1697                ret.push(TrackListItem::TrackSize(item.1));
1698            }
1699            if let Some(line_names) = x.1 {
1700                ret.push(TrackListItem::LineNames(line_names.iter().map(|x| x.into()).collect::<Vec<StrRef>>().into()));
1701            }
1702            ret
1703        };
1704    ;
1705    grid_template_rows: {{ GridTemplateRows
1706        = "none" => GridTemplate::None
1707        | <track_list> -> |x: Vec<TrackListItem>| {
1708            GridTemplate::TrackList(x.into())
1709        };
1710    }};
1711
1712    grid_template_columns: {{ GridTemplateColumns
1713        = "none" => GridTemplate::None
1714        | <track_list> -> |x: Vec<TrackListItem>| {
1715            GridTemplate::TrackList(x.into())
1716        };
1717    }};
1718
1719    grid_auto_flow: {{ GridAutoFlow = <grid_auto_flow_repr> }};
1720
1721    grid_auto_rows: {{ GridAutoRows
1722        = <track_size>+ -> |x: Vec<TrackSize>| {
1723            GridAuto::List(x.into())
1724        };
1725    }};
1726
1727    grid_auto_columns: {{ GridAutoColumns
1728        = <track_size>+ -> |x: Vec<TrackSize>| {
1729            GridAuto::List(x.into())
1730        };
1731    }};
1732
1733    <touch_action_pan_x: u8>:
1734        "pan-x" -> |_| 3;
1735        | "pan-left" -> |_| 1;
1736        | "pan-right" -> |_| 2;
1737    ;
1738    <touch_action_pan_y: u8>:
1739        "pan-y" -> |_| 3;
1740        | "pan-up" -> |_| 1;
1741        | "pan-down" -> |_| 2;
1742    ;
1743    touch_action: {{ TouchAction
1744        = "auto" => TouchActionType::Auto
1745        | "none" => TouchActionType::None
1746        | "manipulation" => TouchActionType::Manipulation
1747        | [<touch_action_pan_x> || <touch_action_pan_y>] -> |(pan_x, pan_y): (Option<u8>, Option<u8>)| {
1748            let pan_x = pan_x.unwrap_or(0);
1749            let pan_y = pan_y.unwrap_or(0);
1750            let ges = TouchActionGestures {
1751                pan_left: (pan_x & 1) > 0,
1752                pan_right: (pan_x & 2) > 0,
1753                pan_up: (pan_y & 1) > 0,
1754                pan_down: (pan_y & 2) > 0,
1755            };
1756            TouchActionType::Gestures(ges)
1757        };
1758    }}
1759});
1760
1761pub(crate) fn split_hv<T: Clone>(x: Vec<T>) -> (T, T) {
1762    let mut x = x.into_iter();
1763    let a = x.next().unwrap();
1764    let b = x.next().unwrap_or_else(|| a.clone());
1765    (a, b)
1766}
1767
1768pub(crate) fn split_edges<T: Clone>(x: Vec<T>) -> (T, T, T, T) {
1769    let mut x = x.into_iter();
1770    let a = x.next().unwrap();
1771    let b = x.next().unwrap_or_else(|| a.clone());
1772    let c = x.next().unwrap_or_else(|| a.clone());
1773    let d = x.next().unwrap_or_else(|| b.clone());
1774    (a, b, c, d)
1775}