list.rs (5586B)
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")] 8 use crate::counter_style::{CounterStyle, CounterStyleParsingFlags}; 9 use crate::derives::*; 10 use crate::parser::{Parse, ParserContext}; 11 #[cfg(feature = "servo")] 12 use crate::properties::longhands::list_style_type::SpecifiedValue as ListStyleType; 13 use cssparser::{Parser, Token}; 14 use style_traits::{ParseError, StyleParseErrorKind}; 15 16 /// Specified and computed `list-style-type` property. 17 #[cfg(feature = "gecko")] 18 #[derive( 19 Clone, 20 Debug, 21 Eq, 22 MallocSizeOf, 23 PartialEq, 24 SpecifiedValueInfo, 25 ToComputedValue, 26 ToCss, 27 ToResolvedValue, 28 ToShmem, 29 ToTyped, 30 )] 31 #[repr(transparent)] 32 pub struct ListStyleType(pub CounterStyle); 33 34 #[cfg(feature = "gecko")] 35 impl ListStyleType { 36 /// Initial specified value for `list-style-type`. 37 #[inline] 38 pub fn disc() -> Self { 39 Self(CounterStyle::disc()) 40 } 41 42 /// none value. 43 #[inline] 44 pub fn none() -> Self { 45 Self(CounterStyle::None) 46 } 47 48 /// Convert from gecko keyword to list-style-type. 49 /// 50 /// This should only be used for mapping type attribute to list-style-type, and thus only 51 /// values possible in that attribute is considered here. 52 pub fn from_gecko_keyword(value: u32) -> Self { 53 use crate::gecko_bindings::structs; 54 use crate::values::CustomIdent; 55 let v8 = value as u8; 56 if v8 == structs::ListStyle_None { 57 return Self::none(); 58 } 59 60 Self(CounterStyle::Name(CustomIdent(match v8 { 61 structs::ListStyle_Disc => atom!("disc"), 62 structs::ListStyle_Circle => atom!("circle"), 63 structs::ListStyle_Square => atom!("square"), 64 structs::ListStyle_Decimal => atom!("decimal"), 65 structs::ListStyle_LowerRoman => atom!("lower-roman"), 66 structs::ListStyle_UpperRoman => atom!("upper-roman"), 67 structs::ListStyle_LowerAlpha => atom!("lower-alpha"), 68 structs::ListStyle_UpperAlpha => atom!("upper-alpha"), 69 _ => unreachable!("Unknown counter style keyword value"), 70 }))) 71 } 72 73 /// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`) 74 #[inline] 75 pub fn is_bullet(&self) -> bool { 76 self.0.is_bullet() 77 } 78 } 79 80 #[cfg(feature = "gecko")] 81 impl Parse for ListStyleType { 82 fn parse<'i, 't>( 83 context: &ParserContext, 84 input: &mut Parser<'i, 't>, 85 ) -> Result<Self, ParseError<'i>> { 86 let flags = CounterStyleParsingFlags::ALLOW_NONE | CounterStyleParsingFlags::ALLOW_STRING; 87 Ok(Self(CounterStyle::parse(context, input, flags)?)) 88 } 89 } 90 91 #[cfg(feature = "servo")] 92 impl ListStyleType { 93 /// Initial specified value for `list-style-type`. 94 #[inline] 95 pub fn disc() -> Self { 96 Self::Disc 97 } 98 99 /// none value. 100 #[inline] 101 pub fn none() -> Self { 102 Self::None 103 } 104 } 105 106 /// A quote pair. 107 #[derive( 108 Clone, 109 Debug, 110 MallocSizeOf, 111 PartialEq, 112 SpecifiedValueInfo, 113 ToComputedValue, 114 ToCss, 115 ToResolvedValue, 116 ToShmem, 117 )] 118 #[repr(C)] 119 pub struct QuotePair { 120 /// The opening quote. 121 pub opening: crate::OwnedStr, 122 123 /// The closing quote. 124 pub closing: crate::OwnedStr, 125 } 126 127 /// List of quote pairs for the specified/computed value of `quotes` property. 128 #[derive( 129 Clone, 130 Debug, 131 Default, 132 MallocSizeOf, 133 PartialEq, 134 SpecifiedValueInfo, 135 ToComputedValue, 136 ToCss, 137 ToResolvedValue, 138 ToShmem, 139 )] 140 #[repr(transparent)] 141 pub struct QuoteList( 142 #[css(iterable, if_empty = "none")] 143 #[ignore_malloc_size_of = "Arc"] 144 pub crate::ArcSlice<QuotePair>, 145 ); 146 147 /// Specified and computed `quotes` property: `auto`, `none`, or a list 148 /// of characters. 149 #[derive( 150 Clone, 151 Debug, 152 MallocSizeOf, 153 PartialEq, 154 SpecifiedValueInfo, 155 ToComputedValue, 156 ToCss, 157 ToResolvedValue, 158 ToShmem, 159 ToTyped, 160 )] 161 #[repr(C)] 162 pub enum Quotes { 163 /// list of quote pairs 164 QuoteList(QuoteList), 165 /// auto (use lang-dependent quote marks) 166 Auto, 167 } 168 169 impl Parse for Quotes { 170 fn parse<'i, 't>( 171 _: &ParserContext, 172 input: &mut Parser<'i, 't>, 173 ) -> Result<Quotes, ParseError<'i>> { 174 if input 175 .try_parse(|input| input.expect_ident_matching("auto")) 176 .is_ok() 177 { 178 return Ok(Quotes::Auto); 179 } 180 181 if input 182 .try_parse(|input| input.expect_ident_matching("none")) 183 .is_ok() 184 { 185 return Ok(Quotes::QuoteList(QuoteList::default())); 186 } 187 188 let mut quotes = Vec::new(); 189 loop { 190 let location = input.current_source_location(); 191 let opening = match input.next() { 192 Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(), 193 Ok(t) => return Err(location.new_unexpected_token_error(t.clone())), 194 Err(_) => break, 195 }; 196 197 let closing = input.expect_string()?.as_ref().to_owned().into(); 198 quotes.push(QuotePair { opening, closing }); 199 } 200 201 if !quotes.is_empty() { 202 Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter( 203 quotes.into_iter(), 204 )))) 205 } else { 206 Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) 207 } 208 } 209 }