/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include #include #include #include namespace facebook::react { /** * One of any predefined CSS keywords. * https://www.w3.org/TR/css-values-4/#keywords */ enum class CSSKeyword : uint8_t { Absolute, Auto, Baseline, Block, Center, Clip, Column, ColumnReverse, Content, Contents, Dashed, Dotted, Double, End, Fixed, Flex, FlexEnd, FlexStart, Grid, Groove, Hidden, Inherit, Initial, Inline, InlineBlock, InlineFlex, InlineGrid, Inset, Ltr, MaxContent, Medium, MinContent, None, Normal, NoWrap, Outset, Relative, Ridge, Row, RowReverse, Rtl, Scroll, Solid, SpaceAround, SpaceBetween, SpaceEvenly, Start, Static, Sticky, Stretch, Thick, Thin, Unset, Visible, Wrap, WrapReverse, }; /** * Represents a contrained set of CSS keywords. */ template concept CSSKeywordSet = std::is_enum_v && std:: is_same_v, std::underlying_type_t>; /** * CSS-wide keywords. * https://www.w3.org/TR/css-values-4/#common-keywords */ enum class CSSWideKeyword : std::underlying_type_t { Inherit = to_underlying(CSSKeyword::Inherit), Initial = to_underlying(CSSKeyword::Initial), Unset = to_underlying(CSSKeyword::Unset), }; /** * Defines a concept for whether an enum has a given member. */ #define CSS_DEFINE_KEYWORD_CONEPTS(name) \ namespace detail { \ template \ concept has##name = (CSSKeywordSet && requires() { T::name; }); \ } CSS_DEFINE_KEYWORD_CONEPTS(Absolute) CSS_DEFINE_KEYWORD_CONEPTS(Auto) CSS_DEFINE_KEYWORD_CONEPTS(Baseline) CSS_DEFINE_KEYWORD_CONEPTS(Block) CSS_DEFINE_KEYWORD_CONEPTS(Center) CSS_DEFINE_KEYWORD_CONEPTS(Clip) CSS_DEFINE_KEYWORD_CONEPTS(Column) CSS_DEFINE_KEYWORD_CONEPTS(ColumnReverse) CSS_DEFINE_KEYWORD_CONEPTS(Content) CSS_DEFINE_KEYWORD_CONEPTS(Contents) CSS_DEFINE_KEYWORD_CONEPTS(Dashed) CSS_DEFINE_KEYWORD_CONEPTS(Dotted) CSS_DEFINE_KEYWORD_CONEPTS(Double) CSS_DEFINE_KEYWORD_CONEPTS(End) CSS_DEFINE_KEYWORD_CONEPTS(Fixed) CSS_DEFINE_KEYWORD_CONEPTS(Flex) CSS_DEFINE_KEYWORD_CONEPTS(FlexEnd) CSS_DEFINE_KEYWORD_CONEPTS(FlexStart) CSS_DEFINE_KEYWORD_CONEPTS(Grid) CSS_DEFINE_KEYWORD_CONEPTS(Groove) CSS_DEFINE_KEYWORD_CONEPTS(Hidden) CSS_DEFINE_KEYWORD_CONEPTS(Inherit) CSS_DEFINE_KEYWORD_CONEPTS(Initial) CSS_DEFINE_KEYWORD_CONEPTS(Inline) CSS_DEFINE_KEYWORD_CONEPTS(InlineBlock) CSS_DEFINE_KEYWORD_CONEPTS(InlineFlex) CSS_DEFINE_KEYWORD_CONEPTS(InlineGrid) CSS_DEFINE_KEYWORD_CONEPTS(Inset) CSS_DEFINE_KEYWORD_CONEPTS(Ltr) CSS_DEFINE_KEYWORD_CONEPTS(MaxContent) CSS_DEFINE_KEYWORD_CONEPTS(Medium) CSS_DEFINE_KEYWORD_CONEPTS(MinContent) CSS_DEFINE_KEYWORD_CONEPTS(None) CSS_DEFINE_KEYWORD_CONEPTS(Normal) CSS_DEFINE_KEYWORD_CONEPTS(NoWrap) CSS_DEFINE_KEYWORD_CONEPTS(Outset) CSS_DEFINE_KEYWORD_CONEPTS(Relative) CSS_DEFINE_KEYWORD_CONEPTS(Ridge) CSS_DEFINE_KEYWORD_CONEPTS(Row) CSS_DEFINE_KEYWORD_CONEPTS(RowReverse) CSS_DEFINE_KEYWORD_CONEPTS(Rtl) CSS_DEFINE_KEYWORD_CONEPTS(Scroll) CSS_DEFINE_KEYWORD_CONEPTS(Solid) CSS_DEFINE_KEYWORD_CONEPTS(SpaceAround) CSS_DEFINE_KEYWORD_CONEPTS(SpaceBetween) CSS_DEFINE_KEYWORD_CONEPTS(SpaceEvenly) CSS_DEFINE_KEYWORD_CONEPTS(Start) CSS_DEFINE_KEYWORD_CONEPTS(Static) CSS_DEFINE_KEYWORD_CONEPTS(Sticky) CSS_DEFINE_KEYWORD_CONEPTS(Stretch) CSS_DEFINE_KEYWORD_CONEPTS(Thick) CSS_DEFINE_KEYWORD_CONEPTS(Thin) CSS_DEFINE_KEYWORD_CONEPTS(Unset) CSS_DEFINE_KEYWORD_CONEPTS(Visible) CSS_DEFINE_KEYWORD_CONEPTS(Wrap) CSS_DEFINE_KEYWORD_CONEPTS(WrapReverse) /** * Parses an ident token, case-insensitive, into a keyword. * * Returns KeywordT::Unset if the ident does not match any entries * in the keyword-set, or CSS-wide keywords. */ template constexpr std::optional parseCSSKeyword(std::string_view ident) { struct LowerCaseTransform { constexpr char operator()(char c) const { if (c >= 'A' && c <= 'Z') { return c + static_cast('a' - 'A'); } return c; } }; switch (fnv1a(ident)) { case fnv1a("absolute"): if constexpr (detail::hasAbsolute) { return KeywordT::Absolute; } break; case fnv1a("auto"): if constexpr (detail::hasAuto) { return KeywordT::Auto; } break; case fnv1a("baseline"): if constexpr (detail::hasBaseline) { return KeywordT::Baseline; } break; case fnv1a("block"): if constexpr (detail::hasBlock) { return KeywordT::Block; } break; case fnv1a("center"): if constexpr (detail::hasCenter) { return KeywordT::Center; } break; case fnv1a("clip"): if constexpr (detail::hasClip) { return KeywordT::Clip; } break; case fnv1a("column"): if constexpr (detail::hasColumn) { return KeywordT::Column; } break; case fnv1a("column-reverse"): if constexpr (detail::hasColumnReverse) { return KeywordT::ColumnReverse; } break; case fnv1a("content"): if constexpr (detail::hasContent) { return KeywordT::Content; } break; case fnv1a("contents"): if constexpr (detail::hasContents) { return KeywordT::Contents; } break; case fnv1a("dashed"): if constexpr (detail::hasDashed) { return KeywordT::Dashed; } break; case fnv1a("dotted"): if constexpr (detail::hasDotted) { return KeywordT::Dotted; } break; case fnv1a("double"): if constexpr (detail::hasDouble) { return KeywordT::Double; } break; case fnv1a("end"): if constexpr (detail::hasEnd) { return KeywordT::End; } break; case fnv1a("fixed"): if constexpr (detail::hasFixed) { return KeywordT::Fixed; } case fnv1a("flex"): if constexpr (detail::hasFlex) { return KeywordT::Flex; } break; case fnv1a("flex-end"): if constexpr (detail::hasFlexEnd) { return KeywordT::FlexEnd; } break; case fnv1a("flex-start"): if constexpr (detail::hasFlexStart) { return KeywordT::FlexStart; } break; case fnv1a("grid"): if constexpr (detail::hasGrid) { return KeywordT::Grid; } break; case fnv1a("groove"): if constexpr (detail::hasGroove) { return KeywordT::Groove; } break; case fnv1a("hidden"): if constexpr (detail::hasHidden) { return KeywordT::Hidden; } break; case fnv1a("inherit"): if constexpr (detail::hasInherit) { return KeywordT::Inherit; } break; case fnv1a("inline"): if constexpr (detail::hasInline) { return KeywordT::Inline; } break; case fnv1a("inline-block"): if constexpr (detail::hasInlineBlock) { return KeywordT::InlineBlock; } break; case fnv1a("inline-flex"): if constexpr (detail::hasInlineFlex) { return KeywordT::InlineFlex; } break; case fnv1a("inline-grid"): if constexpr (detail::hasInlineGrid) { return KeywordT::InlineGrid; } break; case fnv1a("ltr"): if constexpr (detail::hasLtr) { return KeywordT::Ltr; } break; case fnv1a("max-content"): if constexpr (detail::hasMaxContent) { return KeywordT::MaxContent; } break; case fnv1a("medium"): if constexpr (detail::hasMedium) { return KeywordT::Medium; } break; case fnv1a("min-content"): if constexpr (detail::hasMinContent) { return KeywordT::MinContent; } break; case fnv1a("none"): if constexpr (detail::hasNone) { return KeywordT::None; } break; case fnv1a("normal"): if constexpr (detail::hasNormal) { return KeywordT::Normal; } break; case fnv1a("nowrap"): if constexpr (detail::hasNoWrap) { return KeywordT::NoWrap; } break; case fnv1a("outset"): if constexpr (detail::hasOutset) { return KeywordT::Outset; } break; case fnv1a("relative"): if constexpr (detail::hasRelative) { return KeywordT::Relative; } break; case fnv1a("ridge"): if constexpr (detail::hasRidge) { return KeywordT::Ridge; } break; case fnv1a("row"): if constexpr (detail::hasRow) { return KeywordT::Row; } break; case fnv1a("row-reverse"): if constexpr (detail::hasRowReverse) { return KeywordT::RowReverse; } break; case fnv1a("rtl"): if constexpr (detail::hasRtl) { return KeywordT::Rtl; } break; case fnv1a("space-between"): if constexpr (detail::hasSpaceBetween) { return KeywordT::SpaceBetween; } break; case fnv1a("space-around"): if constexpr (detail::hasSpaceAround) { return KeywordT::SpaceAround; } break; case fnv1a("space-evenly"): if constexpr (detail::hasSpaceEvenly) { return KeywordT::SpaceEvenly; } break; case fnv1a("scroll"): if constexpr (detail::hasScroll) { return KeywordT::Scroll; } break; case fnv1a("solid"): if constexpr (detail::hasSolid) { return KeywordT::Solid; } break; case fnv1a("start"): if constexpr (detail::hasStart) { return KeywordT::Start; } case fnv1a("static"): if constexpr (detail::hasStatic) { return KeywordT::Static; } break; case fnv1a("sticky"): if constexpr (detail::hasSticky) { return KeywordT::Sticky; } break; case fnv1a("stretch"): if constexpr (detail::hasStretch) { return KeywordT::Stretch; } break; case fnv1a("thick"): if constexpr (detail::hasThick) { return KeywordT::Thick; } break; case fnv1a("thin"): if constexpr (detail::hasThin) { return KeywordT::Thin; } break; case fnv1a("unset"): if constexpr (detail::hasUnset) { return KeywordT::Unset; } break; case fnv1a("visible"): if constexpr (detail::hasVisible) { return KeywordT::Visible; } break; case fnv1a("wrap"): if constexpr (detail::hasWrap) { return KeywordT::Wrap; } break; case fnv1a("wrap-reverse"): if constexpr (detail::hasWrapReverse) { return KeywordT::WrapReverse; } break; default: break; } return std::nullopt; } } // namespace facebook::react