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
/* 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 `?` operator.
* 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_parse(|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 = LengthOrPercentage::parse?;
    let second = input.try_parse(LengthOrPercentage::parse).unwrap_or(first);
    (first, second)
}
```

*/

#![recursion_limit = "200"] // For color::parse_color_keyword

pub use crate::color::{
    parse_color_keyword, AngleOrNumber, Color, ColorComponentParser, NumberOrPercentage, RGBA,
};
pub use crate::cow_rc_str::CowRcStr;
pub use crate::from_bytes::{stylesheet_encoding, EncodingSupport};
#[doc(hidden)]
pub use crate::macros::_cssparser_internal_to_lowercase;
pub use crate::nth::parse_nth;
pub use crate::parser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind};
pub use crate::parser::{Delimiter, Delimiters, Parser, ParserInput, ParserState};
pub use crate::rules_and_declarations::{parse_important, parse_one_declaration};
pub use crate::rules_and_declarations::{parse_one_rule, RuleListParser};
pub use crate::rules_and_declarations::{AtRuleParser, QualifiedRuleParser};
pub use crate::rules_and_declarations::{DeclarationListParser, DeclarationParser};
pub use crate::serializer::{serialize_identifier, serialize_name, serialize_string};
pub use crate::serializer::{CssStringWriter, ToCss, TokenSerializationType};
pub use crate::tokenizer::{SourceLocation, SourcePosition, Token};
pub use crate::unicode_range::UnicodeRange;
pub use cssparser_macros::*;
#[doc(hidden)]
pub use phf as _cssparser_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 color;
mod cow_rc_str;
mod from_bytes;
mod nth;
mod parser;
mod serializer;
mod unicode_range;

#[cfg(test)]
mod size_of_tests;
#[cfg(test)]
mod tests;