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 66 67 68
//! Port of https://github.com/styled-components/babel-plugin-styled-components/blob/4e2eb388d9c90f2921c306c760657d059d01a518/src/visitors/minify.js
use std::{cell::RefCell, rc::Rc};
use swc_common::DUMMY_SP;
use swc_ecma_ast::*;
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
use super::css::{minify_raw_values, MinifyResult};
use crate::utils::State;
pub fn minify(state: Rc<RefCell<State>>) -> impl Fold + VisitMut {
as_folder(Minify { state })
}
#[derive(Debug)]
struct Minify {
state: Rc<RefCell<State>>,
}
impl VisitMut for Minify {
noop_visit_mut_type!();
fn visit_mut_expr(&mut self, expr: &mut Expr) {
expr.visit_mut_children_with(self);
let Expr::TaggedTpl(tagged) = expr else {
return;
};
if !self.state.borrow().is_styled(&tagged.tag)
&& !self.state.borrow().is_helper(&tagged.tag)
{
return;
}
let MinifyResult {
values: raw_values_minified,
retained_expression_indices,
} = minify_raw_values(tagged.tpl.quasis.iter().map(|q| q.raw.clone()));
tagged.tpl.quasis = raw_values_minified
.into_iter()
.map(|raw| TplElement {
span: DUMMY_SP,
tail: false,
// Omitting `cooked` field since swc_ecma_codegen doesn't use it. If this breaks
// other plugins, we may need to set some value.
// https://rustdoc.swc.rs/swc_ecma_ast/struct.TplElement.html#structfield.cooked
cooked: None,
raw,
})
.collect();
if let Some(q) = tagged.tpl.quasis.last_mut() {
q.tail = true;
}
// Remove expressions that were removed by minification.
// NOTE: Here we assume that the expressions don't have side effects, as
// babel-plugin-styled-components does.
{
let mut idx: usize = 0;
tagged.tpl.exprs.retain(|_| {
idx += 1;
retained_expression_indices.contains(&(idx - 1))
});
}
}
}