1use serde::{de::DeserializeOwned, Deserialize, Serialize};
2use swc_config::regex::CachedRegex;
3#[cfg(feature = "default-css-minifier")]
4use swc_css_codegen::CodegenConfig as CssCodegenOptions;
5#[cfg(feature = "default-css-minifier")]
6use swc_css_minifier::options::MinifyOptions as CssMinifyOptions;
7#[cfg(feature = "default-css-minifier")]
8use swc_css_parser::parser::ParserConfig as CssParserOptions;
9use swc_ecma_ast::EsVersion;
10use swc_ecma_codegen::Config as JsCodegenOptions;
11use swc_ecma_minifier::option::MinifyOptions as JsMinifyOptions;
12use swc_ecma_parser::Syntax;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15#[serde(rename_all = "kebab-case")]
16#[serde(deny_unknown_fields)]
17pub enum MinifierType {
18 JsModule,
19 JsScript,
20 Json,
21 Css,
22 Html,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
26#[serde(deny_unknown_fields)]
27#[serde(rename_all = "kebab-case")]
28pub enum CollapseWhitespaces {
29 None,
31 All,
33 Smart,
35 Conservative,
39 AdvancedConservative,
44 #[default]
48 OnlyMetadata,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
52#[serde(deny_unknown_fields)]
53#[serde(rename_all = "kebab-case")]
54pub enum RemoveRedundantAttributes {
55 None,
57 All,
59 #[default]
63 Smart,
64}
65
66#[derive(Debug, Serialize, Deserialize, Clone)]
67#[serde(deny_unknown_fields)]
68#[serde(untagged)]
69pub enum MinifyJsonOption {
70 Bool(bool),
71 Options(Box<JsonOptions>),
72}
73
74#[derive(Debug, Serialize, Deserialize, Clone)]
75#[serde(rename_all = "camelCase")]
76#[serde(deny_unknown_fields)]
77pub struct JsonOptions {
78 pub pretty: bool,
79}
80
81#[derive(Debug, Serialize, Deserialize, Clone)]
82#[serde(deny_unknown_fields)]
83#[serde(untagged)]
84pub enum MinifyJsOption {
85 Bool(bool),
86 Options(Box<JsOptions>),
87}
88
89#[derive(Debug, Serialize, Deserialize, Clone)]
90#[serde(rename_all = "camelCase")]
91#[serde(deny_unknown_fields)]
92pub struct JsOptions {
93 #[serde(default)]
94 pub parser: JsParserOptions,
95 #[serde(default)]
96 pub minifier: JsMinifyOptions,
97 #[serde(default)]
98 pub codegen: JsCodegenOptions,
99}
100
101#[derive(Default, Debug, Serialize, Deserialize, Clone)]
102#[serde(rename_all = "camelCase")]
103pub struct JsParserOptions {
104 #[serde(default)]
105 pub comments: bool,
106 #[serde(flatten)]
107 pub syntax: Syntax,
108 #[serde(default)]
109 pub target: EsVersion,
110}
111
112#[derive(Debug, Serialize, Deserialize, Clone)]
113#[serde(deny_unknown_fields)]
114#[serde(untagged)]
115pub enum MinifyCssOption<CO> {
116 Bool(bool),
117 Options(CO),
118}
119
120#[cfg(feature = "default-css-minifier")]
121#[derive(Debug, Serialize, Deserialize, Clone)]
122#[serde(rename_all = "camelCase")]
123#[serde(deny_unknown_fields)]
124pub struct CssOptions {
125 #[serde(default)]
126 pub parser: CssParserOptions,
127 #[serde(default)]
128 pub minifier: CssMinifyOptions,
129 #[serde(default)]
130 pub codegen: CssCodegenOptions,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134#[serde(rename_all = "camelCase")]
135#[serde(deny_unknown_fields)]
136pub struct MinifyOptions<CO> {
137 #[serde(default)]
138 pub force_set_html5_doctype: bool,
139 #[serde(default)]
140 pub collapse_whitespaces: CollapseWhitespaces,
141 #[serde(default = "true_by_default")]
144 pub remove_empty_metadata_elements: bool,
145 #[serde(default = "true_by_default")]
146 pub remove_comments: bool,
147 #[serde(default = "default_preserve_comments")]
148 pub preserve_comments: Option<Vec<CachedRegex>>,
149 #[serde(default = "true_by_default")]
150 pub minify_conditional_comments: bool,
151 #[serde(default = "true_by_default")]
158 pub remove_empty_attributes: bool,
159 #[serde(default)]
160 pub remove_redundant_attributes: RemoveRedundantAttributes,
161 #[serde(default = "true_by_default")]
162 pub collapse_boolean_attributes: bool,
163 #[serde(default = "true_by_default")]
166 pub merge_metadata_elements: bool,
167 #[serde(default = "true_by_default")]
171 pub normalize_attributes: bool,
172 #[serde(default = "minify_json_by_default")]
173 pub minify_json: MinifyJsonOption,
174 #[serde(default = "minify_js_by_default")]
175 pub minify_js: MinifyJsOption,
176 #[serde(default = "minify_css_by_default")]
177 pub minify_css: MinifyCssOption<CO>,
178 #[serde(default)]
185 pub minify_additional_scripts_content: Option<Vec<(CachedRegex, MinifierType)>>,
186 pub minify_additional_attributes: Option<Vec<(CachedRegex, MinifierType)>>,
193 #[serde(default = "true_by_default")]
195 pub sort_space_separated_attribute_values: bool,
196 #[serde(default)]
197 pub sort_attributes: bool,
198}
199
200impl<CO: DeserializeOwned> Default for MinifyOptions<CO> {
202 fn default() -> Self {
203 serde_json::from_value(serde_json::Value::Object(Default::default())).unwrap()
204 }
205}
206
207const fn true_by_default() -> bool {
208 true
209}
210
211const fn minify_json_by_default() -> MinifyJsonOption {
212 MinifyJsonOption::Bool(true)
213}
214
215const fn minify_js_by_default() -> MinifyJsOption {
216 MinifyJsOption::Bool(true)
217}
218
219const fn minify_css_by_default<CO>() -> MinifyCssOption<CO> {
220 MinifyCssOption::Bool(true)
221}
222
223fn default_preserve_comments() -> Option<Vec<CachedRegex>> {
224 Some(vec![
225 CachedRegex::new("@preserve").unwrap(),
227 CachedRegex::new("@copyright").unwrap(),
228 CachedRegex::new("@lic").unwrap(),
229 CachedRegex::new("@cc_on").unwrap(),
230 CachedRegex::new("^!").unwrap(),
232 CachedRegex::new("^\\s*#").unwrap(),
234 CachedRegex::new("^\\[if\\s[^\\]+]").unwrap(),
236 CachedRegex::new("\\[endif]").unwrap(),
237 ])
238}