1use {
5 crate::{parsers::{Parse, ParserContext}, CustomParseError, domain::units::{Unit,LengthUnit}},
6 super::{MediaExpressionKind::{self, *}, Ratio, MediaResolution, MediaGrid, ColorBitDepth, MediaOrientation, MediaScan, MediaUpdate, MediaOverflowBlock, MediaOverflowInline, MediaColorGamut, MediaPointer, MediaHover, MediaTransform3D, Device, MediaColorIndex, MonochromeBitDepth, ColorScheme, ReducedMotion},
7 super::Range::*,
8 cssparser::{ParseError, Parser, ToCss},
9 std::fmt,
10};
11
12#[derive(Clone, Debug, PartialEq)]
14pub struct MediaExpression(pub MediaExpressionKind);
15
16impl ToCss for MediaExpression
17{
18 fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result
19 {
20 #[inline(always)]
21 fn write<W: fmt::Write, T: ToCss>(dest: &mut W, name: &str, value: &T) -> fmt::Result
22 {
23 dest.write_char('(')?;
24 dest.write_str(name)?;
25 dest.write_char(':')?;
26 value.to_css(dest)?;
27 dest.write_char(')')
28 }
29
30 match self.0
31 {
32 Width(AtLeast(ref value)) => write(dest, "min-width", value),
33
34 Width(AtMost(ref value)) => write(dest, "max-width", value),
35
36 Width(Exact(ref value)) => write(dest, "width", value),
37
38 Height(AtLeast(ref value)) => write(dest, "min-height", value),
39
40 Height(AtMost(ref value)) => write(dest, "max-height", value),
41
42 Height(Exact(ref value)) => write(dest, "height", value),
43
44 AspectRatio(AtLeast(ref value)) => write(dest, "min-aspect-ratio", value),
45
46 AspectRatio(AtMost(ref value)) => write(dest, "max-aspect-ratio", value),
47
48 AspectRatio(Exact(ref value)) => write(dest, "aspect-ratio", value),
49
50 Orientation(ref value) => write(dest, "orientation", value),
51
52 Resolution(AtLeast(ref value)) => write(dest, "min-resolution", value),
53
54 Resolution(AtMost(ref value)) => write(dest, "max-resolution", value),
55
56 Resolution(Exact(ref value)) => write(dest, "resolution", value),
57
58 Scan(ref value) => write(dest, "scan", value),
59
60 Grid(ref value) => write(dest, "grid", value),
61
62 Update(ref value) => write(dest, "update", value),
63
64 OverflowBlock(ref value) => write(dest, "overflow-block", value),
65
66 OverflowInline(ref value) => write(dest, "overflow-inline", value),
67
68 Color(AtLeast(ref value)) => write(dest, "min-color", value),
69
70 Color(AtMost(ref value)) => write(dest, "max-color", value),
71
72 Color(Exact(ref value)) => write(dest, "color", value),
73
74 ColorIndex(AtLeast(ref value)) => write(dest, "min-color-index", value),
75
76 ColorIndex(AtMost(ref value)) => write(dest, "max-color-index", value),
77
78 ColorIndex(Exact(ref value)) => write(dest, "color-index", value),
79
80 Monochrome(AtLeast(ref value)) => write(dest, "min-monochrome", value),
81
82 Monochrome(AtMost(ref value)) => write(dest, "max-monochrome", value),
83
84 Monochrome(Exact(ref value)) => write(dest, "monochrome", value),
85
86 ColorGamut(ref value) => write(dest, "color-gamut", value),
87
88 Pointer(ref value) => write(dest, "pointer", value),
89
90 Hover(ref value) => write(dest, "hover", value),
91
92 AnyPointer(ref value) => write(dest, "any-pointer", value),
93
94 AnyHover(ref value) => write(dest, "any-hover", value),
95
96 Transform3D(ref value) => write(dest, "-webkit-transform-3d", value),
97
98 PrefersColorScheme(ref value) => write(dest, "prefers-color-scheme", value),
99
100 PrefersReducedMotion(ref value) => write(dest, "prefers-reduced-motion", value),
101 }
102 }
103}
104
105impl MediaExpression
106{
107 pub(crate) fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, CustomParseError<'i>>>
108 {
109 input.expect_parenthesis_block()?;
110 input.parse_nested_block(|input|
111 {
112 let name = input.expect_ident_cloned()?;
113 input.expect_colon()?;
114
115 Ok
116 (
117 MediaExpression
118 (
119 match_ignore_ascii_case!
120 {
121 &name,
122
123 "min-width" => Width(AtLeast(LengthUnit::parse_one_outside_calc_function(context, input)?)),
124
125 "max-width" => Width(AtMost(LengthUnit::parse_one_outside_calc_function(context, input)?)),
126
127 "width" => Width(Exact(LengthUnit::parse_one_outside_calc_function(context, input)?)),
128
129 "min-height" => Height(AtLeast(LengthUnit::parse_one_outside_calc_function(context, input)?)),
130
131 "max-height" => Height(AtMost(LengthUnit::parse_one_outside_calc_function(context, input)?)),
132
133 "height" => Height(Exact(LengthUnit::parse_one_outside_calc_function(context, input)?)),
134
135 "min-aspect-ratio" => AspectRatio(AtLeast(Ratio::parse(context, input)?)),
136
137 "max-aspect-ratio" => AspectRatio(AtMost(Ratio::parse(context, input)?)),
138
139 "aspect-ratio" => AspectRatio(Exact(Ratio::parse(context, input)?)),
140
141 "orientation" => Orientation(MediaOrientation::parse(input)?),
142
143 "min-resolution" => Resolution(AtLeast(MediaResolution::parse(context, input)?)),
144
145 "max-resolution" => Resolution(AtLeast(MediaResolution::parse(context, input)?)),
146
147 "resolution" => Resolution(Exact(MediaResolution::parse(context, input)?)),
148
149 "-webkit-min-device-pixel-ratio" => Resolution(AtLeast(MediaResolution::parseWebKit(input)?)),
150
151 "-webkit-max-device-pixel-ratio" => Resolution(AtMost(MediaResolution::parseWebKit(input)?)),
152
153 "-webkit-device-pixel-ratio" => Resolution(Exact(MediaResolution::parseWebKit(input)?)),
154
155 "scan" => Scan(MediaScan::parse(input)?),
156
157 "grid" => Grid(MediaGrid::parse(context, input)?),
158
159 "update" => Update(MediaUpdate::parse(input)?),
160
161 "overflow-block" => OverflowBlock(MediaOverflowBlock::parse(input)?),
162
163 "overflow-inline" => OverflowInline(MediaOverflowInline::parse(input)?),
164
165 "min-color" => Color(AtLeast(ColorBitDepth::parse(context, input)?)),
166
167 "max-color" => Color(AtMost(ColorBitDepth::parse(context, input)?)),
168
169 "color" => Color(Exact(ColorBitDepth::parse(context, input)?)),
170
171 "min-color-index" => ColorIndex(AtLeast(MediaColorIndex::parse(context, input)?)),
172
173 "max-color-index" => ColorIndex(AtMost(MediaColorIndex::parse(context, input)?)),
174
175 "color-index" => ColorIndex(Exact(MediaColorIndex::parse(context, input)?)),
176
177 "min-monochrome" => Monochrome(AtLeast(MonochromeBitDepth::parse(context, input)?)),
178
179 "max-monochrome" => Monochrome(AtMost(MonochromeBitDepth::parse(context, input)?)),
180
181 "monochrome" => Monochrome(Exact(MonochromeBitDepth::parse(context, input)?)),
182
183 "color-gamut" => ColorGamut(MediaColorGamut::parse(input)?),
184
185 "pointer" => Pointer(MediaPointer::parse(input)?),
186
187 "hover" => Hover(MediaHover::parse(input)?),
188
189 "any-pointer" => AnyPointer(MediaPointer::parse(input)?),
190
191 "any-hover" => AnyHover(MediaHover::parse(input)?),
192
193 "-webkit-transform-3d" => Transform3D(MediaTransform3D::parse(context, input)?),
194
195 "prefers-color-scheme" => PrefersColorScheme(ColorScheme::parse(input)?),
196
197 "prefers-reduced-motion" => PrefersReducedMotion(ReducedMotion::parse(input)?),
198
199 "min-device-width" | "max-device-width" | "device-width" | "min-device-height" | "max-device-height" | "device-height" | "min-device-aspect-ratio" | "max-device-aspect-ratio" | "device-aspect-ratio" => return Err(ParseError::from(CustomParseError::DeprecatedMediaQueryExpression(name.clone()))),
200
201 _ => return Err(ParseError::from(CustomParseError::UnsupportedMediaQueryExpression(name.clone())))
202 }
203 )
204 )
205 })
206 }
207
208 pub fn matches<D: Device>(&self, device: &D) -> bool
210 {
211 use self::MediaExpressionKind::*;
212
213 match self.0
214 {
215 Width(ref range) => device.viewportWidthMatches(range),
216
217 Height(ref range) => device.viewportHeightMatches(range),
218
219 AspectRatio(ref range) => device.viewportAspectRatioMatches(range),
220
221 Orientation(orientation) => device.orientationMatches(orientation),
222
223 Resolution(ref range) => device.viewportResolutionMatches(range),
224
225 Scan(ref scan) => device.scanMatches(scan),
226
227 Grid(ref grid) => device.gridMatches(grid),
228
229 Update(ref update) => device.updateMatches(update),
230
231 OverflowBlock(ref overflowBlock) => device.overflowBlockMatches(overflowBlock),
232
233 OverflowInline(ref overflowInline) => device.overflowInlineMatches(overflowInline),
234
235 Color(ref range) => device.colorBitDepthMatches(range),
236
237 ColorIndex(ref range) => device.colorIndexMatches(range),
238
239 Monochrome(ref range) => device.monochromeBitDepthMatches(range),
240
241 ColorGamut(ref colorGamut) => device.colorGamutMatches(colorGamut),
242
243 Pointer(ref pointer) => device.pointerMatches(pointer),
244
245 Hover(ref hover) => device.hoverMatches(hover),
246
247 AnyPointer(ref pointer) => device.anyPointerMatches(pointer),
248
249 AnyHover(ref hover) => device.anyHoverMatches(hover),
250
251 Transform3D(ref transform3D) => device.transform3DMatches(transform3D),
252
253 PrefersColorScheme(ref prefers_color_scheme) => device.prefers_color_scheme(prefers_color_scheme),
254
255 PrefersReducedMotion(ref prefers_reduced_motion) => device.prefers_reduced_motion(prefers_reduced_motion),
256 }
257 }
258}