style/values/specified/list.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! `list` specified values.
6
7#[cfg(feature = "gecko")]
8use crate::counter_style::{CounterStyle, CounterStyleParsingFlags};
9use crate::derives::*;
10use crate::parser::{Parse, ParserContext};
11use cssparser::{Parser, Token};
12use style_traits::{ParseError, StyleParseErrorKind};
13
14/// Specified and computed `list-style-type` property.
15#[cfg(feature = "gecko")]
16#[derive(
17 Clone,
18 Debug,
19 Eq,
20 MallocSizeOf,
21 PartialEq,
22 SpecifiedValueInfo,
23 ToComputedValue,
24 ToCss,
25 ToResolvedValue,
26 ToShmem,
27 ToTyped,
28)]
29#[repr(transparent)]
30pub struct ListStyleType(pub CounterStyle);
31
32#[cfg(feature = "gecko")]
33impl ListStyleType {
34 /// Initial specified value for `list-style-type`.
35 #[inline]
36 pub fn disc() -> Self {
37 Self(CounterStyle::disc())
38 }
39
40 /// none value.
41 #[inline]
42 pub fn none() -> Self {
43 Self(CounterStyle::None)
44 }
45
46 /// Convert from gecko keyword to list-style-type.
47 ///
48 /// This should only be used for mapping type attribute to list-style-type, and thus only
49 /// values possible in that attribute is considered here.
50 pub fn from_gecko_keyword(value: u32) -> Self {
51 use crate::gecko_bindings::structs;
52 use crate::values::CustomIdent;
53 let v8 = value as u8;
54 if v8 == structs::ListStyle_None {
55 return Self::none();
56 }
57
58 Self(CounterStyle::Name(CustomIdent(match v8 {
59 structs::ListStyle_Disc => atom!("disc"),
60 structs::ListStyle_Circle => atom!("circle"),
61 structs::ListStyle_Square => atom!("square"),
62 structs::ListStyle_Decimal => atom!("decimal"),
63 structs::ListStyle_LowerRoman => atom!("lower-roman"),
64 structs::ListStyle_UpperRoman => atom!("upper-roman"),
65 structs::ListStyle_LowerAlpha => atom!("lower-alpha"),
66 structs::ListStyle_UpperAlpha => atom!("upper-alpha"),
67 _ => unreachable!("Unknown counter style keyword value"),
68 })))
69 }
70
71 /// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
72 #[inline]
73 pub fn is_bullet(&self) -> bool {
74 self.0.is_bullet()
75 }
76}
77
78#[cfg(feature = "gecko")]
79impl Parse for ListStyleType {
80 fn parse<'i, 't>(
81 context: &ParserContext,
82 input: &mut Parser<'i, 't>,
83 ) -> Result<Self, ParseError<'i>> {
84 let flags = CounterStyleParsingFlags::ALLOW_NONE | CounterStyleParsingFlags::ALLOW_STRING;
85 Ok(Self(CounterStyle::parse(context, input, flags)?))
86 }
87}
88
89/// Specified and computed `list-style-type` property.
90#[cfg(feature = "servo")]
91#[derive(
92 Clone,
93 Debug,
94 Eq,
95 MallocSizeOf,
96 Parse,
97 PartialEq,
98 SpecifiedValueInfo,
99 ToCss,
100 ToComputedValue,
101 ToResolvedValue,
102 ToShmem,
103 ToTyped,
104)]
105pub enum ListStyleType {
106 /// A filled circle, similar to • U+2022 BULLET.
107 /// <https://www.w3.org/TR/css-counter-styles-3/#disc>
108 Disc,
109 /// The element has no marker string.
110 /// <https://www.w3.org/TR/css-lists-3/#valdef-list-style-type-none>
111 None,
112 /// A hollow circle, similar to ◦ U+25E6 WHITE BULLET.
113 /// <https://www.w3.org/TR/css-counter-styles-3/#circle>
114 Circle,
115 /// A filled square, similar to ▪ U+25AA BLACK SMALL SQUARE.
116 /// <https://www.w3.org/TR/css-counter-styles-3/#square>
117 Square,
118 /// Symbol for indicating an open disclosure widget, such as the HTML `<details>` element.
119 /// <https://www.w3.org/TR/css-counter-styles-3/#disclosure-open>
120 DisclosureOpen,
121 /// Symbol for indicating a closed disclosure widget, such as the HTML `<details>` element.
122 /// <https://www.w3.org/TR/css-counter-styles-3/#disclosure-closed>
123 DisclosureClosed,
124 /// Western decimal numbers (e.g., 1, 2, 3, ..., 98, 99, 100).
125 /// <https://www.w3.org/TR/css-counter-styles-3/#decimal>
126 Decimal,
127 /// Lowercase ASCII letters (e.g., a, b, c, ..., z, aa, ab).
128 /// <https://www.w3.org/TR/css-counter-styles-3/#lower-alpha>
129 LowerAlpha,
130 /// Uppercase ASCII letters (e.g., A, B, C, ..., Z, AA, AB).
131 /// <https://www.w3.org/TR/css-counter-styles-3/#upper-alpha>
132 UpperAlpha,
133 /// Arabic-indic numbering (e.g.، ١، ٢، ٣، ٤، ...، ٩٨، ٩٩، ١٠٠).
134 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-arabic-indic>
135 ArabicIndic,
136 /// Bengali numbering (e.g., ১, ২, ৩, ..., ৯৮, ৯৯, ১০০).
137 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-bengali>
138 Bengali,
139 /// Cambodian/Khmer numbering (e.g., ១, ២, ៣, ..., ៩៨, ៩៩, ១០០).
140 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-cambodian>
141 Cambodian,
142 /// Han decimal numbers (e.g., 一, 二, 三, ..., 九八, 九九, 一〇〇).
143 /// <https://www.w3.org/TR/css-counter-styles-3/#cjk-decimal>
144 CjkDecimal,
145 /// devanagari numbering (e.g., १, २, ३, ..., ९८, ९९, १००).
146 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-devanagari>
147 Devanagari,
148 /// Gujarati numbering (e.g., ૧, ૨, ૩, ..., ૯૮, ૯૯, ૧૦૦).
149 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-gujarati>
150 Gujarati,
151 /// Gurmukhi numbering (e.g., ੧, ੨, ੩, ..., ੯੮, ੯੯, ੧੦੦).
152 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-gurmukhi>
153 Gurmukhi,
154 /// Kannada numbering (e.g., ೧, ೨, ೩, ..., ೯೮, ೯೯, ೧೦೦).
155 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-kannada>
156 Kannada,
157 /// Cambodian/Khmer numbering (e.g., ១, ២, ៣, ..., ៩៨, ៩៩, ១០០).
158 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-khmer>
159 Khmer,
160 /// Laotian numbering (e.g., ໑, ໒, ໓, ..., ໙໘, ໙໙, ໑໐໐).
161 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-lao<
162 Lao,
163 /// Malayalam numbering (e.g., ൧, ൨, ൩, ..., ൯൮, ൯൯, ൧൦൦).
164 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-malayalam>
165 Malayalam,
166 /// Mongolian numbering (e.g., ᠑, ᠒, ᠓, ..., ᠙᠘, ᠙᠙, ᠑᠐᠐).
167 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-mongolian>
168 Mongolian,
169 /// Myanmar (Burmese) numbering (e.g., ၁, ၂, ၃, ..., ၉၈, ၉၉, ၁၀၀).
170 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-myanmar>
171 Myanmar,
172 /// Oriya numbering (e.g., ୧, ୨, ୩, ..., ୯୮, ୯୯, ୧୦୦).
173 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-oriya>
174 Oriya,
175 /// Persian numbering (e.g., ۱, ۲, ۳, ۴, ..., ۹۸, ۹۹, ۱۰۰).
176 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-persian>
177 Persian,
178 /// Telugu numbering (e.g., ౧, ౨, ౩, ..., ౯౮, ౯౯, ౧౦౦).
179 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-telugu>
180 Telugu,
181 /// Thai (Siamese) numbering (e.g., ๑, ๒, ๓, ..., ๙๘, ๙๙, ๑๐๐).
182 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-thai>
183 Thai,
184 /// Tibetan numbering (e.g., ༡, ༢, ༣, ..., ༩༨, ༩༩, ༡༠༠).
185 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-tibetan>
186 Tibetan,
187 /// Han "Earthly Branch" ordinals (e.g., 子, 丑, 寅, ..., 亥).
188 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-cjk-earthly-branch>
189 CjkEarthlyBranch,
190 /// Han "Heavenly Stem" ordinals (e.g., 甲, 乙, 丙, ..., 癸)
191 /// <https://www.w3.org/TR/css-counter-styles-3/#valdef-counter-style-name-cjk-heavenly-stem>
192 CjkHeavenlyStem,
193 /// Lowercase classical Greek (e.g., α, β, γ, ..., ω, αα, αβ).
194 /// <https://www.w3.org/TR/css-counter-styles-3/#lower-greek>
195 LowerGreek,
196 /// Dictionary-order hiragana lettering (e.g., あ, い, う, ..., ん, ああ, あい).
197 /// <https://www.w3.org/TR/css-counter-styles-3/#hiragana>
198 Hiragana,
199 /// Iroha-order hiragana lettering (e.g., い, ろ, は, ..., す, いい, いろ).
200 /// <https://www.w3.org/TR/css-counter-styles-3/#hiragana-iroha>
201 HiraganaIroha,
202 /// Dictionary-order katakana lettering (e.g., ア, イ, ウ, ..., ン, アア, アイ).
203 /// <https://www.w3.org/TR/css-counter-styles-3/#katakana>
204 Katakana,
205 /// Iroha-order katakana lettering (e.g., イ, ロ, ハ, ..., ス, イイ, イロ)
206 /// <https://www.w3.org/TR/css-counter-styles-3/#katakana-iroha>
207 KatakanaIroha,
208}
209
210#[cfg(feature = "servo")]
211impl ListStyleType {
212 /// Initial specified value for `list-style-type`.
213 #[inline]
214 pub fn disc() -> Self {
215 Self::Disc
216 }
217
218 /// none value.
219 #[inline]
220 pub fn none() -> Self {
221 Self::None
222 }
223}
224
225/// A quote pair.
226#[derive(
227 Clone,
228 Debug,
229 MallocSizeOf,
230 PartialEq,
231 SpecifiedValueInfo,
232 ToComputedValue,
233 ToCss,
234 ToResolvedValue,
235 ToShmem,
236)]
237#[repr(C)]
238pub struct QuotePair {
239 /// The opening quote.
240 pub opening: crate::OwnedStr,
241
242 /// The closing quote.
243 pub closing: crate::OwnedStr,
244}
245
246/// List of quote pairs for the specified/computed value of `quotes` property.
247#[derive(
248 Clone,
249 Debug,
250 Default,
251 MallocSizeOf,
252 PartialEq,
253 SpecifiedValueInfo,
254 ToComputedValue,
255 ToCss,
256 ToResolvedValue,
257 ToShmem,
258)]
259#[repr(transparent)]
260pub struct QuoteList(
261 #[css(iterable, if_empty = "none")]
262 #[ignore_malloc_size_of = "Arc"]
263 pub crate::ArcSlice<QuotePair>,
264);
265
266/// Specified and computed `quotes` property: `auto`, `none`, or a list
267/// of characters.
268#[derive(
269 Clone,
270 Debug,
271 MallocSizeOf,
272 PartialEq,
273 SpecifiedValueInfo,
274 ToComputedValue,
275 ToCss,
276 ToResolvedValue,
277 ToShmem,
278 ToTyped,
279)]
280#[repr(C)]
281pub enum Quotes {
282 /// list of quote pairs
283 QuoteList(QuoteList),
284 /// auto (use lang-dependent quote marks)
285 Auto,
286}
287
288impl Parse for Quotes {
289 fn parse<'i, 't>(
290 _: &ParserContext,
291 input: &mut Parser<'i, 't>,
292 ) -> Result<Quotes, ParseError<'i>> {
293 if input
294 .try_parse(|input| input.expect_ident_matching("auto"))
295 .is_ok()
296 {
297 return Ok(Quotes::Auto);
298 }
299
300 if input
301 .try_parse(|input| input.expect_ident_matching("none"))
302 .is_ok()
303 {
304 return Ok(Quotes::QuoteList(QuoteList::default()));
305 }
306
307 let mut quotes = Vec::new();
308 loop {
309 let location = input.current_source_location();
310 let opening = match input.next() {
311 Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(),
312 Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
313 Err(_) => break,
314 };
315
316 let closing = input.expect_string()?.as_ref().to_owned().into();
317 quotes.push(QuotePair { opening, closing });
318 }
319
320 if !quotes.is_empty() {
321 Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter(
322 quotes.into_iter(),
323 ))))
324 } else {
325 Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
326 }
327 }
328}