Skip to main content

oxc_css_parser/parser/
convert.rs

1use crate::{
2    Span,
3    ast::{
4        Dimension, DimensionKind, Ident, InterpolableIdentStaticPart, InterpolableStrStaticPart,
5        InterpolableUrlStaticPart, Number, Placeholder, Str,
6    },
7    error::{Error, ErrorKind, PResult},
8    tokenizer::token,
9};
10
11impl<'a> TryFrom<(token::Dimension<'a>, Span)> for Dimension<'a> {
12    type Error = Error;
13
14    fn try_from((token, span): (token::Dimension<'a>, Span)) -> PResult<Self> {
15        let value_span = Span { start: span.start, end: span.start + token.value.raw.len() };
16        let unit_span = Span { start: span.start + token.value.raw.len(), end: span.end };
17
18        let value = (token.value, value_span).try_into()?;
19        let unit = Ident::from((token.unit, unit_span));
20        let kind = dimension_kind(unit.name);
21
22        Ok(Dimension { value, unit, kind, span })
23    }
24}
25
26pub(super) fn dimension_kind(unit_name: &str) -> DimensionKind {
27    if unit_name.eq_ignore_ascii_case("px")
28        || unit_name.eq_ignore_ascii_case("em")
29        || unit_name.eq_ignore_ascii_case("rem")
30        || unit_name.eq_ignore_ascii_case("ex")
31        || unit_name.eq_ignore_ascii_case("rex")
32        || unit_name.eq_ignore_ascii_case("cap")
33        || unit_name.eq_ignore_ascii_case("rcap")
34        || unit_name.eq_ignore_ascii_case("ch")
35        || unit_name.eq_ignore_ascii_case("rch")
36        || unit_name.eq_ignore_ascii_case("ic")
37        || unit_name.eq_ignore_ascii_case("ric")
38        || unit_name.eq_ignore_ascii_case("lh")
39        || unit_name.eq_ignore_ascii_case("rlh")
40        || unit_name.eq_ignore_ascii_case("vw")
41        || unit_name.eq_ignore_ascii_case("vh")
42        || unit_name.eq_ignore_ascii_case("vi")
43        || unit_name.eq_ignore_ascii_case("vb")
44        || unit_name.eq_ignore_ascii_case("vmin")
45        || unit_name.eq_ignore_ascii_case("vmax")
46        || unit_name.eq_ignore_ascii_case("lvw")
47        || unit_name.eq_ignore_ascii_case("lvh")
48        || unit_name.eq_ignore_ascii_case("lvi")
49        || unit_name.eq_ignore_ascii_case("lvb")
50        || unit_name.eq_ignore_ascii_case("lvmin")
51        || unit_name.eq_ignore_ascii_case("lvmax")
52        || unit_name.eq_ignore_ascii_case("svw")
53        || unit_name.eq_ignore_ascii_case("svh")
54        || unit_name.eq_ignore_ascii_case("svi")
55        || unit_name.eq_ignore_ascii_case("svb")
56        || unit_name.eq_ignore_ascii_case("vmin")
57        || unit_name.eq_ignore_ascii_case("vmax")
58        || unit_name.eq_ignore_ascii_case("dvw")
59        || unit_name.eq_ignore_ascii_case("dvh")
60        || unit_name.eq_ignore_ascii_case("dvi")
61        || unit_name.eq_ignore_ascii_case("dvb")
62        || unit_name.eq_ignore_ascii_case("dvmin")
63        || unit_name.eq_ignore_ascii_case("dvmax")
64        || unit_name.eq_ignore_ascii_case("cm")
65        || unit_name.eq_ignore_ascii_case("mm")
66        || unit_name.eq_ignore_ascii_case("Q")
67        || unit_name.eq_ignore_ascii_case("in")
68        || unit_name.eq_ignore_ascii_case("pc")
69        || unit_name.eq_ignore_ascii_case("pt")
70    {
71        DimensionKind::Length
72    } else if unit_name.eq_ignore_ascii_case("deg")
73        || unit_name.eq_ignore_ascii_case("grad")
74        || unit_name.eq_ignore_ascii_case("rad")
75        || unit_name.eq_ignore_ascii_case("turn")
76    {
77        DimensionKind::Angle
78    } else if unit_name.eq_ignore_ascii_case("s") || unit_name.eq_ignore_ascii_case("ms") {
79        DimensionKind::Duration
80    } else if unit_name.eq_ignore_ascii_case("Hz") || unit_name.eq_ignore_ascii_case("kHz") {
81        DimensionKind::Frequency
82    } else if unit_name.eq_ignore_ascii_case("dpi")
83        || unit_name.eq_ignore_ascii_case("dpcm")
84        || unit_name.eq_ignore_ascii_case("dppx")
85    {
86        DimensionKind::Resolution
87    } else if unit_name.eq_ignore_ascii_case("fr") {
88        DimensionKind::Flex
89    } else {
90        DimensionKind::Unknown
91    }
92}
93
94impl<'a> From<(token::Ident<'a>, Span)> for Ident<'a> {
95    fn from((token, span): (token::Ident<'a>, Span)) -> Self {
96        Ident { name: token.raw, raw: token.raw, span }
97    }
98}
99
100impl<'a> From<(token::Placeholder<'a>, Span)> for Placeholder<'a> {
101    fn from((token, span): (token::Placeholder<'a>, Span)) -> Self {
102        Placeholder { index: token.index, suffix: token.suffix, span }
103    }
104}
105
106impl<'a> From<(token::Ident<'a>, Span)> for InterpolableIdentStaticPart<'a> {
107    fn from((token, span): (token::Ident<'a>, Span)) -> Self {
108        InterpolableIdentStaticPart { value: token.raw, raw: token.raw, span }
109    }
110}
111
112impl<'a> TryFrom<(token::Number<'a>, Span)> for Number<'a> {
113    type Error = Error;
114
115    fn try_from((token, span): (token::Number<'a>, Span)) -> PResult<Self> {
116        token
117            .raw
118            .parse()
119            .map_err(|_| Error { kind: ErrorKind::InvalidNumber, span: span.clone() })
120            .map(|value| Self { value, raw: token.raw, span })
121    }
122}
123
124impl<'a> From<(token::StrTemplate<'a>, Span)> for InterpolableStrStaticPart<'a> {
125    fn from((token, span): (token::StrTemplate<'a>, Span)) -> Self {
126        let raw_without_quotes = if token.tail {
127            unsafe { token.raw.get_unchecked(0..token.raw.len() - 1) }
128        } else if token.head {
129            unsafe { token.raw.get_unchecked(1..token.raw.len()) }
130        } else {
131            token.raw
132        };
133        let value = raw_without_quotes;
134        Self { value, raw: token.raw, span }
135    }
136}
137
138impl<'a> From<(token::UrlTemplate<'a>, Span)> for InterpolableUrlStaticPart<'a> {
139    fn from((token, span): (token::UrlTemplate<'a>, Span)) -> Self {
140        let value = token.raw;
141        Self { value, raw: token.raw, span }
142    }
143}
144
145impl<'a> From<(token::Str<'a>, Span)> for Str<'a> {
146    fn from((str, span): (token::Str<'a>, Span)) -> Self {
147        let raw_without_quotes = unsafe { str.raw.get_unchecked(1..str.raw.len() - 1) };
148        let value = raw_without_quotes;
149        Self { value, raw: str.raw, span }
150    }
151}