tailwind_css_fixes/systems/instruction/
resolver.rs

1use super::*;
2
3// noinspection SpellCheckingInspection
4impl TailwindInstruction {
5    #[inline(never)]
6    pub fn get_instance(&self) -> Result<Box<dyn TailwindInstance>> {
7        let element = self.view_elements();
8        let pattern = element.as_slice();
9        let arbitrary = self.view_arbitrary();
10        let neg = self.negative;
11        let instance = match pattern {
12            // Layout System
13            ["aspect", rest @ ..] => TailwindAspect::parse(rest, arbitrary)?.boxed(),
14            ["container"] => TailwindContainer::default().boxed(),
15            ["columns", rest @ ..] => TailwindColumns::parse(rest, arbitrary)?.boxed(),
16            ["break", rest @ ..] => TailwindBreak::parse(rest, arbitrary)?,
17            ["box", rest @ ..] => Self::box_adaptor(rest, arbitrary)?,
18            // begin https://tailwindcss.com/docs/display
19            // skip [flex, table]
20            ["block"] => TailwindDisplay::from("block").boxed(),
21            ["inline", "block"] => TailwindDisplay::from("inline-block").boxed(),
22            ["inline"] => TailwindDisplay::from("inline").boxed(),
23            ["inline", "flex"] => TailwindDisplay::from("inline-flex").boxed(),
24            ["inline", "table"] => TailwindDisplay::from("inline-table").boxed(),
25            ["flow", "root"] => TailwindDisplay::from("flow-root").boxed(),
26            ["grid"] => TailwindDisplay::from("grid").boxed(),
27            ["inline", "grid"] => TailwindDisplay::from("inline-grid").boxed(),
28            ["contents"] => TailwindDisplay::from("contents").boxed(),
29            ["list", "item"] => TailwindDisplay::from("inline-grid").boxed(),
30            ["hidden"] => TailwindDisplay::from("hidden").boxed(),
31            // https://tailwindcss.com/docs/float
32            ["float", rest @ ..] => TailwindFloat::parse(rest, arbitrary)?.boxed(),
33            ["clear", rest @ ..] => TailwindClear::parse(rest, arbitrary)?.boxed(),
34            ["isolate"] => TailwindIsolation::from("isolate").boxed(),
35            ["isolation", rest @ ..] => TailwindIsolation::parse(rest, arbitrary)?.boxed(),
36            ["object", rest @ ..] => object_adaptor(rest, arbitrary)?,
37            ["overflow", rest @ ..] => TailwindOverflow::parse(rest, arbitrary)?.boxed(),
38            ["overscroll", rest @ ..] => TailwindOverscroll::parse(rest, arbitrary)?.boxed(),
39            // https://tailwindcss.com/docs/position#header
40            [s @ ("static" | "fixed" | "absolute" | "relative" | "sticky")] => TailwindPosition::from(*s).boxed(),
41            ["position", rest @ ..] => TailwindPosition::parse(rest, arbitrary)?.boxed(),
42            // https://tailwindcss.com/docs/top-right-bottom-left
43            ["inset", rest @ ..] => TailwindInset::parse(rest, arbitrary, neg)?.boxed(),
44            ["top", rest @ ..] => TailwindTop::parse(rest, arbitrary, neg)?.boxed(),
45            ["right", rest @ ..] => TailwindRight::parse(rest, arbitrary, neg)?.boxed(),
46            ["bottom", rest @ ..] => TailwindBottom::parse(rest, arbitrary, neg)?.boxed(),
47            ["left", rest @ ..] => TailwindLeft::parse(rest, arbitrary, neg)?.boxed(),
48            ["start", rest @ ..] => TailwindStart::parse(rest, arbitrary, neg)?.boxed(),
49            ["end", rest @ ..] => TailwindEnd::parse(rest, arbitrary, neg)?.boxed(),
50            // https://tailwindcss.com/docs/visibility
51            ["invisible"] => TailwindVisibility::from("hidden").boxed(),
52            ["visible" | "visibility", rest @ ..] => TailwindVisibility::parse(rest, arbitrary)?.boxed(),
53            // https://tailwindcss.com/docs/z-index
54            ["z", rest @ ..] => TailwindZIndex::parse(rest, arbitrary, neg)?.boxed(),
55            // Flexbox & Grid
56            ["basis", rest @ ..] => TailwindBasis::parse(rest, arbitrary)?.boxed(),
57            ["flex", rest @ ..] => TailwindFlex::adapt(rest, arbitrary)?,
58            ["grow", rest @ ..] => TailWindGrow::parse(rest, arbitrary)?.boxed(),
59            ["shrink", rest @ ..] => TailWindShrink::parse(rest, arbitrary)?.boxed(),
60            ["order", rest @ ..] => TailWindOrder::parse(rest, arbitrary, neg)?.boxed(),
61            ["grid", rest @ ..] => TailwindGrid::adapt(rest, arbitrary)?,
62            // https://tailwindcss.com/docs/grid-column
63            ["col", rest @ ..] => TailwindColumn::parse(rest, arbitrary)?.boxed(),
64            ["row", rest @ ..] => TailwindRow::parse(rest, arbitrary)?.boxed(),
65            ["auto", rest @ ..] => TailwindGridAuto::parse(rest, arbitrary)?.boxed(),
66            ["gap", rest @ ..] => TailwindGap::parse(rest, arbitrary)?.boxed(),
67            ["justify", rest @ ..] => justify_adaptor(rest, arbitrary)?,
68            ["content", rest @ ..] => TailwindContent::adapt(rest, arbitrary)?,
69            ["items", rest @ ..] => TailwindItems::parse(rest, arbitrary)?.boxed(),
70            ["self", rest @ ..] => TailwindSelf::parse(rest, arbitrary)?.boxed(),
71            ["place", rest @ ..] => TailwindPlace::adapt(rest, arbitrary)?,
72            // justify catched
73            // Spacing System
74            ["p" | "pl" | "pr" | "pb" | "pt" | "px" | "py", ..] => TailwindPadding::parse(pattern, arbitrary, neg)?.boxed(),
75            ["m" | "ml" | "mr" | "mb" | "mt" | "mx" | "my", ..] => TailwindMargin::parse(pattern, arbitrary, neg)?.boxed(),
76            ["space", rest @ ..] => TailwindSpace::parse(rest, arbitrary, neg)?,
77            // Sizing System
78            ["w", rest @ ..] => TailwindSizing::parse_width(rest, arbitrary)?.boxed(),
79            ["min", "w", rest @ ..] => TailwindSizing::parse_width_min(rest, arbitrary)?.boxed(),
80            ["max", "w", rest @ ..] => TailwindSizing::parse_width_max(rest, arbitrary)?.boxed(),
81            ["h", rest @ ..] => TailwindSizing::parse_height(rest, arbitrary)?.boxed(),
82            ["min", "h", rest @ ..] => TailwindSizing::parse_height_min(rest, arbitrary)?.boxed(),
83            ["max", "h", rest @ ..] => TailwindSizing::parse_height_max(rest, arbitrary)?.boxed(),
84            // Typography System
85            ["font", rest @ ..] => font_adaptor(rest, arbitrary)?,
86            ["text", rest @ ..] => text_adaptor(rest, arbitrary)?,
87            // begin https://tailwindcss.com/docs/font-variant-numeric
88            ["antialiased"] => TailwindFontSmoothing::from("todo").boxed(),
89            ["subpixel", "antialiased"] => TailwindFontSmoothing::from("todo").boxed(),
90            ["italic"] => TailwindFontStyle::from("italic").boxed(),
91            ["not", "italic"] => TailwindFontStyle::from("normal").boxed(),
92            // https://tailwindcss.com/docs/font-variant-numeric
93            ["normal", "nums"] => TailwindFontVariantNumeric::from("normal").boxed(),
94            ["ordinal"] => TailwindFontVariantNumeric::from("ordinal").boxed(),
95            ["slashed", "zero"] => TailwindFontVariantNumeric::from("slashed-zero").boxed(),
96            ["lining", "nums"] => TailwindFontVariantNumeric::from("lining-nums").boxed(),
97            ["oldstyle", "nums"] => TailwindFontVariantNumeric::from("oldstyle-nums").boxed(),
98            ["proportional", "nums"] => TailwindFontVariantNumeric::from("proportional-nums").boxed(),
99            ["tabular", "nums"] => TailwindFontVariantNumeric::from("tabular-nums").boxed(),
100            ["diagonal", "fractions"] => TailwindFontVariantNumeric::from("diagonal-fractions").boxed(),
101            ["stacked", "fractions"] => TailwindFontVariantNumeric::from("stacked-fractions").boxed(),
102            // https://tailwindcss.com/docs/letter-spacing
103            ["tracking", rest @ ..] => TailwindTracking::parse(rest, arbitrary)?.boxed(),
104            ["leading", rest @ ..] => TailwindLeading::parse(rest, arbitrary)?.boxed(),
105            ["list", rest @ ..] => list_adaptor(rest, arbitrary)?,
106            // https://tailwindcss.com/docs/text-decoration
107            ["underline"] => TailwindDecorationLine::from("underline").boxed(),
108            ["overline"] => TailwindDecorationLine::from("overline").boxed(),
109            ["line", "through"] => TailwindDecorationLine::from("line-through").boxed(),
110            ["no", "underline"] => TailwindDecorationLine::from("none").boxed(),
111            // https://tailwindcss.com/docs/text-decoration-color
112            ["decoration", rest @ ..] => TailwindDecoration::adapt(rest, arbitrary)?,
113            ["underline", "offset", rest @ ..] => TailwindUnderlineOffset::parse(rest, arbitrary)?.boxed(),
114            // https://tailwindcss.com/docs/text-transform
115            ["uppercase"] => TailwindTextTransform::from("uppercase").boxed(),
116            ["lowercase"] => TailwindTextTransform::from("lowercase").boxed(),
117            ["capitalize"] => TailwindTextTransform::from("capitalize").boxed(),
118            ["normal", "case"] => TailwindTextTransform::from("none").boxed(),
119            // https://tailwindcss.com/docs/text-overflow
120            ["truncate"] => TailwindTextOverflow::Truncate.boxed(),
121            ["indent", rest @ ..] => TailwindIndent::parse(rest, arbitrary)?.boxed(),
122            ["align", rest @ ..] => TailwindAlign::parse(rest, arbitrary)?.boxed(),
123            ["whitespace", rest @ ..] => TailwindWhiteSpace::parse(rest, arbitrary)?.boxed(),
124            // break catched
125            // content catched
126            // Typography System Extension
127            ["prose"] => todo!(),
128            // Backgrounds System
129            ["bg", rest @ ..] => Self::bg_adaptor(rest, arbitrary, neg)?,
130            ["from", rest @ ..] => TailwindFrom::parse(rest, arbitrary)?.boxed(),
131            ["via", rest @ ..] => TailwindVia::parse(rest, arbitrary)?.boxed(),
132            ["to", rest @ ..] => TailwindTo::parse(rest, arbitrary)?.boxed(),
133            // Borders System
134            ["rounded", rest @ ..] => TailwindRounded::parse(rest, arbitrary)?.boxed(),
135            ["border", rest @ ..] => Self::border_adaptor(rest, arbitrary)?,
136            ["divide", rest @ ..] => TailwindDivide::adapt(rest, arbitrary)?,
137            ["outline", rest @ ..] => outline_adaptor(rest, arbitrary)?,
138            ["ring", rest @ ..] => ring_adaptor(rest, arbitrary)?,
139            // Effects System
140            ["shadow", rest @ ..] => Self::shadow_adaptor(rest, arbitrary)?,
141            ["opacity", rest @ ..] => TailwindOpacity::parse(rest, arbitrary, false)?.boxed(),
142            ["mix", "blend", rest @ ..] => TailwindBlend::parse(rest, arbitrary)?.boxed(),
143            ["mask", rest @ ..] => mask_adaptor(rest, arbitrary, neg)?,
144            // Filters System
145            ["blur", rest @ ..] => TailwindBlur::parse(rest, arbitrary, false)?.boxed(),
146            ["brightness", rest @ ..] => TailwindBrightness::parse(rest, arbitrary, false)?.boxed(),
147            ["contrast", rest @ ..] => TailwindContrast::parse(rest, arbitrary, false)?.boxed(),
148            ["drop", "shadow", rest @ ..] => TailwindShadow::parse(rest, arbitrary, true)?.boxed(),
149            ["grayscale", rest @ ..] => TailwindGrayscale::parse(rest, arbitrary, false)?.boxed(),
150            ["hue", "rotate", rest @ ..] => TailwindHueRotate::parse(rest, arbitrary, false, neg)?.boxed(),
151            ["invert", rest @ ..] => TailwindInvert::parse(rest, arbitrary, false)?.boxed(),
152            ["saturate", rest @ ..] => TailwindSaturate::parse(rest, arbitrary, false)?.boxed(),
153            ["sepia", rest @ ..] => TailwindSepia::parse(rest, arbitrary, false)?.boxed(),
154            ["backdrop", rest @ ..] => Self::backdrop_adaptor(rest, arbitrary, neg)?,
155            // Tables System
156            ["table", rest @ ..] => Self::table_adaptor(rest, arbitrary)?,
157            // Transitions System
158            ["transition", rest @ ..] => TailwindTransition::parse(rest, arbitrary)?.boxed(),
159            ["duration", rest @ ..] => TailwindDuration::parse(rest, arbitrary)?.boxed(),
160            ["ease", rest @ ..] => TailwindEase::parse(rest, arbitrary)?.boxed(),
161            ["delay", rest @ ..] => TailwindDelay::parse(rest, arbitrary)?.boxed(),
162            ["animate", rest @ ..] => TailwindAnimate::parse(rest, arbitrary)?.boxed(),
163            // Transforms System
164            ["scale", rest @ ..] => TailwindScale::parse(rest, arbitrary, neg)?.boxed(),
165            ["rotate", rest @ ..] => TailwindRotate::parse(rest, arbitrary, neg)?.boxed(),
166            ["translate", rest @ ..] => TailwindTranslate::parse(rest, arbitrary, neg)?.boxed(),
167            ["skew", rest @ ..] => TailwindSkew::parse(rest, arbitrary, neg)?.boxed(),
168            ["origin", rest @ ..] => TailwindOrigin::parse(rest, arbitrary)?.boxed(),
169            // Interactivity System
170            ["accent", rest @ ..] => TailwindAccentColor::parse(rest, arbitrary)?.boxed(),
171            // https://tailwindcss.com/docs/appearance
172            ["appearance", rest @ ..] => TailwindAppearance::parse(rest, arbitrary)?.boxed(),
173            ["cursor", rest @ ..] => TailwindCursor::parse(rest, arbitrary)?.boxed(),
174            ["caret", rest @ ..] => TailwindCaretColor::parse(rest, arbitrary)?.boxed(),
175            ["pointer", "events", rest @ ..] => TailwindPointerEvents::parse(rest, arbitrary)?.boxed(),
176            ["resize", rest @ ..] => TailwindResize::parse(rest, arbitrary)?.boxed(),
177            ["scroll", rest @ ..] => scroll_adaptor(rest, arbitrary, neg)?,
178            ["snap", rest @ ..] => snap_adaptor(rest, arbitrary)?,
179            ["touch", rest @ ..] => TailwindTorch::parse(rest, arbitrary)?.boxed(),
180            ["select", rest @ ..] => TailwindSelect::parse(rest, arbitrary)?.boxed(),
181            ["will", "change", rest @ ..] => TailwindWillChange::parse(rest, arbitrary)?.boxed(),
182            // SVG System
183            ["fill", rest @ ..] => TailwindFillColor::parse(rest, arbitrary)?.boxed(),
184            ["stroke", rest @ ..] => TailwindStroke::parse(rest, arbitrary)?,
185            // Accessibility System
186            ["sr", "only"] => TailwindScreenReader::new(true).boxed(),
187            ["not", "sr", "only"] => TailwindScreenReader::new(false).boxed(),
188            // Contextual Markers for Variants
189            ["peer"] => TailwindVariantMarker::parse(pattern, arbitrary)?.boxed(),
190            ["group"] => TailwindVariantMarker::parse(pattern, arbitrary)?.boxed(),
191            // Form System Extension
192            _ => return syntax_error!("Unknown instructions: {} + {}", element.join("-"), arbitrary.get_class()),
193        };
194        Ok(instance)
195    }
196    #[inline]
197    fn bg_adaptor(pattern: &[&str], arbitrary: &TailwindArbitrary, neg: Negative) -> Result<Box<dyn TailwindInstance>> {
198        let out = match pattern {
199            // https://tailwindcss.com/docs/background-attachment
200            [s @ ("fixed" | "local" | "scroll")] => TailwindBackgroundAttachment::from(*s).boxed(),
201            ["attach", rest @ ..] => TailwindBackgroundAttachment::parse(rest, arbitrary)?.boxed(),
202            // https://tailwindcss.com/docs/background-clip
203            ["clip", rest @ ..] => TailwindBackgroundClip::parse(rest, arbitrary)?.boxed(),
204            // https://tailwindcss.com/docs/background-origin
205            ["origin", rest @ ..] => TailwindBackgroundOrigin::parse(rest, arbitrary)?.boxed(),
206            // https://tailwindcss.com/docs/background-repeat
207            ["no", "repeat"] => TailwindBackgroundRepeat::from("no-repeat").boxed(),
208            ["repeat", rest @ ..] => TailwindBackgroundRepeat::parse(rest, arbitrary)?.boxed(),
209            // https://tailwindcss.com/docs/background-size
210            [s @ ("auto" | "cover" | "contain")] => TailwindBackgroundSize::from(*s).boxed(),
211            ["size", rest @ ..] => TailwindBackgroundSize::parse(rest, arbitrary)?.boxed(),
212            // https://tailwindcss.com/docs/background-blend-mode
213            ["blend", rest @ ..] => TailwindBackgroundBlend::parse(rest, arbitrary)?.boxed(),
214            // https://tailwindcss.com/docs/background-image
215            // https://v3.tailwindcss.com/docs/background-image (bg-gradient-* alias for linear)
216            ["none"] | ["gradient" | "linear" | "radial" | "conic", ..] => {
217                TailwindBackgroundImage::parse(pattern, arbitrary, neg)?.boxed()
218            }
219            [] => {
220                if arbitrary.as_str().starts_with("url(") || arbitrary.as_str().contains("gradient(") {
221                    TailwindBackgroundImage::parse(pattern, arbitrary, neg)?.boxed()
222                } else {
223                    // Otherwise, assume arbitrary color.
224                    TailwindBackgroundColor::parse(pattern, arbitrary)?.boxed()
225                }
226            }
227            _ => TailwindBackgroundColor::parse(pattern, arbitrary)?.boxed()
228        };
229        Ok(out)
230    }
231    #[inline]
232    fn border_adaptor(pattern: &[&str], arbitrary: &TailwindArbitrary) -> Result<Box<dyn TailwindInstance>> {
233        let color = |color| TailwindBorderColor::from(color).boxed();
234        let out = match pattern {
235            // https://tailwindcss.com/docs/border-style
236            [s @ ("solid" | "dashed" | "dotted" | "double" | "hidden" | "none")] => TailwindBorderStyle::from(*s).boxed(),
237            // https://tailwindcss.com/docs/border-collapse
238            ["separate"] => TailwindBorderCollapse::from("separate").boxed(),
239            ["collapse"] if arbitrary.is_none() => TailwindBorderCollapse::from("collapse").boxed(),
240            ["collapse", rest @ ..] => TailwindBorderCollapse::parse(rest, arbitrary)?.boxed(),
241            // https://tailwindcss.com/docs/border-width
242            [] => {
243                if arbitrary.as_str().starts_with('#') {
244                    TailwindBorderColor::from(arbitrary.as_color()?).boxed()
245                } else {
246                    TailwindBorderWidth::parse(pattern, arbitrary)?.boxed()
247                }
248            }, // e.g. border-[3px] or border-[#hex]
249            ["0" | "2" | "4" | "8", ..] if arbitrary.is_none() => TailwindBorderWidth::parse(pattern, arbitrary)?.boxed(), // e.g. border-4
250            ["x" | "y" | "t" | "r" | "b" | "l", ..] => TailwindBorderWidth::parse(pattern, arbitrary)?.boxed(), // e.g. border-x-2
251            // https://tailwindcss.com/docs/border-color
252            ["black"] => color(TailwindColor::Black),
253            ["white"] => color(TailwindColor::White),
254            // Alternate way to define color, e.g., border-color-<color>
255            ["color", rest @ ..] => TailwindBorderColor::parse(rest, arbitrary)?.boxed(),
256            _ => TailwindBorderColor::parse(pattern, arbitrary)?.boxed(),
257        };
258        Ok(out)
259    }
260    #[inline]
261    fn shadow_adaptor(pattern: &[&str], arbitrary: &TailwindArbitrary) -> Result<Box<dyn TailwindInstance>> {
262        let out = match pattern {
263            // https://tailwindcss.com/docs/box-shadow
264            ["black" | "white" | "current" | "transparent"] => TailwindShadowColor::parse(pattern, arbitrary)?.boxed(),
265            ["color", rest @ ..] => TailwindShadowColor::parse(rest, arbitrary)?.boxed(),
266            // https://tailwindcss.com/docs/box-shadow-color
267            _ => TailwindShadow::parse(pattern, arbitrary, false)?.boxed(),
268        };
269        Ok(out)
270    }
271    #[inline]
272    fn box_adaptor(str: &[&str], arbitrary: &TailwindArbitrary) -> Result<Box<dyn TailwindInstance>> {
273        let out = match str {
274            // https://tailwindcss.com/docs/box-decoration-break
275            ["decoration" | "break", rest @ ..] => TailwindBoxDecoration::parse(rest, arbitrary)?.boxed(),
276            ["clone"] => TailwindBoxDecoration::from("clone").boxed(),
277            ["slice"] => TailwindBoxDecoration::from("slice").boxed(),
278            // https://tailwindcss.com/docs/box-sizing
279            ["border"] => TailwindBoxSizing::from("border-box").boxed(),
280            ["content"] => TailwindBoxSizing::from("content-box").boxed(),
281            ["sizing", rest @ ..] => TailwindBoxSizing::parse(rest, arbitrary)?.boxed(),
282            _ => return syntax_error!("Unknown box instructions: {}", str.join("-")),
283        };
284        Ok(out)
285    }
286
287    #[inline]
288    fn backdrop_adaptor(str: &[&str], arbitrary: &TailwindArbitrary, negative: Negative) -> Result<Box<dyn TailwindInstance>> {
289        let out = match str {
290            // https://tailwindcss.com/docs/backdrop-blur
291            ["blur", rest @ ..] => TailwindBlur::parse(rest, arbitrary, true)?.boxed(),
292            // https://tailwindcss.com/docs/backdrop-brightness
293            ["brightness", rest @ ..] => TailwindBrightness::parse(rest, arbitrary, true)?.boxed(),
294            // https://tailwindcss.com/docs/backdrop-contrast
295            ["contrast", rest @ ..] => TailwindContrast::parse(rest, arbitrary, true)?.boxed(),
296            // https://tailwindcss.com/docs/backdrop-grayscale
297            ["grayscale", rest @ ..] => TailwindGrayscale::parse(rest, arbitrary, true)?.boxed(),
298            // https://tailwindcss.com/docs/backdrop-hue-rotate
299            ["hue", "rotate", rest @ ..] => TailwindHueRotate::parse(rest, arbitrary, true, negative)?.boxed(),
300            // https://tailwindcss.com/docs/backdrop-invert
301            ["invert", rest @ ..] => TailwindInvert::parse(rest, arbitrary, true)?.boxed(),
302            // https://tailwindcss.com/docs/backdrop-opacity
303            ["opacity", rest @ ..] => TailwindOpacity::parse(rest, arbitrary, true)?.boxed(),
304            // https://tailwindcss.com/docs/backdrop-saturate
305            ["saturate", rest @ ..] => TailwindSaturate::parse(rest, arbitrary, true)?.boxed(),
306            // https://tailwindcss.com/docs/backdrop-sepia
307            ["sepia", rest @ ..] => TailwindSepia::parse(rest, arbitrary, true)?.boxed(),
308            _ => return syntax_error!("Unknown backdrop instructions: {}", str.join("-")),
309        };
310        Ok(out)
311    }
312    #[inline]
313    fn table_adaptor(pattern: &[&str], arbitrary: &TailwindArbitrary) -> Result<Box<dyn TailwindInstance>> {
314        let out = match pattern {
315            // https://tailwindcss.com/docs/display#flex
316            [] if arbitrary.is_none() => TailwindDisplay::from("table").boxed(),
317            ["caption"] => TailwindDisplay::from("table-caption").boxed(),
318            ["cell"] => TailwindDisplay::from("table-cell").boxed(),
319            ["column"] => TailwindDisplay::from("table-column").boxed(),
320            ["column", "group"] => TailwindDisplay::from("table-column-group").boxed(),
321            ["footer", "group"] => TailwindDisplay::from("table-footer-group").boxed(),
322            ["header", "group"] => TailwindDisplay::from("table-header-group").boxed(),
323            ["row", "group"] => TailwindDisplay::from("table-row-group").boxed(),
324            ["row"] => TailwindDisplay::from("table-row").boxed(),
325            // https://tailwindcss.com/docs/table-layout
326            _ => TailwindTableLayout::parse(pattern, arbitrary)?.boxed(),
327        };
328        Ok(out)
329    }
330}