lewp_css/domain/selectors/
our_selector_impl.rs

1// This file is part of css. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT. No part of predicator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
2// Copyright © 2017 The developers of css. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT.
3
4use {
5    crate::{
6        domain::{
7            at_rules::namespace::{NamespacePrefix, NamespaceUrl, Namespaces},
8            selectors::{
9                NonTreeStructuralPseudoClass,
10                OurSelector,
11                PseudoElement,
12                VendorPrefixablePseudoClassName,
13                VendorPrefixablePseudoElementName,
14            },
15            Atom,
16            VendorPrefix,
17        },
18        parsers::OurSelectorParser,
19        CustomParseError,
20    },
21    cssparser::{ParseError, Parser, ParserInput, ToCss},
22    selectors::SelectorImpl,
23    std::collections::HashMap,
24};
25
26#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
27pub struct OurSelectorImpl;
28
29impl SelectorImpl for OurSelectorImpl {
30    type ExtraMatchingData = String;
31
32    type AttrValue = Atom;
33
34    type Identifier = Atom;
35
36    type LocalName = Atom;
37
38    type NamespacePrefix = NamespacePrefix;
39
40    type NamespaceUrl = NamespaceUrl;
41
42    type BorrowedNamespaceUrl = str;
43
44    type BorrowedLocalName = str;
45
46    type NonTSPseudoClass = NonTreeStructuralPseudoClass;
47
48    type PseudoElement = PseudoElement;
49}
50
51impl OurSelectorImpl {
52    /// Parses a selector
53    pub fn parse_selector(
54        selector_css: &str,
55    ) -> Result<OurSelector, ParseError<CustomParseError>> {
56        const LineNumberingIsZeroBased: u32 = 0;
57
58        let mut parserInput = ParserInput::new_with_line_number_offset(
59            selector_css,
60            LineNumberingIsZeroBased,
61        );
62        let mut input = Parser::new(&mut parserInput);
63
64        let applyVendorPrefixToPseudoClasses = HashMap::default();
65        let applyVendorPrefixToPseudoElements = HashMap::default();
66        let ourSelectorParser = OurSelectorParser {
67            namespaces: Namespaces::empty(),
68            applyVendorPrefixToPseudoClasses: &applyVendorPrefixToPseudoClasses,
69            applyVendorPrefixToPseudoElements:
70                &applyVendorPrefixToPseudoElements,
71        };
72
73        match ourSelectorParser.parse(&mut input) {
74            Err(error) => Err(error),
75            Ok(mut selectors) => {
76                let newSelector = selectors.0.drain(..).next().unwrap();
77                Ok(newSelector)
78            }
79        }
80    }
81
82    /// Applies a vendor prefix to a CSS selector
83    #[inline(always)]
84    pub fn reparse_with_vendor_prefix<'a>(
85        selector: &OurSelector,
86        applyVendorPrefixToPseudoClasses: &'a HashMap<
87            VendorPrefixablePseudoClassName,
88            VendorPrefix,
89        >,
90        applyVendorPrefixToPseudoElements: &'a HashMap<
91            VendorPrefixablePseudoElementName,
92            VendorPrefix,
93        >,
94    ) -> Option<OurSelector> {
95        const LineNumberingIsZeroBased: u32 = 0;
96
97        let originalCss = selector.to_css_string();
98
99        let mut parserInput = ParserInput::new_with_line_number_offset(
100            &originalCss,
101            LineNumberingIsZeroBased,
102        );
103        let mut input = Parser::new(&mut parserInput);
104
105        let ourSelectorParser = OurSelectorParser {
106            namespaces: Namespaces::empty(),
107            applyVendorPrefixToPseudoClasses,
108            applyVendorPrefixToPseudoElements,
109        };
110
111        let mut selectors = ourSelectorParser.parse(&mut input).unwrap();
112        let newSelector = selectors.0.drain(..).next().unwrap();
113
114        if newSelector.to_css_string() != originalCss {
115            Some(newSelector)
116        } else {
117            None
118        }
119    }
120}