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