1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![crate_name = "cssparser"] #![crate_type = "rlib"] #![cfg_attr(feature = "bench", feature(test))] #![deny(missing_docs)] /*! Implementation of [CSS Syntax Module Level 3](https://drafts.csswg.org/css-syntax/) for Rust. # Input Everything is based on `Parser` objects, which borrow a `&str` input. If you have bytes (from a file, the network, or something) and want to support character encodings other than UTF-8, see the `stylesheet_encoding` function, which can be used together with rust-encoding or encoding-rs. # Conventions for parsing functions * Take (at least) a `input: &mut cssparser::Parser` parameter * Return `Result<_, ()>` * When returning `Ok(_)`, the function must have consumed exactly the amount of input that represents the parsed value. * When returning `Err(())`, any amount of input may have been consumed. As a consequence, when calling another parsing function, either: * Any `Err(())` return value must be propagated. This happens by definition for tail calls, and can otherwise be done with the `try!` macro. * Or the call must be wrapped in a `Parser::try` call. `try` takes a closure that takes a `Parser` and returns a `Result`, calls it once, and returns itself that same result. If the result is `Err`, it restores the position inside the input to the one saved before calling the closure. Examples: ```{rust,ignore} // 'none' | <image> fn parse_background_image(context: &ParserContext, input: &mut Parser) -> Result<Option<Image>, ()> { if input.try(|input| input.expect_ident_matching("none")).is_ok() { Ok(None) } else { Image::parse(context, input).map(Some) // tail call } } ``` ```{rust,ignore} // [ <length> | <percentage> ] [ <length> | <percentage> ]? fn parse_border_spacing(_context: &ParserContext, input: &mut Parser) -> Result<(LengthOrPercentage, LengthOrPercentage), ()> { let first = try!(LengthOrPercentage::parse); let second = input.try(LengthOrPercentage::parse).unwrap_or(first); (first, second) } ``` */ #![recursion_limit="200"] // For color::parse_color_keyword #[macro_use] extern crate cssparser_macros; #[macro_use] extern crate matches; #[macro_use] extern crate procedural_masquerade; #[doc(hidden)] pub extern crate phf as _internal__phf; #[cfg(test)] extern crate encoding_rs; #[cfg(test)] extern crate difference; #[cfg(test)] extern crate rustc_serialize; #[cfg(feature = "serde")] extern crate serde; #[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize; pub use cssparser_macros::*; pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation}; pub use rules_and_declarations::{parse_important}; pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration}; pub use rules_and_declarations::{RuleListParser, parse_one_rule}; pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser}; pub use from_bytes::{stylesheet_encoding, EncodingSupport}; pub use color::{RGBA, Color, parse_color_keyword}; pub use nth::parse_nth; pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string, TokenSerializationType}; pub use parser::{Parser, Delimiter, Delimiters, SourcePosition}; pub use unicode_range::UnicodeRange; // For macros #[doc(hidden)] pub use macros::_internal__to_lowercase; // For macros when used in this crate. Unsure how $crate works with procedural-masquerade. mod cssparser { pub use _internal__phf; } #[macro_use] mod macros; mod rules_and_declarations; #[cfg(feature = "dummy_match_byte")] mod tokenizer; #[cfg(not(feature = "dummy_match_byte"))] mod tokenizer { include!(concat!(env!("OUT_DIR"), "/tokenizer.rs")); } mod parser; mod from_bytes; mod color; mod nth; mod serializer; mod unicode_range; #[cfg(test)] mod tests;