Skip to main content

css_module_lexer/
lib.rs

1mod css_syntax;
2mod dependencies;
3mod dependency_types;
4mod lexer;
5
6pub use dependencies::DashedIdentCollector;
7pub use dependencies::LexDependencies;
8pub use dependencies::ModeData;
9pub use dependency_types::Dependency;
10pub use dependency_types::DependencyContext;
11pub use dependency_types::DependencyIndex;
12pub use dependency_types::DependencyListRange;
13pub use dependency_types::ImportAttributes;
14pub use dependency_types::Mode;
15pub use dependency_types::Range;
16pub use dependency_types::UrlRangeKind;
17pub use dependency_types::ValueAtRuleImportItem;
18pub use dependency_types::Warning;
19pub use dependency_types::WarningKind;
20pub use lexer::{Lexer, LexerVisitor, Pos, Token, TokenFlags, TokenKind, TokenWithTrivia, Trivia};
21
22pub trait HandleWarning<'s> {
23    fn handle_warning(&mut self, warning: Warning<'s>);
24}
25
26impl<'s, F: FnMut(Warning<'s>)> HandleWarning<'s> for F {
27    fn handle_warning(&mut self, warning: Warning<'s>) {
28        self(warning);
29    }
30}
31
32pub fn lex_dependencies<'s>(
33    input: &'s str,
34    mode: Mode,
35    mut handle_dependency: impl FnMut(&Dependency<'s>),
36    handle_warning: impl HandleWarning<'s>,
37) -> DependencyContext<'s> {
38    let mut lexer = Lexer::new(input, DashedIdentCollector::default());
39    let mut visitor = LexDependencies::new(handle_warning, mode);
40    visitor.lex_streaming(&mut lexer);
41    let dependency_context = visitor.into_dependency_context();
42    for dependency in dependency_context.iter() {
43        handle_dependency(dependency);
44    }
45    dependency_context
46}
47
48pub fn collect_dependencies(input: &str, mode: Mode) -> (DependencyContext<'_>, Vec<Warning<'_>>) {
49    let mut warnings = Vec::with_capacity(estimate_warning_capacity(input.len(), mode));
50    let mut lexer = Lexer::new(input, DashedIdentCollector::default());
51    let mut visitor = LexDependencies::new(|v| warnings.push(v), mode);
52    visitor.lex_streaming(&mut lexer);
53    (visitor.into_dependency_context(), warnings)
54}
55
56fn estimate_warning_capacity(input_len: usize, mode: Mode) -> usize {
57    let warning_rate = match mode {
58        Mode::Pure => (1, 256),
59        _ => (1, 512),
60    };
61
62    estimate_capacity(input_len, warning_rate.0, warning_rate.1, 2, 512)
63}
64
65#[inline]
66fn estimate_capacity(
67    input_len: usize,
68    numerator: usize,
69    denominator: usize,
70    minimum: usize,
71    maximum: usize,
72) -> usize {
73    input_len
74        .saturating_mul(numerator)
75        .checked_div(denominator)
76        .unwrap_or(0)
77        .clamp(minimum, maximum)
78}