@swc/plugin-styled-jsx 1.5.83 → 1.5.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/package.json +1 -1
  2. package/swc_plugin_styled_jsx.wasm +0 -0
  3. package/transform/Cargo.toml +0 -39
  4. package/transform/src/lib.rs +0 -7
  5. package/transform/src/lifetime.rs +0 -408
  6. package/transform/src/style.rs +0 -25
  7. package/transform/src/transform_css_lightningcss.rs +0 -589
  8. package/transform/src/transform_css_swc.rs +0 -392
  9. package/transform/src/utils.rs +0 -371
  10. package/transform/src/visitor.rs +0 -963
  11. package/transform/tests/errors/nested-style-tags/input.js +0 -31
  12. package/transform/tests/errors/nested-style-tags/output-lightningcss.js +0 -58
  13. package/transform/tests/errors/nested-style-tags/output-lightningcss.stderr +0 -27
  14. package/transform/tests/errors/nested-style-tags/output-swc.js +0 -58
  15. package/transform/tests/errors/nested-style-tags/output-swc.stderr +0 -27
  16. package/transform/tests/errors/nested-style-tags/output.js +0 -58
  17. package/transform/tests/errors/no-child/input.js +0 -6
  18. package/transform/tests/errors/no-child/output-lightningcss.js +0 -8
  19. package/transform/tests/errors/no-child/output-lightningcss.stderr +0 -9
  20. package/transform/tests/errors/no-child/output-swc.js +0 -8
  21. package/transform/tests/errors/no-child/output-swc.stderr +0 -9
  22. package/transform/tests/errors/no-child/output.js +0 -8
  23. package/transform/tests/errors/ts-with-css-resolve/input.js +0 -10
  24. package/transform/tests/errors/ts-with-css-resolve/output-lightningcss.js +0 -5
  25. package/transform/tests/errors/ts-with-css-resolve/output-lightningcss.stderr +0 -2
  26. package/transform/tests/errors/ts-with-css-resolve/output-swc.js +0 -5
  27. package/transform/tests/errors/ts-with-css-resolve/output-swc.stderr +0 -2
  28. package/transform/tests/errors/ts-with-css-resolve/output.js +0 -5
  29. package/transform/tests/errors/two-children/input.js +0 -8
  30. package/transform/tests/errors/two-children/output-lightningcss.js +0 -12
  31. package/transform/tests/errors/two-children/output-lightningcss.stderr +0 -11
  32. package/transform/tests/errors/two-children/output-swc.js +0 -12
  33. package/transform/tests/errors/two-children/output-swc.stderr +0 -11
  34. package/transform/tests/errors/two-children/output.js +0 -12
  35. package/transform/tests/errors/wrong-child-type/input.js +0 -7
  36. package/transform/tests/errors/wrong-child-type/output-lightningcss.js +0 -10
  37. package/transform/tests/errors/wrong-child-type/output-lightningcss.stderr +0 -10
  38. package/transform/tests/errors/wrong-child-type/output-swc.js +0 -10
  39. package/transform/tests/errors/wrong-child-type/output-swc.stderr +0 -10
  40. package/transform/tests/errors/wrong-child-type/output.js +0 -10
  41. package/transform/tests/errors/wrong-jsx-expression-type/input.js +0 -7
  42. package/transform/tests/errors/wrong-jsx-expression-type/output-lightningcss.js +0 -10
  43. package/transform/tests/errors/wrong-jsx-expression-type/output-lightningcss.stderr +0 -10
  44. package/transform/tests/errors/wrong-jsx-expression-type/output-swc.js +0 -10
  45. package/transform/tests/errors/wrong-jsx-expression-type/output-swc.stderr +0 -10
  46. package/transform/tests/errors/wrong-jsx-expression-type/output.js +0 -10
  47. package/transform/tests/fixture/.expressions/input.js +0 -90
  48. package/transform/tests/fixture/absent/input.js +0 -6
  49. package/transform/tests/fixture/absent/output.lightningcss.js +0 -7
  50. package/transform/tests/fixture/absent/output.swc.js +0 -7
  51. package/transform/tests/fixture/attribute-generation-classname-rewriting/input.js +0 -55
  52. package/transform/tests/fixture/attribute-generation-classname-rewriting/output.lightningcss.js +0 -112
  53. package/transform/tests/fixture/attribute-generation-classname-rewriting/output.swc.js +0 -112
  54. package/transform/tests/fixture/attribute-generation-modes/input.js +0 -166
  55. package/transform/tests/fixture/attribute-generation-modes/output.lightningcss.js +0 -228
  56. package/transform/tests/fixture/attribute-generation-modes/output.swc.js +0 -228
  57. package/transform/tests/fixture/class/input.js +0 -14
  58. package/transform/tests/fixture/class/output.lightningcss.js +0 -12
  59. package/transform/tests/fixture/class/output.swc.js +0 -12
  60. package/transform/tests/fixture/comments/input.js +0 -18
  61. package/transform/tests/fixture/comments/output.lightningcss.js +0 -12
  62. package/transform/tests/fixture/comments/output.swc.js +0 -12
  63. package/transform/tests/fixture/component-attribute/input.js +0 -11
  64. package/transform/tests/fixture/component-attribute/output.lightningcss.js +0 -10
  65. package/transform/tests/fixture/component-attribute/output.swc.js +0 -10
  66. package/transform/tests/fixture/conflicts/input.js +0 -16
  67. package/transform/tests/fixture/conflicts/output.lightningcss.js +0 -14
  68. package/transform/tests/fixture/conflicts/output.swc.js +0 -14
  69. package/transform/tests/fixture/css-selector-after-pseudo/input.js +0 -18
  70. package/transform/tests/fixture/css-selector-after-pseudo/output.lightningcss.js +0 -11
  71. package/transform/tests/fixture/css-selector-after-pseudo/output.swc.js +0 -11
  72. package/transform/tests/fixture/css-tag-same-file/input.js +0 -25
  73. package/transform/tests/fixture/css-tag-same-file/output.lightningcss.js +0 -21
  74. package/transform/tests/fixture/css-tag-same-file/output.swc.js +0 -21
  75. package/transform/tests/fixture/different-jsx-ids/input.js +0 -23
  76. package/transform/tests/fixture/different-jsx-ids/output.lightningcss.js +0 -24
  77. package/transform/tests/fixture/different-jsx-ids/output.swc.js +0 -24
  78. package/transform/tests/fixture/dynamic-element/input.js +0 -56
  79. package/transform/tests/fixture/dynamic-element/output.lightningcss.js +0 -40
  80. package/transform/tests/fixture/dynamic-element/output.swc.js +0 -40
  81. package/transform/tests/fixture/dynamic-element-class/input.js +0 -32
  82. package/transform/tests/fixture/dynamic-element-class/output.lightningcss.js +0 -25
  83. package/transform/tests/fixture/dynamic-element-class/output.swc.js +0 -25
  84. package/transform/tests/fixture/dynamic-element-external/input.js +0 -12
  85. package/transform/tests/fixture/dynamic-element-external/output.lightningcss.js +0 -12
  86. package/transform/tests/fixture/dynamic-element-external/output.swc.js +0 -12
  87. package/transform/tests/fixture/dynamic-this-in-arrow/input.js +0 -41
  88. package/transform/tests/fixture/dynamic-this-in-arrow/output.lightningcss.js +0 -39
  89. package/transform/tests/fixture/dynamic-this-in-arrow/output.swc.js +0 -39
  90. package/transform/tests/fixture/exported-jsx-style/input.js +0 -1
  91. package/transform/tests/fixture/exported-jsx-style/output.lightningcss.js +0 -1
  92. package/transform/tests/fixture/exported-jsx-style/output.swc.js +0 -1
  93. package/transform/tests/fixture/exported-non-jsx-style/input.js +0 -1
  94. package/transform/tests/fixture/exported-non-jsx-style/output.lightningcss.js +0 -1
  95. package/transform/tests/fixture/exported-non-jsx-style/output.swc.js +0 -1
  96. package/transform/tests/fixture/external-nested-scope/input.js +0 -5
  97. package/transform/tests/fixture/external-nested-scope/output.lightningcss.js +0 -7
  98. package/transform/tests/fixture/external-nested-scope/output.swc.js +0 -7
  99. package/transform/tests/fixture/external-stylesheet/input.js +0 -41
  100. package/transform/tests/fixture/external-stylesheet/output.lightningcss.js +0 -34
  101. package/transform/tests/fixture/external-stylesheet/output.swc.js +0 -34
  102. package/transform/tests/fixture/external-stylesheet-global/input.js +0 -19
  103. package/transform/tests/fixture/external-stylesheet-global/output.lightningcss.js +0 -18
  104. package/transform/tests/fixture/external-stylesheet-global/output.swc.js +0 -18
  105. package/transform/tests/fixture/external-stylesheet-multi-line/input.js +0 -9
  106. package/transform/tests/fixture/external-stylesheet-multi-line/output.lightningcss.js +0 -9
  107. package/transform/tests/fixture/external-stylesheet-multi-line/output.swc.js +0 -9
  108. package/transform/tests/fixture/fragment/input.js +0 -51
  109. package/transform/tests/fixture/fragment/output.lightningcss.js +0 -47
  110. package/transform/tests/fixture/fragment/output.swc.js +0 -47
  111. package/transform/tests/fixture/global/input.js +0 -22
  112. package/transform/tests/fixture/global/output.lightningcss.js +0 -7
  113. package/transform/tests/fixture/global/output.swc.js +0 -7
  114. package/transform/tests/fixture/global-child-selector/input.js +0 -10
  115. package/transform/tests/fixture/global-child-selector/output.lightningcss.js +0 -8
  116. package/transform/tests/fixture/global-child-selector/output.swc.js +0 -8
  117. package/transform/tests/fixture/global-redundant/input.js +0 -12
  118. package/transform/tests/fixture/global-redundant/output.lightningcss.js +0 -10
  119. package/transform/tests/fixture/global-redundant/output.swc.js +0 -10
  120. package/transform/tests/fixture/issue-30480/input.js +0 -11
  121. package/transform/tests/fixture/issue-30480/output.lightningcss.js +0 -15
  122. package/transform/tests/fixture/issue-30480/output.swc.js +0 -15
  123. package/transform/tests/fixture/issue-30570/input.js +0 -15
  124. package/transform/tests/fixture/issue-30570/output.lightningcss.js +0 -12
  125. package/transform/tests/fixture/issue-30570/output.swc.js +0 -12
  126. package/transform/tests/fixture/issue-31562-interpolation-in-mdea/input.js +0 -30
  127. package/transform/tests/fixture/issue-31562-interpolation-in-mdea/output.lightningcss.js +0 -43
  128. package/transform/tests/fixture/issue-31562-interpolation-in-mdea/output.swc.js +0 -43
  129. package/transform/tests/fixture/mixed-global-scoped/input.js +0 -9
  130. package/transform/tests/fixture/mixed-global-scoped/output.lightningcss.js +0 -11
  131. package/transform/tests/fixture/mixed-global-scoped/output.swc.js +0 -11
  132. package/transform/tests/fixture/multiple-jsx/input.js +0 -43
  133. package/transform/tests/fixture/multiple-jsx/output.lightningcss.js +0 -32
  134. package/transform/tests/fixture/multiple-jsx/output.swc.js +0 -32
  135. package/transform/tests/fixture/nested-style-tags/index.js +0 -0
  136. package/transform/tests/fixture/next-54653/input.js +0 -10
  137. package/transform/tests/fixture/next-54653/output.lightningcss.js +0 -3
  138. package/transform/tests/fixture/next-54653/output.swc.js +0 -3
  139. package/transform/tests/fixture/non-styled-jsx-style/input.js +0 -7
  140. package/transform/tests/fixture/non-styled-jsx-style/output.lightningcss.js +0 -12
  141. package/transform/tests/fixture/non-styled-jsx-style/output.swc.js +0 -12
  142. package/transform/tests/fixture/not-styled-jsx-tagged-templates/input.js +0 -30
  143. package/transform/tests/fixture/not-styled-jsx-tagged-templates/output.lightningcss.js +0 -23
  144. package/transform/tests/fixture/not-styled-jsx-tagged-templates/output.swc.js +0 -23
  145. package/transform/tests/fixture/number-after-placeholder/input.js +0 -17
  146. package/transform/tests/fixture/number-after-placeholder/output.lightningcss.js +0 -17
  147. package/transform/tests/fixture/number-after-placeholder/output.swc.js +0 -17
  148. package/transform/tests/fixture/one-off-global-selectors/input.js +0 -10
  149. package/transform/tests/fixture/one-off-global-selectors/output.lightningcss.js +0 -8
  150. package/transform/tests/fixture/one-off-global-selectors/output.swc.js +0 -8
  151. package/transform/tests/fixture/source-maps/input.js +0 -8
  152. package/transform/tests/fixture/source-maps/output.lightningcss.js +0 -8
  153. package/transform/tests/fixture/source-maps/output.swc.js +0 -8
  154. package/transform/tests/fixture/stateless/input.js +0 -8
  155. package/transform/tests/fixture/stateless/output.lightningcss.js +0 -12
  156. package/transform/tests/fixture/stateless/output.swc.js +0 -12
  157. package/transform/tests/fixture/styles/input.js +0 -57
  158. package/transform/tests/fixture/styles/output.lightningcss.js +0 -39
  159. package/transform/tests/fixture/styles/output.swc.js +0 -39
  160. package/transform/tests/fixture/styles-external-invalid/input.js +0 -13
  161. package/transform/tests/fixture/styles-external-invalid/output.lightningcss.js +0 -9
  162. package/transform/tests/fixture/styles-external-invalid/output.swc.js +0 -9
  163. package/transform/tests/fixture/styles-external-invalid2/input.js +0 -11
  164. package/transform/tests/fixture/styles-external-invalid2/output.lightningcss.js +0 -8
  165. package/transform/tests/fixture/styles-external-invalid2/output.swc.js +0 -8
  166. package/transform/tests/fixture/styles2/input.js +0 -6
  167. package/transform/tests/fixture/styles2/output.lightningcss.js +0 -5
  168. package/transform/tests/fixture/styles2/output.swc.js +0 -5
  169. package/transform/tests/fixture/too-many/input.js +0 -35
  170. package/transform/tests/fixture/too-many/output.lightningcss.js +0 -49
  171. package/transform/tests/fixture/too-many/output.swc.js +0 -49
  172. package/transform/tests/fixture/tpl-escape-1/input.js +0 -14
  173. package/transform/tests/fixture/tpl-escape-1/output.lightningcss.js +0 -12
  174. package/transform/tests/fixture/tpl-escape-1/output.swc.js +0 -12
  175. package/transform/tests/fixture/tpl-escape-2/input.js +0 -17
  176. package/transform/tests/fixture/tpl-escape-2/output.lightningcss.js +0 -17
  177. package/transform/tests/fixture/tpl-escape-2/output.swc.js +0 -17
  178. package/transform/tests/fixture/tpl-placeholder-1-as-property/input.js +0 -17
  179. package/transform/tests/fixture/tpl-placeholder-1-as-property/output.lightningcss.js +0 -28
  180. package/transform/tests/fixture/tpl-placeholder-1-as-property/output.swc.js +0 -28
  181. package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/input.js +0 -21
  182. package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/output.lightningcss.js +0 -34
  183. package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/output.swc.js +0 -34
  184. package/transform/tests/fixture/tpl-placeholder-3-as-value/input.js +0 -17
  185. package/transform/tests/fixture/tpl-placeholder-3-as-value/output.lightningcss.js +0 -28
  186. package/transform/tests/fixture/tpl-placeholder-3-as-value/output.swc.js +0 -28
  187. package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/input.js +0 -17
  188. package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/output.lightningcss.js +0 -31
  189. package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/output.swc.js +0 -31
  190. package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/input.js +0 -16
  191. package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/output.lightningcss.js +0 -31
  192. package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/output.swc.js +0 -31
  193. package/transform/tests/fixture/transform-css/input.js +0 -176
  194. package/transform/tests/fixture/transform-css/output.lightningcss.js +0 -8
  195. package/transform/tests/fixture/transform-css/output.swc.js +0 -8
  196. package/transform/tests/fixture/transform-css-complex-selector/input.js +0 -116
  197. package/transform/tests/fixture/transform-css-complex-selector/output.lightningcss.js +0 -8
  198. package/transform/tests/fixture/transform-css-complex-selector/output.swc.js +0 -8
  199. package/transform/tests/fixture/transform-css-complex-selector-2/input.js +0 -12
  200. package/transform/tests/fixture/transform-css-complex-selector-2/output.lightningcss.js +0 -8
  201. package/transform/tests/fixture/transform-css-complex-selector-2/output.swc.js +0 -8
  202. package/transform/tests/fixture/transform-css-global/input.js +0 -32
  203. package/transform/tests/fixture/transform-css-global/output.lightningcss.js +0 -8
  204. package/transform/tests/fixture/transform-css-global/output.swc.js +0 -8
  205. package/transform/tests/fixture/transform-css-media-query/input.js +0 -24
  206. package/transform/tests/fixture/transform-css-media-query/output.lightningcss.js +0 -8
  207. package/transform/tests/fixture/transform-css-media-query/output.swc.js +0 -8
  208. package/transform/tests/fixture/transform-css-normal/input.js +0 -22
  209. package/transform/tests/fixture/transform-css-normal/output.lightningcss.js +0 -8
  210. package/transform/tests/fixture/transform-css-normal/output.swc.js +0 -8
  211. package/transform/tests/fixture/transform-css-nth-1/input.js +0 -10
  212. package/transform/tests/fixture/transform-css-nth-1/output.lightningcss.js +0 -8
  213. package/transform/tests/fixture/transform-css-nth-1/output.swc.js +0 -8
  214. package/transform/tests/fixture/whitespace/input.js +0 -12
  215. package/transform/tests/fixture/whitespace/output.lightningcss.js +0 -12
  216. package/transform/tests/fixture/whitespace/output.swc.js +0 -12
  217. package/transform/tests/fixture.rs +0 -129
@@ -1,963 +0,0 @@
1
- use std::{
2
- collections::hash_map::DefaultHasher,
3
- hash::{Hash, Hasher},
4
- mem::take,
5
- sync::Arc,
6
- };
7
-
8
- use easy_error::{bail, Error};
9
- use serde::Deserialize;
10
- use swc_common::{collections::AHashSet, errors::HANDLER, FileName, SourceMap, Span, DUMMY_SP};
11
- use swc_ecma_ast::*;
12
- use swc_ecma_minifier::{
13
- eval::{EvalResult, Evaluator},
14
- marks::Marks,
15
- };
16
- use swc_ecma_utils::{collect_decls, drop_span, prepend_stmt, private_ident};
17
- use swc_ecma_visit::{Fold, FoldWith};
18
-
19
- use crate::{
20
- style::{ExternalStyle, JSXStyle, LocalStyle},
21
- utils::{
22
- add, and, compute_class_names, get_usable_import_specifier, hash_string, ident,
23
- is_capitalized, make_external_styled_jsx_el, make_local_styled_jsx_el, not_eq, or,
24
- string_literal_expr, styled_jsx_import_decl,
25
- },
26
- };
27
-
28
- #[derive(Debug, Clone, Copy, Deserialize)]
29
- #[serde(rename_all = "camelCase")]
30
- pub struct Config {
31
- #[serde(default)]
32
- pub use_lightningcss: bool,
33
- }
34
-
35
- pub fn styled_jsx(cm: Arc<SourceMap>, file_name: FileName, config: Config) -> impl Fold {
36
- let file_name = match file_name {
37
- FileName::Real(real_file_name) => real_file_name
38
- .to_str()
39
- .map(|real_file_name| real_file_name.to_string()),
40
- _ => None,
41
- };
42
-
43
- StyledJSXTransformer {
44
- cm,
45
- config,
46
- file_name,
47
- styles: Default::default(),
48
- static_class_name: Default::default(),
49
- class_name: Default::default(),
50
- file_has_styled_jsx: Default::default(),
51
- has_styled_jsx: Default::default(),
52
- bindings: Default::default(),
53
- nearest_scope_bindings: Default::default(),
54
- func_scope_level: Default::default(),
55
- style_import_name: Default::default(),
56
- external_bindings: Default::default(),
57
- file_has_css_resolve: Default::default(),
58
- external_hash: Default::default(),
59
- add_hash: Default::default(),
60
- add_default_decl: Default::default(),
61
- in_function_params: Default::default(),
62
- evaluator: Default::default(),
63
- visiting_styled_jsx_descendants: Default::default(),
64
- }
65
- }
66
-
67
- struct StyledJSXTransformer {
68
- cm: Arc<SourceMap>,
69
- config: Config,
70
-
71
- file_name: Option<String>,
72
- styles: Vec<JSXStyle>,
73
- static_class_name: Option<String>,
74
- class_name: Option<Expr>,
75
- file_has_styled_jsx: bool,
76
- has_styled_jsx: bool,
77
- bindings: AHashSet<Id>,
78
- nearest_scope_bindings: AHashSet<Id>,
79
- func_scope_level: u8,
80
- style_import_name: Option<String>,
81
- external_bindings: Vec<Id>,
82
- file_has_css_resolve: bool,
83
- external_hash: Option<String>,
84
- add_hash: Option<(Id, String)>,
85
- add_default_decl: Option<(Id, Expr)>,
86
- in_function_params: bool,
87
- evaluator: Option<Evaluator>,
88
- visiting_styled_jsx_descendants: bool,
89
- }
90
-
91
- enum StyleExpr<'a> {
92
- Str(&'a Str),
93
- Tpl(&'a Tpl, &'a Expr),
94
- Ident(&'a Ident),
95
- }
96
-
97
- impl Fold for StyledJSXTransformer {
98
- fn fold_jsx_element(&mut self, el: JSXElement) -> JSXElement {
99
- if is_styled_jsx(&el) {
100
- if self.visiting_styled_jsx_descendants {
101
- HANDLER.with(|handler| {
102
- handler
103
- .struct_span_err(
104
- el.span,
105
- "Detected nested styled-jsx tag.\nRead more: https://nextjs.org/docs/messages/nested-styled-jsx-tags",
106
- )
107
- .emit()
108
- });
109
- return el;
110
- }
111
-
112
- let parent_has_styled_jsx = self.has_styled_jsx;
113
- if !parent_has_styled_jsx && self.check_for_jsx_styles(Some(&el), &el.children).is_err()
114
- {
115
- return el;
116
- }
117
- let el = match self.replace_jsx_style(&el) {
118
- Ok(el) => el,
119
- Err(_) => el,
120
- };
121
- if !parent_has_styled_jsx {
122
- self.reset_styles_state();
123
- }
124
- return el;
125
- }
126
-
127
- if self.has_styled_jsx {
128
- self.visiting_styled_jsx_descendants = true;
129
- let el = el.fold_children_with(self);
130
- self.visiting_styled_jsx_descendants = false;
131
- return el;
132
- }
133
-
134
- if self.check_for_jsx_styles(None, &el.children).is_err() {
135
- return el;
136
- }
137
- let el = el.fold_children_with(self);
138
- self.reset_styles_state();
139
-
140
- el
141
- }
142
-
143
- fn fold_jsx_fragment(&mut self, fragment: JSXFragment) -> JSXFragment {
144
- if self.has_styled_jsx {
145
- self.visiting_styled_jsx_descendants = true;
146
- let fragment = fragment.fold_children_with(self);
147
- self.visiting_styled_jsx_descendants = false;
148
- return fragment;
149
- }
150
-
151
- if self.check_for_jsx_styles(None, &fragment.children).is_err() {
152
- return fragment;
153
- };
154
- let fragment = fragment.fold_children_with(self);
155
- self.reset_styles_state();
156
-
157
- fragment
158
- }
159
-
160
- fn fold_jsx_opening_element(&mut self, mut el: JSXOpeningElement) -> JSXOpeningElement {
161
- if !self.has_styled_jsx {
162
- return el;
163
- }
164
-
165
- el.attrs = el.attrs.fold_with(self);
166
-
167
- if let JSXElementName::Ident(Ident { sym, span, .. }) = &el.name {
168
- if sym != "style"
169
- && sym != self.style_import_name.as_ref().unwrap()
170
- && (!is_capitalized(sym)
171
- || self
172
- .nearest_scope_bindings
173
- .contains(&(sym.clone(), span.ctxt)))
174
- {
175
- let (existing_class_name, existing_index, existing_spread_index) =
176
- get_existing_class_name(&el);
177
-
178
- let new_class_name = match (existing_class_name, &self.class_name) {
179
- (Some(existing_class_name), Some(class_name)) => Some(add(
180
- add(class_name.clone(), string_literal_expr(" ")),
181
- existing_class_name,
182
- )),
183
- (Some(existing_class_name), None) => Some(existing_class_name),
184
- (None, Some(class_name)) => Some(class_name.clone()),
185
- _ => None,
186
- };
187
-
188
- if let Some(new_class_name) = new_class_name {
189
- let class_name_attr = JSXAttrOrSpread::JSXAttr(JSXAttr {
190
- span: DUMMY_SP,
191
- name: JSXAttrName::Ident(ident("className")),
192
- value: Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
193
- expr: JSXExpr::Expr(Box::new(new_class_name)),
194
- span: DUMMY_SP,
195
- })),
196
- });
197
- el.attrs.push(class_name_attr);
198
- }
199
- if let Some(existing_spread_index) = existing_spread_index {
200
- el.attrs.remove(existing_spread_index);
201
- }
202
- if let Some(existing_index) = existing_index {
203
- el.attrs.remove(existing_index);
204
- }
205
- }
206
- }
207
-
208
- el
209
- }
210
-
211
- fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
212
- let ImportDecl {
213
- ref src,
214
- ref specifiers,
215
- ..
216
- } = decl;
217
- if &src.value == "styled-jsx/css" {
218
- for specifier in specifiers {
219
- match specifier {
220
- ImportSpecifier::Default(default_specifier) => {
221
- self.external_bindings.push(default_specifier.local.to_id())
222
- }
223
- ImportSpecifier::Named(named_specifier) => {
224
- self.external_bindings.push(named_specifier.local.to_id())
225
- }
226
- _ => {}
227
- }
228
- }
229
- }
230
-
231
- decl
232
- }
233
-
234
- fn fold_expr(&mut self, expr: Expr) -> Expr {
235
- let expr = expr.fold_children_with(self);
236
- match expr {
237
- Expr::TaggedTpl(tagged_tpl) => match &*tagged_tpl.tag {
238
- Expr::Ident(identifier) => {
239
- if self.external_bindings.contains(&identifier.to_id()) {
240
- match self.process_tagged_template_expr(&tagged_tpl, &identifier.sym) {
241
- Ok(expr) => expr,
242
- Err(_) => Expr::TaggedTpl(tagged_tpl),
243
- }
244
- } else {
245
- Expr::TaggedTpl(tagged_tpl)
246
- }
247
- }
248
- Expr::Member(MemberExpr {
249
- obj: boxed_ident, ..
250
- }) => {
251
- if let Expr::Ident(identifier) = &**boxed_ident {
252
- if self.external_bindings.contains(&identifier.to_id()) {
253
- match self.process_tagged_template_expr(&tagged_tpl, &identifier.sym) {
254
- Ok(expr) => expr,
255
- Err(_) => Expr::TaggedTpl(tagged_tpl),
256
- }
257
- } else {
258
- Expr::TaggedTpl(tagged_tpl)
259
- }
260
- } else {
261
- Expr::TaggedTpl(tagged_tpl)
262
- }
263
- }
264
- _ => Expr::TaggedTpl(tagged_tpl),
265
- },
266
- expr => expr,
267
- }
268
- }
269
-
270
- fn fold_var_declarator(&mut self, declarator: VarDeclarator) -> VarDeclarator {
271
- let declarator = declarator.fold_children_with(self);
272
- if let Some(external_hash) = &self.external_hash.take() {
273
- if let Pat::Ident(BindingIdent {
274
- id: Ident { span, sym, .. },
275
- ..
276
- }) = &declarator.name
277
- {
278
- self.add_hash = Some(((sym.clone(), span.ctxt), external_hash.clone()));
279
- }
280
- }
281
- declarator
282
- }
283
-
284
- fn fold_export_default_expr(&mut self, default_expr: ExportDefaultExpr) -> ExportDefaultExpr {
285
- let default_expr = default_expr.fold_children_with(self);
286
- if let Some(external_hash) = &self.external_hash.take() {
287
- let default_ident = private_ident!("_defaultExport");
288
- self.add_hash = Some((default_ident.to_id(), external_hash.clone()));
289
- self.add_default_decl = Some((default_ident.to_id(), *default_expr.expr));
290
- return ExportDefaultExpr {
291
- expr: Box::new(Expr::Ident(default_ident)),
292
- span: DUMMY_SP,
293
- };
294
- }
295
- default_expr
296
- }
297
-
298
- fn fold_block_stmt(&mut self, mut block: BlockStmt) -> BlockStmt {
299
- let mut new_stmts = vec![];
300
- for stmt in block.stmts {
301
- new_stmts.push(stmt.fold_children_with(self));
302
- if let Some(add_hash) = self.add_hash.take() {
303
- new_stmts.push(add_hash_statement(add_hash));
304
- }
305
- }
306
-
307
- block.stmts = new_stmts;
308
- block
309
- }
310
-
311
- fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
312
- let mut new_items = vec![];
313
- for item in items {
314
- let new_item = item.fold_children_with(self);
315
- if let Some((default_ident, default_expr)) = &self.add_default_decl {
316
- new_items.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl {
317
- kind: VarDeclKind::Const,
318
- declare: false,
319
- decls: vec![VarDeclarator {
320
- name: Pat::Ident(BindingIdent {
321
- id: Ident {
322
- sym: default_ident.0.clone(),
323
- span: DUMMY_SP.with_ctxt(default_ident.1),
324
- optional: false,
325
- },
326
- type_ann: None,
327
- }),
328
- init: Some(Box::new(default_expr.clone())),
329
- definite: false,
330
- span: DUMMY_SP,
331
- }],
332
- span: DUMMY_SP,
333
- })))));
334
- self.add_default_decl = None;
335
- if let Some(add_hash) = self.add_hash.take() {
336
- new_items.push(ModuleItem::Stmt(add_hash_statement(add_hash)));
337
- }
338
- }
339
- if !is_styled_css_import(&new_item) {
340
- new_items.push(new_item);
341
- }
342
- if let Some(add_hash) = self.add_hash.take() {
343
- new_items.push(ModuleItem::Stmt(add_hash_statement(add_hash)));
344
- }
345
- }
346
-
347
- if self.file_has_styled_jsx || self.file_has_css_resolve {
348
- prepend_stmt(
349
- &mut new_items,
350
- styled_jsx_import_decl(self.style_import_name.as_ref().unwrap()),
351
- );
352
- }
353
-
354
- new_items
355
- }
356
-
357
- fn fold_binding_ident(&mut self, node: BindingIdent) -> BindingIdent {
358
- if self.in_function_params {
359
- self.nearest_scope_bindings.insert(node.id.to_id());
360
- }
361
- node
362
- }
363
-
364
- fn fold_assign_pat_prop(&mut self, node: AssignPatProp) -> AssignPatProp {
365
- if self.in_function_params {
366
- self.nearest_scope_bindings.insert(node.key.to_id());
367
- }
368
- node
369
- }
370
-
371
- fn fold_function(&mut self, mut func: Function) -> Function {
372
- self.func_scope_level += 1;
373
- let surrounding_scope_bindings = take(&mut self.nearest_scope_bindings);
374
- self.in_function_params = true;
375
- let mut new_params = vec![];
376
- for param in func.params {
377
- new_params.push(param.fold_with(self));
378
- }
379
- func.params = new_params;
380
- self.in_function_params = false;
381
- self.nearest_scope_bindings.extend(collect_decls(&func));
382
- func.body = func.body.fold_with(self);
383
- self.nearest_scope_bindings = surrounding_scope_bindings;
384
- self.func_scope_level -= 1;
385
- func
386
- }
387
-
388
- fn fold_arrow_expr(&mut self, mut func: ArrowExpr) -> ArrowExpr {
389
- self.func_scope_level += 1;
390
- let surrounding_scope_bindings = take(&mut self.nearest_scope_bindings);
391
- self.in_function_params = true;
392
- let mut new_params = vec![];
393
- for param in func.params {
394
- new_params.push(param.fold_with(self));
395
- }
396
- func.params = new_params;
397
- self.in_function_params = false;
398
- self.nearest_scope_bindings.extend(collect_decls(&func));
399
- func.body = func.body.fold_with(self);
400
- self.nearest_scope_bindings = surrounding_scope_bindings;
401
- self.func_scope_level -= 1;
402
- func
403
- }
404
-
405
- fn fold_module(&mut self, module: Module) -> Module {
406
- self.bindings = collect_decls(&module);
407
- self.evaluator = Some(Evaluator::new(module.clone(), Marks::new()));
408
- self.style_import_name = Some(get_usable_import_specifier(&module.body));
409
- let module = module.fold_children_with(self);
410
- if self.file_has_css_resolve
411
- && self.file_name.is_some()
412
- && self.file_name.as_ref().unwrap().ends_with(".ts")
413
- {
414
- let file_name: &str = self.file_name.as_ref().unwrap();
415
- HANDLER.with(|handler| {
416
- handler.err(&format!(
417
- "{} uses `css.resolve`, but ends with `.ts`. The file extension needs to be \
418
- `.tsx` so that the jsx injected by `css.resolve` will be transformed.",
419
- file_name
420
- ));
421
- });
422
- }
423
- module
424
- }
425
- }
426
-
427
- impl StyledJSXTransformer {
428
- fn check_for_jsx_styles(
429
- &mut self,
430
- el: Option<&JSXElement>,
431
- children: &[JSXElementChild],
432
- ) -> Result<(), Error> {
433
- let mut styles = vec![];
434
- let mut process_style = |el: &JSXElement| {
435
- self.file_has_styled_jsx = true;
436
- self.has_styled_jsx = true;
437
- let expr = get_style_expr(el)?;
438
- let style_info = self.get_jsx_style(expr, is_global(el));
439
- styles.insert(0, style_info);
440
-
441
- Ok(())
442
- };
443
-
444
- if el.is_some() && is_styled_jsx(el.unwrap()) {
445
- process_style(el.unwrap())?;
446
- } else {
447
- for i in children {
448
- if let JSXElementChild::JSXElement(child_el) = &i {
449
- if is_styled_jsx(child_el) {
450
- process_style(child_el)?;
451
- }
452
- }
453
- }
454
- };
455
-
456
- if self.has_styled_jsx {
457
- let (static_class_name, class_name) =
458
- compute_class_names(&styles, self.style_import_name.as_ref().unwrap());
459
- self.styles = styles;
460
- self.static_class_name = static_class_name;
461
- self.class_name = class_name;
462
- }
463
-
464
- Ok(())
465
- }
466
-
467
- fn get_jsx_style(&mut self, style_expr: StyleExpr, is_global_jsx_element: bool) -> JSXStyle {
468
- let mut hasher = DefaultHasher::new();
469
- let css: String;
470
- let css_span: Span;
471
- let is_dynamic;
472
- let mut expressions = vec![];
473
- let mut is_expr_property = vec![];
474
- match style_expr {
475
- StyleExpr::Str(Str { value, span, .. }) => {
476
- hasher.write(value.as_ref().as_bytes());
477
- css = value.to_string();
478
- css_span = *span;
479
- is_dynamic = false;
480
- }
481
- StyleExpr::Tpl(
482
- Tpl {
483
- exprs,
484
- quasis,
485
- span,
486
- },
487
- expr,
488
- ) => {
489
- if exprs.is_empty() {
490
- hasher.write(quasis[0].raw.as_bytes());
491
- css = quasis[0].raw.to_string();
492
- css_span = *span;
493
- is_dynamic = false;
494
- } else {
495
- drop_span(expr.clone()).hash(&mut hasher);
496
- let mut s = String::new();
497
- for i in 0..quasis.len() {
498
- // TODO: Handle comments
499
-
500
- let before = &*quasis[i].raw;
501
- let before = before.trim();
502
-
503
- let placeholder = if i == quasis.len() - 1 {
504
- is_expr_property.push(false);
505
- String::new()
506
- } else if before.ends_with([';', '{']) {
507
- is_expr_property.push(true);
508
- format!("__styled-jsx-placeholder-{}__: 0", i)
509
- } else {
510
- is_expr_property.push(false);
511
- format!("__styled-jsx-placeholder-{}__", i)
512
- };
513
- s.push_str(&quasis[i].raw);
514
- s.push_str(&placeholder);
515
- }
516
- css = s;
517
- css_span = *span;
518
- is_dynamic = if self.func_scope_level > 0 {
519
- let res = self.evaluator.as_mut().unwrap().eval(expr);
520
- !matches!(res, Some(EvalResult::Lit(_)))
521
- } else {
522
- false
523
- };
524
- expressions = exprs.clone();
525
- }
526
- }
527
- StyleExpr::Ident(ident) => {
528
- return JSXStyle::External(ExternalStyle {
529
- expr: Expr::Member(MemberExpr {
530
- obj: Box::new(Expr::Ident(ident.clone())),
531
- prop: MemberProp::Ident(Ident {
532
- sym: "__hash".into(),
533
- span: DUMMY_SP,
534
- optional: false,
535
- }),
536
- span: DUMMY_SP,
537
- }),
538
- identifier: ident.clone(),
539
- is_global: is_global_jsx_element,
540
- });
541
- }
542
- }
543
-
544
- JSXStyle::Local(LocalStyle {
545
- hash: format!("{:x}", hasher.finish()),
546
- css,
547
- css_span,
548
- is_dynamic,
549
- expressions,
550
- is_expr_property,
551
- })
552
- }
553
-
554
- fn replace_jsx_style(&mut self, el: &JSXElement) -> Result<JSXElement, Error> {
555
- let style_info = self.styles.pop().unwrap();
556
-
557
- let is_global = el.opening.attrs.iter().any(|attr| {
558
- if let JSXAttrOrSpread::JSXAttr(JSXAttr {
559
- name: JSXAttrName::Ident(Ident { sym, .. }),
560
- ..
561
- }) = &attr
562
- {
563
- if sym == "global" {
564
- return true;
565
- }
566
- }
567
- false
568
- });
569
-
570
- match &style_info {
571
- JSXStyle::Local(style_info) => {
572
- let css = if self.config.use_lightningcss {
573
- crate::transform_css_lightningcss::transform_css(
574
- self.cm.clone(),
575
- style_info,
576
- is_global,
577
- &self.static_class_name,
578
- )?
579
- } else {
580
- crate::transform_css_swc::transform_css(
581
- self.cm.clone(),
582
- style_info,
583
- is_global,
584
- &self.static_class_name,
585
- )?
586
- };
587
-
588
- Ok(make_local_styled_jsx_el(
589
- style_info,
590
- css,
591
- self.style_import_name.as_ref().unwrap(),
592
- self.static_class_name.as_ref(),
593
- ))
594
- }
595
- JSXStyle::External(style) => Ok(make_external_styled_jsx_el(
596
- style,
597
- self.style_import_name.as_ref().unwrap(),
598
- )),
599
- }
600
- }
601
-
602
- fn process_tagged_template_expr(
603
- &mut self,
604
- tagged_tpl: &TaggedTpl,
605
- tag: &str,
606
- ) -> Result<Expr, Error> {
607
- if tag != "resolve" {
608
- // Check whether there are undefined references or
609
- // references to this.something (e.g. props or state).
610
- // We allow dynamic styles only when resolving styles.
611
- }
612
-
613
- let style = self.get_jsx_style(
614
- StyleExpr::Tpl(&tagged_tpl.tpl, &Expr::Tpl(*tagged_tpl.tpl.clone())),
615
- false,
616
- );
617
- let styles = vec![style];
618
- let (static_class_name, class_name) =
619
- compute_class_names(&styles, self.style_import_name.as_ref().unwrap());
620
- let tag = match &*tagged_tpl.tag {
621
- Expr::Ident(Ident { sym, .. }) => sym.to_string(),
622
- Expr::Member(MemberExpr {
623
- prop: MemberProp::Ident(Ident { sym, .. }),
624
- ..
625
- }) => sym.to_string(),
626
- _ => String::from("not_styled_jsx_tag"),
627
- };
628
- let style = if let JSXStyle::Local(style) = &styles[0] {
629
- if tag != "resolve" {
630
- self.external_hash = Some(hash_string(&style.hash.clone()));
631
- }
632
- style
633
- } else {
634
- bail!("This shouldn't happen, we already know that this is a template literal");
635
- };
636
- let css = if self.config.use_lightningcss {
637
- crate::transform_css_lightningcss::transform_css(
638
- self.cm.clone(),
639
- style,
640
- tag == "global",
641
- &static_class_name,
642
- )?
643
- } else {
644
- crate::transform_css_swc::transform_css(
645
- self.cm.clone(),
646
- style,
647
- tag == "global",
648
- &static_class_name,
649
- )?
650
- };
651
- if tag == "resolve" {
652
- self.file_has_css_resolve = true;
653
- return Ok(Expr::Object(ObjectLit {
654
- props: vec![
655
- PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
656
- key: PropName::Ident(Ident {
657
- sym: "styles".into(),
658
- span: DUMMY_SP,
659
- optional: false,
660
- }),
661
- value: Box::new(Expr::JSXElement(Box::new(make_local_styled_jsx_el(
662
- style,
663
- css,
664
- self.style_import_name.as_ref().unwrap(),
665
- self.static_class_name.as_ref(),
666
- )))),
667
- }))),
668
- PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
669
- key: PropName::Ident(Ident {
670
- sym: "className".into(),
671
- span: DUMMY_SP,
672
- optional: false,
673
- }),
674
- value: Box::new(class_name.unwrap()),
675
- }))),
676
- ],
677
- span: DUMMY_SP,
678
- }));
679
- }
680
- Ok(Expr::New(NewExpr {
681
- callee: Box::new(Expr::Ident(Ident {
682
- sym: "String".into(),
683
- span: DUMMY_SP,
684
- optional: false,
685
- })),
686
- args: Some(vec![ExprOrSpread {
687
- expr: Box::new(css),
688
- spread: None,
689
- }]),
690
- span: DUMMY_SP,
691
- type_args: None,
692
- }))
693
- }
694
-
695
- fn reset_styles_state(&mut self) {
696
- self.has_styled_jsx = false;
697
- self.static_class_name = None;
698
- self.class_name = None;
699
- self.styles = vec![];
700
- }
701
- }
702
-
703
- fn is_styled_jsx(el: &JSXElement) -> bool {
704
- if let JSXElementName::Ident(Ident { sym, .. }) = &el.opening.name {
705
- if sym != "style" {
706
- return false;
707
- }
708
- }
709
-
710
- el.opening.attrs.iter().any(|attr| {
711
- if let JSXAttrOrSpread::JSXAttr(JSXAttr {
712
- name: JSXAttrName::Ident(Ident { sym, .. }),
713
- ..
714
- }) = &attr
715
- {
716
- if sym == "jsx" {
717
- return true;
718
- }
719
- }
720
- false
721
- })
722
- }
723
-
724
- fn is_global(el: &JSXElement) -> bool {
725
- if let JSXElementName::Ident(Ident { sym, .. }) = &el.opening.name {
726
- if sym != "style" {
727
- return false;
728
- }
729
- }
730
-
731
- el.opening.attrs.iter().any(|attr| {
732
- if let JSXAttrOrSpread::JSXAttr(JSXAttr {
733
- name: JSXAttrName::Ident(Ident { sym, .. }),
734
- ..
735
- }) = &attr
736
- {
737
- if sym == "global" {
738
- return true;
739
- }
740
- }
741
- false
742
- })
743
- }
744
-
745
- fn get_style_expr(el: &JSXElement) -> Result<StyleExpr, Error> {
746
- let non_whitespace_children: &Vec<&JSXElementChild> = &el
747
- .children
748
- .iter()
749
- .filter(|child| {
750
- if let JSXElementChild::JSXText(txt) = child {
751
- if txt.value.chars().all(char::is_whitespace) {
752
- return false;
753
- }
754
- }
755
- true
756
- })
757
- .collect();
758
-
759
- if non_whitespace_children.len() != 1 {
760
- HANDLER.with(|handler| {
761
- handler
762
- .struct_span_err(
763
- el.span,
764
- &format!(
765
- "Expected one child under JSX style tag, but got {}.\nRead more: https://nextjs.org/docs/messages/invalid-styled-jsx-children",
766
- non_whitespace_children.len()
767
- ),
768
- )
769
- .emit()
770
- });
771
- bail!("styled-jsx style error");
772
- }
773
-
774
- if let JSXElementChild::JSXExprContainer(JSXExprContainer {
775
- expr: JSXExpr::Expr(expr),
776
- ..
777
- }) = non_whitespace_children[0]
778
- {
779
- return Ok(match &**expr {
780
- Expr::Lit(Lit::Str(str)) => StyleExpr::Str(str),
781
- Expr::Tpl(tpl) => StyleExpr::Tpl(tpl, expr),
782
- Expr::Ident(ident) => StyleExpr::Ident(ident),
783
- _ => {
784
- HANDLER.with(|handler| {
785
- handler
786
- .struct_span_err(
787
- el.span,
788
- "Expected a template literal, string or identifier inside the JSXExpressionContainer.\nRead more: https://nextjs.org/docs/messages/invalid-styled-jsx-children",
789
- )
790
- .emit()
791
- });
792
- bail!("wrong jsx expression container type");
793
- }
794
- });
795
- }
796
-
797
- HANDLER.with(|handler| {
798
- handler
799
- .struct_span_err(
800
- el.span,
801
- "Expected a single child of type JSXExpressionContainer under JSX Style tag.\nRead more: https://nextjs.org/docs/messages/invalid-styled-jsx-children",
802
- )
803
- .emit()
804
- });
805
- bail!("next-swc compilation error");
806
- }
807
-
808
- fn get_existing_class_name(el: &JSXOpeningElement) -> (Option<Expr>, Option<usize>, Option<usize>) {
809
- let mut spreads = vec![];
810
- let mut class_name_expr = None;
811
- let mut existing_index = None;
812
- let mut existing_spread_index = None;
813
- for i in (0..el.attrs.len()).rev() {
814
- match &el.attrs[i] {
815
- JSXAttrOrSpread::JSXAttr(JSXAttr {
816
- name: JSXAttrName::Ident(Ident { sym, .. }),
817
- value,
818
- ..
819
- }) => {
820
- if sym == "className" {
821
- existing_index = Some(i);
822
- class_name_expr = match value {
823
- Some(JSXAttrValue::Lit(str_lit)) => Some(Expr::Lit(str_lit.clone())),
824
- Some(JSXAttrValue::JSXExprContainer(JSXExprContainer {
825
- expr: JSXExpr::Expr(expr),
826
- ..
827
- })) => Some(*expr.clone()),
828
- None => None,
829
- _ => None,
830
- };
831
- break;
832
- }
833
- }
834
- JSXAttrOrSpread::SpreadElement(SpreadElement { expr, .. }) => {
835
- if let Expr::Object(ObjectLit { props, .. }) = &**expr {
836
- let mut has_spread = false;
837
- let mut has_class_name = false;
838
- for j in 0..props.len() {
839
- if let PropOrSpread::Prop(prop) = &props[j] {
840
- if let Prop::KeyValue(KeyValueProp {
841
- key: PropName::Ident(Ident { sym, .. }),
842
- value,
843
- }) = &**prop
844
- {
845
- if sym == "className" {
846
- has_class_name = true;
847
- class_name_expr = Some(*value.clone());
848
- if props.len() == 1 {
849
- existing_spread_index = Some(i);
850
- }
851
- }
852
- }
853
- } else {
854
- has_spread = true;
855
- }
856
- }
857
- if has_class_name {
858
- break;
859
- }
860
- if !has_spread {
861
- continue;
862
- }
863
- }
864
-
865
- let valid_spread = matches!(&**expr, Expr::Member(_) | Expr::Ident(_));
866
-
867
- if valid_spread {
868
- let member_dot_name = Expr::Member(MemberExpr {
869
- obj: Box::new(*expr.clone()),
870
- prop: MemberProp::Ident(ident("className")),
871
- span: DUMMY_SP,
872
- });
873
- // `${name} && ${name}.className != null && ${name}.className`
874
- spreads.push(and(
875
- and(
876
- *expr.clone(),
877
- not_eq(
878
- member_dot_name.clone(),
879
- Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
880
- ),
881
- ),
882
- member_dot_name.clone(),
883
- ));
884
- }
885
- }
886
- _ => {}
887
- };
888
- }
889
-
890
- let spread_expr = match spreads.len() {
891
- 0 => None,
892
- _ => Some(join_spreads(spreads)),
893
- };
894
-
895
- let class_name_expr = match class_name_expr {
896
- Some(e @ Expr::Tpl(_) | e @ Expr::Lit(Lit::Str(_))) => Some(e),
897
- None => None,
898
- _ => Some(or(class_name_expr.unwrap(), string_literal_expr(""))),
899
- };
900
-
901
- let existing_class_name_expr = match (spread_expr, class_name_expr) {
902
- (Some(spread_expr), Some(class_name_expr)) => Some(or(spread_expr, class_name_expr)),
903
- (Some(spread_expr), None) => Some(or(spread_expr, string_literal_expr(""))),
904
- (None, Some(class_name_expr)) => Some(class_name_expr),
905
- _ => None,
906
- };
907
-
908
- (
909
- existing_class_name_expr,
910
- existing_index,
911
- existing_spread_index,
912
- )
913
- }
914
-
915
- fn join_spreads(spreads: Vec<Expr>) -> Expr {
916
- let mut new_expr = spreads[0].clone();
917
- for i in spreads.iter().skip(1) {
918
- new_expr = Expr::Bin(BinExpr {
919
- op: op!("||"),
920
- left: Box::new(new_expr.clone()),
921
- right: Box::new(i.clone()),
922
- span: DUMMY_SP,
923
- })
924
- }
925
- new_expr
926
- }
927
-
928
- fn add_hash_statement((id, hash): (Id, String)) -> Stmt {
929
- Stmt::Expr(ExprStmt {
930
- expr: Box::new(Expr::Assign(AssignExpr {
931
- left: PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
932
- obj: Box::new(Expr::Ident(Ident {
933
- sym: id.0,
934
- span: DUMMY_SP.with_ctxt(id.1),
935
- optional: false,
936
- })),
937
- prop: MemberProp::Ident(Ident {
938
- sym: "__hash".into(),
939
- span: DUMMY_SP,
940
- optional: false,
941
- }),
942
- span: DUMMY_SP,
943
- }))),
944
- right: Box::new(string_literal_expr(&hash)),
945
- op: op!("="),
946
- span: DUMMY_SP,
947
- })),
948
- span: DUMMY_SP,
949
- })
950
- }
951
-
952
- fn is_styled_css_import(item: &ModuleItem) -> bool {
953
- if let ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
954
- src: box Str { value, .. },
955
- ..
956
- })) = item
957
- {
958
- if value == "styled-jsx/css" {
959
- return true;
960
- }
961
- }
962
- false
963
- }