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
//! Import/export analyzer

use swc_atoms::JsWord;
use swc_css_ast::{
    ComponentValue, Declaration, DeclarationName, ImportHref, ImportPrelude, Stylesheet, UrlValue,
};
use swc_css_visit::{Visit, VisitWith};

pub fn analyze_imports(ss: &Stylesheet) -> Vec<JsWord> {
    let mut v = Analyzer {
        imports: Default::default(),
    };
    ss.visit_with(&mut v);
    v.imports.sort();
    v.imports.dedup();
    v.imports
}

struct Analyzer {
    imports: Vec<JsWord>,
}

impl Visit for Analyzer {
    fn visit_import_prelude(&mut self, n: &ImportPrelude) {
        n.visit_children_with(self);

        match &*n.href {
            ImportHref::Url(u) => {
                if let Some(s) = &u.value {
                    match &**s {
                        UrlValue::Str(s) => {
                            self.imports.push(s.value.clone());
                        }
                        UrlValue::Raw(v) => {
                            self.imports.push(v.value.clone());
                        }
                    }
                }
            }
            ImportHref::Str(s) => {
                self.imports.push(s.value.clone());
            }
        }
    }

    fn visit_declaration(&mut self, d: &Declaration) {
        d.visit_children_with(self);

        if let DeclarationName::Ident(name) = &d.name {
            if &*name.value == "composes" {
                // composes: name from 'foo.css'
                if d.value.len() >= 3 {
                    match (&d.value[d.value.len() - 2], &d.value[d.value.len() - 1]) {
                        (ComponentValue::Ident(ident), ComponentValue::Str(s))
                            if ident.value == "from" =>
                        {
                            self.imports.push(s.value.clone());
                        }
                        _ => (),
                    }
                }
            }
        }
    }
}