Skip to main content

styled_components/
lib.rs

1#![deny(unused)]
2
3use serde::Deserialize;
4use swc_atoms::Wtf8Atom;
5use swc_common::{comments::Comments, pass::Optional};
6use swc_ecma_ast::{fn_pass, Pass};
7
8pub use crate::{
9    utils::{analyze, analyzer, State},
10    visitors::{
11        display_name_and_id::display_name_and_id, minify::visitor::minify,
12        pure_annotation::pure_annotation, template_literals::template_literals,
13        transpile_css_prop::transpile::transpile_css_prop,
14    },
15};
16
17mod css;
18mod utils;
19mod visitors;
20
21#[derive(Debug, Default, Clone, Deserialize)]
22#[serde(rename_all = "camelCase", deny_unknown_fields)]
23pub struct Config {
24    #[serde(default = "true_by_default")]
25    pub display_name: bool,
26
27    #[serde(default = "true_by_default")]
28    pub ssr: bool,
29
30    #[serde(default = "true_by_default")]
31    pub file_name: bool,
32
33    #[serde(default = "default_index_file_name")]
34    pub meaningless_file_names: Vec<String>,
35
36    #[serde(default)]
37    pub namespace: String,
38
39    #[serde(default)]
40    pub top_level_import_paths: Vec<Wtf8Atom>,
41
42    #[serde(default = "true_by_default")]
43    pub transpile_template_literals: bool,
44
45    #[serde(default = "true_by_default")]
46    pub minify: bool,
47
48    #[serde(default)]
49    pub pure: bool,
50
51    #[serde(default = "true_by_default")]
52    pub css_prop: bool,
53}
54
55fn true_by_default() -> bool {
56    true
57}
58
59fn default_index_file_name() -> Vec<String> {
60    vec!["index".to_string()]
61}
62
63impl Config {
64    pub(crate) fn use_namespace(&self) -> String {
65        if self.namespace.is_empty() {
66            return String::new();
67        }
68        format!("{}__", self.namespace)
69    }
70}
71
72pub fn styled_components<'a, C>(
73    file_name: Option<&'a str>,
74    src_file_hash: u128,
75    config: &'a Config,
76    comments: C,
77) -> impl 'a + Pass
78where
79    C: 'a + Comments + Clone,
80{
81    fn_pass(move |program| {
82        let mut state = State::default();
83
84        program.mutate(analyzer(config, &mut state));
85
86        if config.css_prop {
87            program.mutate(transpile_css_prop(&mut state));
88        }
89
90        if !state.need_work() {
91            return;
92        }
93
94        program.mutate((
95            Optional {
96                enabled: config.minify,
97                visitor: minify(&state),
98            },
99            display_name_and_id(file_name, src_file_hash, config, &state),
100            Optional {
101                enabled: config.transpile_template_literals,
102                visitor: template_literals(&state),
103            },
104            Optional {
105                enabled: config.pure,
106                visitor: pure_annotation(comments.clone(), &state),
107            },
108        ));
109    })
110}