Skip to main content

css_module_lexer/
lib.rs

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