Skip to main content

stylex_css/order/constants/
legacy_expand_shorthands_order.rs

1use crate::values::common::split_value_required;
2use crate::values::parser::parse_css;
3use stylex_constants::constants::common::{LOGICAL_FLOAT_END_VAR, LOGICAL_FLOAT_START_VAR};
4use stylex_structures::order_pair::OrderPair;
5
6/// Helper function to check if a string is a valid list-style-type value
7/// Matches: [a-z-]+ or quoted strings like "..." or '...'
8fn is_list_style_type(s: &str) -> bool {
9  // Check for properly quoted strings with matching quotes (minimum length 2)
10  if s.len() >= 2
11    && ((s.starts_with('"') && s.ends_with('"')) || (s.starts_with('\'') && s.ends_with('\'')))
12  {
13    return true;
14  }
15
16  // Check if it matches [a-z-]+ pattern (lowercase letters and hyphens only)
17  !s.is_empty() && s.chars().all(|c| c.is_ascii_lowercase() || c == '-')
18}
19
20#[derive(Debug, PartialEq, Eq, Clone, Hash)]
21pub struct Shorthands;
22
23impl Shorthands {
24  fn border(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
25    Ok(vec![
26      OrderPair("borderTop".into(), raw_value.to_owned()),
27      OrderPair("borderInlineEnd".into(), raw_value.to_owned()),
28      OrderPair("borderBottom".into(), raw_value.to_owned()),
29      OrderPair("borderInlineStart".into(), raw_value),
30    ])
31  }
32
33  fn border_color(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
34    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
35
36    Ok(vec![
37      OrderPair("borderTopColor".into(), Some(top)),
38      OrderPair("borderInlineEndColor".into(), Some(right)),
39      OrderPair("borderBottomColor".into(), Some(bottom)),
40      OrderPair("borderInlineStartColor".into(), Some(left)),
41    ])
42  }
43  fn border_horizontal(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
44    Ok(vec![
45      OrderPair("borderInlineStart".into(), raw_value.to_owned()),
46      OrderPair("borderInlineEnd".into(), raw_value),
47    ])
48  }
49  fn border_style(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
50    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
51
52    Ok(vec![
53      OrderPair("borderTopStyle".into(), Some(top)),
54      OrderPair("borderInlineEndStyle".into(), Some(right)),
55      OrderPair("borderBottomStyle".into(), Some(bottom)),
56      OrderPair("borderInlineStartStyle".into(), Some(left)),
57    ])
58  }
59  fn border_vertical(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
60    Ok(vec![
61      OrderPair("borderTop".into(), raw_value.to_owned()),
62      OrderPair("borderBottom".into(), raw_value),
63    ])
64  }
65  fn border_width(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
66    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
67
68    Ok(vec![
69      OrderPair("borderTopWidth".into(), Some(top)),
70      OrderPair("borderInlineEndWidth".into(), Some(right)),
71      OrderPair("borderBottomWidth".into(), Some(bottom)),
72      OrderPair("borderInlineStartWidth".into(), Some(left)),
73    ])
74  }
75
76  fn border_horizontal_color(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
77    Ok(vec![
78      OrderPair("borderInlineStartColor".into(), raw_value.to_owned()),
79      OrderPair("borderInlineEndColor".into(), raw_value),
80    ])
81  }
82  fn border_horizontal_style(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
83    Ok(vec![
84      OrderPair("borderInlineStartStyle".into(), raw_value.to_owned()),
85      OrderPair("borderInlineEndStyle".into(), raw_value),
86    ])
87  }
88  fn border_horizontal_width(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
89    Ok(vec![
90      OrderPair("borderInlineStartWidth".into(), raw_value.to_owned()),
91      OrderPair("borderInlineEndWidth".into(), raw_value),
92    ])
93  }
94  fn border_inline_color(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
95    Ok(vec![
96      OrderPair("borderInlineStartColor".into(), raw_value.to_owned()),
97      OrderPair("borderInlineEndColor".into(), raw_value),
98    ])
99  }
100  fn border_inline_style(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
101    Ok(vec![
102      OrderPair("borderInlineStartStyle".into(), raw_value.to_owned()),
103      OrderPair("borderInlineEndStyle".into(), raw_value),
104    ])
105  }
106  fn border_inline_width(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
107    Ok(vec![
108      OrderPair("borderInlineStartWidth".into(), raw_value.to_owned()),
109      OrderPair("borderInlineEndWidth".into(), raw_value),
110    ])
111  }
112  fn border_vertical_color(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
113    Ok(vec![
114      OrderPair("borderTopColor".into(), raw_value.to_owned()),
115      OrderPair("borderBottomColor".into(), raw_value),
116    ])
117  }
118  fn border_vertical_style(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
119    Ok(vec![
120      OrderPair("borderTopStyle".into(), raw_value.to_owned()),
121      OrderPair("borderBottomStyle".into(), raw_value),
122    ])
123  }
124  fn border_vertical_width(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
125    Ok(vec![
126      OrderPair("borderTopWidth".into(), raw_value.to_owned()),
127      OrderPair("borderBottomWidth".into(), raw_value),
128    ])
129  }
130
131  fn border_radius(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
132    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
133
134    Ok(vec![
135      OrderPair("borderStartStartRadius".into(), Some(top)),
136      OrderPair("borderStartEndRadius".into(), Some(right)),
137      OrderPair("borderEndEndRadius".into(), Some(bottom)),
138      OrderPair("borderEndStartRadius".into(), Some(left)),
139    ])
140  }
141
142  fn contain_intrinsic_size(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
143    let parts = split_value_required(raw_value.as_deref());
144    let parts = [parts.0, parts.1, parts.2, parts.3];
145
146    let mut coll: Vec<String> = Vec::with_capacity(parts.len());
147
148    for part in parts {
149      if let Some(last_element) = coll.last()
150        && last_element == "auto"
151        && !part.is_empty()
152      {
153        coll.pop();
154        coll.push(format!("auto {}", part));
155        continue;
156      }
157      coll.push(part);
158    }
159
160    let width = coll.first().cloned().unwrap_or_default();
161    let height = coll.get(1).cloned().unwrap_or_else(|| width.clone());
162
163    Ok(vec![
164      OrderPair("containIntrinsicWidth".into(), Some(width)),
165      OrderPair("containIntrinsicHeight".into(), Some(height)),
166    ])
167  }
168
169  fn inset(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
170    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
171
172    Ok(vec![
173      OrderPair("top".into(), Some(top)),
174      OrderPair("insetInlineEnd".into(), Some(right)),
175      OrderPair("bottom".into(), Some(bottom)),
176      OrderPair("insetInlineStart".into(), Some(left)),
177    ])
178  }
179  fn inset_inline(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
180    let (start, end, _, _) = split_value_required(raw_value.as_deref());
181
182    let mut result = vec![];
183
184    result.extend(Shorthands::start(Some(start))?);
185    result.extend(Shorthands::end(Some(end))?);
186
187    Ok(result)
188  }
189  fn inset_block(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
190    let (top, bottom, _, _) = split_value_required(raw_value.as_deref());
191
192    Ok(vec![
193      OrderPair("top".into(), Some(top)),
194      OrderPair("bottom".into(), Some(bottom)),
195    ])
196  }
197  fn start(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
198    Ok(vec![
199      OrderPair("insetInlineStart".into(), raw_value),
200      OrderPair("left".into(), None),
201      OrderPair("right".into(), None),
202    ])
203  }
204  fn end(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
205    Ok(vec![
206      OrderPair("insetInlineEnd".into(), raw_value),
207      OrderPair("left".into(), None),
208      OrderPair("right".into(), None),
209    ])
210  }
211  fn left(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
212    Ok(vec![
213      OrderPair("left".into(), raw_value),
214      OrderPair("insetInlineStart".into(), None),
215      OrderPair("insetInlineEnd".into(), None),
216    ])
217  }
218  fn right(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
219    Ok(vec![
220      OrderPair("right".into(), raw_value),
221      OrderPair("insetInlineStart".into(), None),
222      OrderPair("insetInlineEnd".into(), None),
223    ])
224  }
225
226  fn gap(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
227    let (row, column, _, _) = split_value_required(raw_value.as_deref());
228
229    Ok(vec![
230      OrderPair("rowGap".into(), Some(row)),
231      OrderPair("columnGap".into(), Some(column)),
232    ])
233  }
234  fn margin(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
235    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
236
237    Ok(vec![
238      OrderPair("marginTop".into(), Some(top)),
239      OrderPair("marginInlineEnd".into(), Some(right)),
240      OrderPair("marginBottom".into(), Some(bottom)),
241      OrderPair("marginInlineStart".into(), Some(left)),
242    ])
243  }
244  fn margin_horizontal(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
245    let (start, end, _, _) = split_value_required(raw_value.as_deref());
246
247    let mut result = vec![];
248
249    result.extend(Shorthands::margin_start(Some(start))?);
250    result.extend(Shorthands::margin_end(Some(end))?);
251
252    Ok(result)
253  }
254  fn margin_start(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
255    Ok(vec![
256      OrderPair("marginInlineStart".into(), raw_value),
257      OrderPair("marginLeft".into(), None),
258      OrderPair("marginRight".into(), None),
259    ])
260  }
261  fn margin_end(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
262    Ok(vec![
263      OrderPair("marginInlineEnd".into(), raw_value),
264      OrderPair("marginLeft".into(), None),
265      OrderPair("marginRight".into(), None),
266    ])
267  }
268  fn margin_left(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
269    Ok(vec![
270      OrderPair("marginLeft".into(), raw_value),
271      OrderPair("marginInlineStart".into(), None),
272      OrderPair("marginInlineEnd".into(), None),
273    ])
274  }
275  fn margin_right(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
276    Ok(vec![
277      OrderPair("marginRight".into(), raw_value),
278      OrderPair("marginInlineStart".into(), None),
279      OrderPair("marginInlineEnd".into(), None),
280    ])
281  }
282  fn margin_vertical(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
283    let (top, bottom, _, _) = split_value_required(raw_value.as_deref());
284
285    Ok(vec![
286      OrderPair("marginTop".into(), Some(top)),
287      OrderPair("marginBottom".into(), Some(bottom)),
288    ])
289  }
290
291  fn list_style(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
292    // Handle None case
293    if raw_value.is_none() {
294      return Ok(vec![
295        OrderPair("listStyleType".into(), None),
296        OrderPair("listStylePosition".into(), None),
297        OrderPair("listStyleImage".into(), None),
298      ]);
299    }
300
301    let raw_value_str = match raw_value.as_ref() {
302      Some(v) => v,
303      None => return Err("listStyle requires a value.".into()),
304    };
305    let parts: Vec<String> = parse_css(raw_value_str);
306
307    // Global values that must be the only value
308    let list_style_global_values = ["inherit", "initial", "revert", "unset"];
309
310    // Position values (unambiguous)
311    let list_style_position_values = ["inside", "outside"];
312
313    // Handle global keywords - must be the only value
314    if parts.len() == 1 && list_style_global_values.contains(&parts[0].as_str()) {
315      let global_value = Some(parts[0].clone());
316      return Ok(vec![
317        OrderPair("listStyleType".into(), global_value.clone()),
318        OrderPair("listStylePosition".into(), global_value.clone()),
319        OrderPair("listStyleImage".into(), global_value),
320      ]);
321    }
322
323    let mut image: Option<String> = None;
324    let mut position: Option<String> = None;
325    let mut list_type: Option<String> = None;
326    let mut remaining_parts: Vec<String> = Vec::new();
327
328    // First pass: assign values that can only belong to one property
329    for part in &parts {
330      // Check for global keywords mixed with other values (invalid)
331      // and use of `var()` which can't be disambiguated
332      if list_style_global_values.contains(&part.as_str()) || part.contains("var(--") {
333        return Err(format!("Invalid listStyle value: '{}'", raw_value_str));
334      }
335      // Check if it's a position value (unambiguous)
336      else if list_style_position_values.contains(&part.as_str()) {
337        if position.is_some() {
338          return Err(format!("Invalid listStyle value: '{}'", raw_value_str));
339        }
340        position = Some(part.clone());
341      }
342      // Check if it's a type value that's not 'none' (unambiguous)
343      // Type values are: keywords (letters and hyphens) or quoted strings
344      else if part != "none" && is_list_style_type(part) {
345        if list_type.is_some() {
346          return Err(format!("Invalid listStyle value: '{}'", raw_value_str));
347        }
348        list_type = Some(part.clone());
349      }
350      // Keep ambiguous values for second pass
351      else {
352        remaining_parts.push(part.clone());
353      }
354    }
355
356    // Second pass: handle remaining parts (including 'none' and image values)
357    for part in remaining_parts {
358      // If 'none' and type is not yet assigned, assign to type
359      if part == "none" && list_type.is_none() {
360        list_type = Some(part);
361      }
362      // Otherwise assign to image
363      else {
364        if image.is_some() {
365          return Err(format!("Invalid listStyle value: '{}'", raw_value_str));
366        }
367        image = Some(part);
368      }
369    }
370
371    Ok(vec![
372      OrderPair("listStyleType".into(), list_type),
373      OrderPair("listStylePosition".into(), position),
374      OrderPair("listStyleImage".into(), image),
375    ])
376  }
377
378  fn overflow(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
379    let (x, y, _, _) = split_value_required(raw_value.as_deref());
380    Ok(vec![
381      OrderPair("overflowX".into(), Some(x)),
382      OrderPair("overflowY".into(), Some(y)),
383    ])
384  }
385  fn padding(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
386    let (top, right, bottom, left) = split_value_required(raw_value.as_deref());
387
388    Ok(vec![
389      OrderPair("paddingTop".into(), Some(top)),
390      OrderPair("paddingInlineEnd".into(), Some(right)),
391      OrderPair("paddingBottom".into(), Some(bottom)),
392      OrderPair("paddingInlineStart".into(), Some(left)),
393    ])
394  }
395  fn padding_horizontal(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
396    let (start, end, _, _) = split_value_required(raw_value.as_deref());
397
398    let mut result = vec![];
399
400    result.extend(Shorthands::padding_start(Some(start))?);
401    result.extend(Shorthands::padding_end(Some(end))?);
402
403    Ok(result)
404  }
405  fn padding_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
406    Ok(vec![
407      OrderPair("paddingInlineStart".into(), val),
408      OrderPair("paddingLeft".into(), None),
409      OrderPair("paddingRight".into(), None),
410    ])
411  }
412  fn padding_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
413    Ok(vec![
414      OrderPair("paddingInlineEnd".into(), val),
415      OrderPair("paddingLeft".into(), None),
416      OrderPair("paddingRight".into(), None),
417    ])
418  }
419  fn padding_left(val: Option<String>) -> Result<Vec<OrderPair>, String> {
420    Ok(vec![
421      OrderPair("paddingLeft".into(), val),
422      OrderPair("paddingInlineStart".into(), None),
423      OrderPair("paddingInlineEnd".into(), None),
424    ])
425  }
426  fn padding_right(val: Option<String>) -> Result<Vec<OrderPair>, String> {
427    Ok(vec![
428      OrderPair("paddingRight".into(), val),
429      OrderPair("paddingInlineStart".into(), None),
430      OrderPair("paddingInlineEnd".into(), None),
431    ])
432  }
433  fn padding_vertical(raw_value: Option<String>) -> Result<Vec<OrderPair>, String> {
434    let (top, bottom, _, _) = split_value_required(raw_value.as_deref());
435
436    Ok(vec![
437      OrderPair("paddingTop".into(), Some(top)),
438      OrderPair("paddingBottom".into(), Some(bottom)),
439    ])
440  }
441
442  pub fn get(name: &str) -> Option<fn(Option<String>) -> Result<Vec<OrderPair>, String>> {
443    match name {
444      "border" => Some(Shorthands::border),
445      "borderColor" => Some(Shorthands::border_color),
446      "borderHorizontal" => Some(Shorthands::border_horizontal),
447      "borderStyle" => Some(Shorthands::border_style),
448      "borderVertical" => Some(Shorthands::border_vertical),
449      "borderWidth" => Some(Shorthands::border_width),
450      "borderHorizontalColor" => Some(Shorthands::border_horizontal_color),
451      "borderHorizontalStyle" => Some(Shorthands::border_horizontal_style),
452      "borderHorizontalWidth" => Some(Shorthands::border_horizontal_width),
453      "borderInlineColor" => Some(Shorthands::border_inline_color),
454      "borderInlineStyle" => Some(Shorthands::border_inline_style),
455      "borderInlineWidth" => Some(Shorthands::border_inline_width),
456      "borderVerticalColor" => Some(Shorthands::border_vertical_color),
457      "borderVerticalStyle" => Some(Shorthands::border_vertical_style),
458      "borderVerticalWidth" => Some(Shorthands::border_vertical_width),
459      "borderRadius" => Some(Shorthands::border_radius),
460      "containIntrinsicSize" => Some(Shorthands::contain_intrinsic_size),
461      "inset" => Some(Shorthands::inset),
462      "insetInline" => Some(Shorthands::inset_inline),
463      "insetBlock" => Some(Shorthands::inset_block),
464      "start" => Some(Shorthands::start),
465      "end" => Some(Shorthands::end),
466      "left" => Some(Shorthands::left),
467      "right" => Some(Shorthands::right),
468      "gap" => Some(Shorthands::gap),
469      "listStyle" => Some(Shorthands::list_style),
470      "margin" => Some(Shorthands::margin),
471      "marginHorizontal" => Some(Shorthands::margin_horizontal),
472      "marginStart" => Some(Shorthands::margin_start),
473      "marginEnd" => Some(Shorthands::margin_end),
474      "marginLeft" => Some(Shorthands::margin_left),
475      "marginRight" => Some(Shorthands::margin_right),
476      "marginVertical" => Some(Shorthands::margin_vertical),
477      "overflow" => Some(Shorthands::overflow),
478      "padding" => Some(Shorthands::padding),
479      "paddingHorizontal" => Some(Shorthands::padding_horizontal),
480      "paddingStart" => Some(Shorthands::padding_start),
481      "paddingEnd" => Some(Shorthands::padding_end),
482      "paddingLeft" => Some(Shorthands::padding_left),
483      "paddingRight" => Some(Shorthands::padding_right),
484      "paddingVertical" => Some(Shorthands::padding_vertical),
485
486      _ => None,
487    }
488  }
489}
490
491#[derive(Debug, PartialEq, Eq, Clone, Hash)]
492pub struct Aliases;
493
494#[allow(dead_code)]
495impl Aliases {
496  fn inset_block_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
497    Ok(vec![OrderPair("top".into(), val)])
498  }
499  fn inset_block_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
500    Ok(vec![OrderPair("bottom".into(), val)])
501  }
502
503  fn block_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
504    Ok(vec![OrderPair("height".into(), val)])
505  }
506  fn inline_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
507    Ok(vec![OrderPair("width".into(), val)])
508  }
509  fn min_block_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
510    Ok(vec![OrderPair("minHeight".into(), val)])
511  }
512  fn min_inline_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
513    Ok(vec![OrderPair("minWidth".into(), val)])
514  }
515  fn max_block_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
516    Ok(vec![OrderPair("maxHeight".into(), val)])
517  }
518  fn max_inline_size(val: Option<String>) -> Result<Vec<OrderPair>, String> {
519    Ok(vec![OrderPair("maxWidth".into(), val)])
520  }
521  fn border_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
522    Ok(vec![OrderPair("borderInlineStart".into(), val)])
523  }
524  fn border_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
525    Ok(vec![OrderPair("borderInlineEnd".into(), val)])
526  }
527  fn border_block_start_width(val: Option<String>) -> Result<Vec<OrderPair>, String> {
528    Ok(vec![OrderPair("borderTopWidth".into(), val)])
529  }
530  fn border_block_start_style(val: Option<String>) -> Result<Vec<OrderPair>, String> {
531    Ok(vec![OrderPair("borderTopStyle".into(), val)])
532  }
533  fn border_block_start_color(val: Option<String>) -> Result<Vec<OrderPair>, String> {
534    Ok(vec![OrderPair("borderTopColor".into(), val)])
535  }
536  fn border_block_end_width(val: Option<String>) -> Result<Vec<OrderPair>, String> {
537    Ok(vec![OrderPair("borderBottomWidth".into(), val)])
538  }
539  fn border_block_end_style(val: Option<String>) -> Result<Vec<OrderPair>, String> {
540    Ok(vec![OrderPair("borderBottomStyle".into(), val)])
541  }
542  fn border_block_end_color(val: Option<String>) -> Result<Vec<OrderPair>, String> {
543    Ok(vec![OrderPair("borderBottomColor".into(), val)])
544  }
545
546  fn border_inline_start_width(val: Option<String>) -> Result<Vec<OrderPair>, String> {
547    Ok(vec![OrderPair("borderInlineStartWidth".into(), val)])
548  }
549  fn border_inline_start_style(val: Option<String>) -> Result<Vec<OrderPair>, String> {
550    Ok(vec![OrderPair("borderInlineStartStyle".into(), val)])
551  }
552  fn border_inline_start_color(val: Option<String>) -> Result<Vec<OrderPair>, String> {
553    Ok(vec![OrderPair("borderInlineStartColor".into(), val)])
554  }
555  fn border_inline_end_width(val: Option<String>) -> Result<Vec<OrderPair>, String> {
556    Ok(vec![OrderPair("borderInlineEndWidth".into(), val)])
557  }
558  fn border_inline_end_style(val: Option<String>) -> Result<Vec<OrderPair>, String> {
559    Ok(vec![OrderPair("borderInlineEndStyle".into(), val)])
560  }
561  fn border_inline_end_color(val: Option<String>) -> Result<Vec<OrderPair>, String> {
562    Ok(vec![OrderPair("borderInlineEndColor".into(), val)])
563  }
564  fn border_start_start_radius(val: Option<String>) -> Result<Vec<OrderPair>, String> {
565    Ok(vec![OrderPair("borderTopStartRadius".into(), val)])
566  }
567  fn border_start_end_radius(val: Option<String>) -> Result<Vec<OrderPair>, String> {
568    Ok(vec![OrderPair("borderTopEndRadius".into(), val)])
569  }
570  fn border_end_start_radius(val: Option<String>) -> Result<Vec<OrderPair>, String> {
571    Ok(vec![OrderPair("borderBottomStartRadius".into(), val)])
572  }
573  fn border_end_end_radius(val: Option<String>) -> Result<Vec<OrderPair>, String> {
574    Ok(vec![OrderPair("borderBottomEndRadius".into(), val)])
575  }
576
577  fn grid_row_gap(value: Option<String>) -> Result<Vec<OrderPair>, String> {
578    Ok(vec![OrderPair("rowGap".into(), value)])
579  }
580  fn grid_column_gap(value: Option<String>) -> Result<Vec<OrderPair>, String> {
581    Ok(vec![OrderPair("columnGap".into(), value)])
582  }
583
584  fn margin_block_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
585    Ok(vec![OrderPair("marginTop".into(), val)])
586  }
587  fn margin_block_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
588    Ok(vec![OrderPair("marginBottom".into(), val)])
589  }
590  fn margin_inline_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
591    Ok(vec![OrderPair("marginInlineStart".into(), val)])
592  }
593  fn margin_inline_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
594    Ok(vec![OrderPair("marginInlineEnd".into(), val)])
595  }
596
597  fn overflow_block(value: Option<String>) -> Result<Vec<OrderPair>, String> {
598    Ok(vec![OrderPair("overflowY".into(), value)])
599  }
600  fn overflow_inline(value: Option<String>) -> Result<Vec<OrderPair>, String> {
601    Ok(vec![OrderPair("overflowX".into(), value)])
602  }
603
604  fn padding_block_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
605    Ok(vec![OrderPair("paddingTop".into(), val)])
606  }
607  fn padding_block_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
608    Ok(vec![OrderPair("paddingBottom".into(), val)])
609  }
610
611  fn padding_inline_start(val: Option<String>) -> Result<Vec<OrderPair>, String> {
612    Ok(vec![OrderPair("paddingInlineStart".into(), val)])
613  }
614  fn padding_inline_end(val: Option<String>) -> Result<Vec<OrderPair>, String> {
615    Ok(vec![OrderPair("paddingInlineEnd".into(), val)])
616  }
617
618  fn scroll_margin_block_start(value: Option<String>) -> Result<Vec<OrderPair>, String> {
619    Ok(vec![OrderPair("scrollMarginTop".into(), value)])
620  }
621  fn scroll_margin_block_end(value: Option<String>) -> Result<Vec<OrderPair>, String> {
622    Ok(vec![OrderPair("scrollMarginBottom".into(), value)])
623  }
624
625  fn float(value: Option<String>) -> Result<Vec<OrderPair>, String> {
626    if let Some(ref val) = value {
627      if val == "inline-start" || val == "start" {
628        return Ok(vec![OrderPair(
629          "float".into(),
630          Some(format!("var({})", LOGICAL_FLOAT_START_VAR)),
631        )]);
632      } else if val == "inline-end" || val == "end" {
633        return Ok(vec![OrderPair(
634          "float".into(),
635          Some(format!("var({})", LOGICAL_FLOAT_END_VAR)),
636        )]);
637      }
638    }
639    Ok(vec![OrderPair("float".into(), value)])
640  }
641
642  fn clear(value: Option<String>) -> Result<Vec<OrderPair>, String> {
643    if let Some(ref val) = value {
644      if val == "inline-start" || val == "start" {
645        return Ok(vec![OrderPair(
646          "clear".into(),
647          Some(format!("var({})", LOGICAL_FLOAT_START_VAR)),
648        )]);
649      } else if val == "inline-end" || val == "end" {
650        return Ok(vec![OrderPair(
651          "clear".into(),
652          Some(format!("var({})", LOGICAL_FLOAT_END_VAR)),
653        )]);
654      }
655    }
656    Ok(vec![OrderPair("clear".into(), value)])
657  }
658
659  pub fn get(name: &str) -> Option<fn(Option<String>) -> Result<Vec<OrderPair>, String>> {
660    match name {
661      "insetBlockStart" => Some(Aliases::inset_block_start),
662      "insetBlockEnd" => Some(Aliases::inset_block_end),
663      "insetInlineStart" => Shorthands::get("start"),
664      "insetInlineEnd" => Shorthands::get("end"),
665      "blockSize" => Some(Aliases::block_size),
666      "inlineSize" => Some(Aliases::inline_size),
667      "minBlockSize" => Some(Aliases::min_block_size),
668      "minInlineSize" => Some(Aliases::min_inline_size),
669      "maxBlockSize" => Some(Aliases::max_block_size),
670      "maxInlineSize" => Some(Aliases::max_inline_size),
671      "borderBlockWidth" => Shorthands::get("borderVerticalWidth"),
672      "borderBlockStyle" => Shorthands::get("borderVerticalStyle"),
673      "borderBlockColor" => Shorthands::get("borderVerticalColor"),
674      "borderStart" => Some(Aliases::border_start),
675      "borderEnd" => Some(Aliases::border_end),
676      "borderBlockStartWidth" => Some(Aliases::border_block_start_width),
677      "borderBlockStartStyle" => Some(Aliases::border_block_start_style),
678      "borderBlockStartColor" => Some(Aliases::border_block_start_color),
679      "borderBlockEndWidth" => Some(Aliases::border_block_end_width),
680      "borderBlockEndStyle" => Some(Aliases::border_block_end_style),
681      "borderBlockEndColor" => Some(Aliases::border_block_end_color),
682      "borderInlineWidth" => Shorthands::get("borderInlineWidth"),
683      "borderInlineStyle" => Shorthands::get("borderInlineStyle"),
684      "borderInlineColor" => Shorthands::get("borderInlineColor"),
685      "borderTopStartRadius" => Some(Aliases::border_start_start_radius),
686      "borderTopEndRadius" => Some(Aliases::border_start_end_radius),
687      "borderBottomStartRadius" => Some(Aliases::border_end_start_radius),
688      "borderBottomEndRadius" => Some(Aliases::border_end_end_radius),
689      "gridGap" => Shorthands::get("gap"),
690      "gridRowGap" => Some(Aliases::grid_row_gap),
691      "gridColumnGap" => Some(Aliases::grid_column_gap),
692      "marginBlock" => Shorthands::get("marginVertical"),
693      "marginBlockStart" => Some(Aliases::margin_block_start),
694      "marginBlockEnd" => Some(Aliases::margin_block_end),
695      "marginInline" => Shorthands::get("marginHorizontal"),
696      "marginInlineStart" => Some(Aliases::margin_inline_start),
697      "marginInlineEnd" => Some(Aliases::margin_inline_end),
698      "overflowBlock" => Some(Aliases::overflow_block),
699      "overflowInline" => Some(Aliases::overflow_inline),
700      "paddingBlock" => Shorthands::get("paddingVertical"),
701      "paddingBlockStart" => Some(Aliases::padding_block_start),
702      "paddingBlockEnd" => Some(Aliases::padding_block_end),
703      "paddingInline" => Shorthands::get("paddingHorizontal"),
704      "paddingInlineStart" => Some(Aliases::padding_inline_start),
705      "paddingInlineEnd" => Some(Aliases::padding_inline_end),
706      "scrollMarginBlockStart" => Some(Aliases::scroll_margin_block_start),
707      "scrollMarginBlockEnd" => Some(Aliases::scroll_margin_block_end),
708      "float" => Some(Aliases::float),
709      "clear" => Some(Aliases::clear),
710      _ => None,
711    }
712  }
713}