csskit_transform/
reduce_urls.rs1use crate::prelude::*;
2use css_ast::{Url, UrlOrString, Visitable};
3
4pub struct ReduceUrls<'a, 'ctx, N: Visitable + NodeWithMetadata<CssMetadata>> {
5 pub transformer: &'ctx Transformer<'a, CssMetadata, N, CssMinifierFeature>,
6}
7
8impl<'a, 'ctx, N> Transform<'a, 'ctx, CssMetadata, N, CssMinifierFeature> for ReduceUrls<'a, 'ctx, N>
9where
10 N: Visitable + NodeWithMetadata<CssMetadata>,
11{
12 fn may_change(features: CssMinifierFeature, _node: &N) -> bool {
13 features.contains(CssMinifierFeature::ReduceUrls)
14 }
15
16 fn new(transformer: &'ctx Transformer<'a, CssMetadata, N, CssMinifierFeature>) -> Self {
17 Self { transformer }
18 }
19}
20
21impl<'a, 'ctx, N> Visit for ReduceUrls<'a, 'ctx, N>
22where
23 N: Visitable + NodeWithMetadata<CssMetadata>,
24{
25 fn visit_url_or_string(&mut self, url_or_string: &UrlOrString) {
26 let url = match url_or_string {
27 UrlOrString::Url(url) => url,
28 UrlOrString::String(_) => return,
29 };
30 match url {
31 Url::UrlFunction(_, string, _) | Url::SrcFunction(_, string, _) => {
32 self.transformer.replace_parsed::<UrlOrString>(
33 url_or_string.to_span(),
34 &format!("\"{}\"", {
35 let sc = self.transformer.to_source_cursor((*string).into());
36 let token = sc.token();
37 let start = token.leading_len() as usize;
38 let end = sc.source().len() - token.trailing_len() as usize;
39 &sc.source()[start..end]
40 }),
41 );
42 }
43 Url::Url(url_token) => {
44 let sc = self.transformer.to_source_cursor((*url_token).into());
45 let token = sc.token();
46 let leading_len = token.leading_len() as usize;
47 let trailing_len = token.trailing_len() as usize;
48 let url_content = &sc.source()[leading_len..(sc.source().len() - trailing_len)];
49 let url_content = url_content.trim();
50 self.transformer
51 .replace_parsed::<UrlOrString>(url_or_string.to_span(), &format!("\"{}\"", url_content));
52 }
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use crate::test_helpers::{assert_no_transform, assert_transform};
60 use css_ast::{CssAtomSet, StyleSheet};
61
62 #[test]
63 fn reduces_url_function_to_string_in_import() {
64 assert_transform!(
65 CssMinifierFeature::ReduceUrls,
66 CssAtomSet,
67 StyleSheet,
68 "@import url(\"foo.css\");",
69 "@import \"foo.css\";"
70 );
71 }
72
73 #[test]
74 fn reduces_url_function_single_quotes_to_string_in_import() {
75 assert_transform!(
76 CssMinifierFeature::ReduceUrls,
77 CssAtomSet,
78 StyleSheet,
79 "@import url('foo.css');",
80 "@import \"foo.css\";"
81 );
82 }
83
84 #[test]
85 fn reduces_bare_url_to_string_in_import() {
86 assert_transform!(
87 CssMinifierFeature::ReduceUrls,
88 CssAtomSet,
89 StyleSheet,
90 "@import url(foo.css);",
91 "@import \"foo.css\";"
92 );
93 }
94
95 #[test]
96 fn reduces_url_with_media_query() {
97 assert_transform!(
98 CssMinifierFeature::ReduceUrls,
99 CssAtomSet,
100 StyleSheet,
101 "@import url(\"foo.css\") screen;",
102 "@import \"foo.css\" screen;"
103 );
104 }
105
106 #[test]
107 fn reduces_url_with_layer() {
108 assert_transform!(
109 CssMinifierFeature::ReduceUrls,
110 CssAtomSet,
111 StyleSheet,
112 "@import url(\"foo.css\") layer;",
113 "@import \"foo.css\" layer;"
114 );
115 }
116
117 #[test]
118 fn reduces_url_with_supports() {
119 assert_transform!(
120 CssMinifierFeature::ReduceUrls,
121 CssAtomSet,
122 StyleSheet,
123 "@import url(\"foo.css\") supports(not (display: flex));",
124 "@import \"foo.css\" supports(not (display: flex));"
125 );
126 }
127
128 #[test]
129 fn reduces_url_with_layer_and_supports() {
130 assert_transform!(
131 CssMinifierFeature::ReduceUrls,
132 CssAtomSet,
133 StyleSheet,
134 "@import url(\"foo.css\") layer(base) supports(not (display: flex));",
135 "@import \"foo.css\" layer(base) supports(not (display: flex));"
136 );
137 }
138
139 #[test]
140 fn does_not_transform_bare_string() {
141 assert_no_transform!(CssMinifierFeature::ReduceUrls, CssAtomSet, StyleSheet, "@import \"foo.css\";");
142 }
143
144 #[test]
145 fn reduces_namespace_url_to_string() {
146 assert_transform!(
147 CssMinifierFeature::ReduceUrls,
148 CssAtomSet,
149 StyleSheet,
150 "@namespace url(\"http://www.w3.org/1999/xhtml\");",
151 "@namespace \"http://www.w3.org/1999/xhtml\";"
152 );
153 }
154
155 #[test]
156 fn reduces_namespace_url_with_prefix() {
157 assert_transform!(
158 CssMinifierFeature::ReduceUrls,
159 CssAtomSet,
160 StyleSheet,
161 "@namespace html url(\"http://www.w3.org/1999/xhtml\");",
162 "@namespace html \"http://www.w3.org/1999/xhtml\";"
163 );
164 }
165}