omena_parser/facts/
at_rules.rs1use cstree::text::TextRange;
7use omena_syntax::{StyleDialect, SyntaxKind};
8
9use crate::{at_rule_spec, scss_at_rule_spec};
10
11use super::StyleFactSink;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct ParsedAtRuleFact {
15 pub name: String,
16 pub node_kind: Option<SyntaxKind>,
17 pub range: TextRange,
18}
19
20pub(crate) fn collect_at_rule_facts_from_sink(sink: &StyleFactSink<'_>) -> Vec<ParsedAtRuleFact> {
21 sink.tokens()
22 .iter()
23 .filter(|token| token.kind == SyntaxKind::AtKeyword)
24 .map(|token| at_rule_fact_from_cst_token(sink.text(), token.range, sink.dialect()))
25 .collect()
26}
27
28fn at_rule_fact_from_cst_token(
29 text: &str,
30 range: TextRange,
31 dialect: StyleDialect,
32) -> ParsedAtRuleFact {
33 let start = u32::from(range.start()) as usize;
34 let end = u32::from(range.end()) as usize;
35 let source_text = text.get(start..end).unwrap_or_default();
36 let css_spec = at_rule_spec(source_text);
37 let node_kind = css_spec
38 .or_else(|| match dialect {
39 StyleDialect::Scss | StyleDialect::Sass => scss_at_rule_spec(source_text),
40 StyleDialect::Css | StyleDialect::Less => None,
41 })
42 .map(|spec| spec.node_kind);
43 let name = if css_spec.is_some() {
44 source_text.to_ascii_lowercase()
45 } else {
46 source_text.to_string()
47 };
48 ParsedAtRuleFact {
49 name,
50 node_kind,
51 range,
52 }
53}