@swc/plugin-styled-jsx 1.5.76 → 1.5.78

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 (128) hide show
  1. package/Cargo.toml +12 -11
  2. package/package.json +1 -1
  3. package/src/lib.rs +10 -3
  4. package/swc_plugin_styled_jsx.wasm +0 -0
  5. package/transform/Cargo.toml +19 -12
  6. package/transform/src/lib.rs +2 -1
  7. package/transform/src/style.rs +2 -1
  8. package/transform/src/{transform_css.rs → transform_css_lightningcss.rs} +5 -5
  9. package/transform/src/transform_css_swc.rs +392 -0
  10. package/transform/src/utils.rs +2 -1
  11. package/transform/src/visitor.rs +50 -21
  12. package/transform/tests/errors/nested-style-tags/output.js +31 -4
  13. package/transform/tests/errors/ts-with-css-resolve/output.js +1 -1
  14. package/transform/tests/fixture/absent/output.swc.js +7 -0
  15. package/transform/tests/fixture/attribute-generation-classname-rewriting/output.swc.js +112 -0
  16. package/transform/tests/fixture/attribute-generation-modes/output.swc.js +228 -0
  17. package/transform/tests/fixture/class/output.swc.js +12 -0
  18. package/transform/tests/fixture/comments/output.swc.js +12 -0
  19. package/transform/tests/fixture/component-attribute/output.swc.js +10 -0
  20. package/transform/tests/fixture/conflicts/output.swc.js +14 -0
  21. package/transform/tests/fixture/css-selector-after-pseudo/output.swc.js +11 -0
  22. package/transform/tests/fixture/css-tag-same-file/output.swc.js +21 -0
  23. package/transform/tests/fixture/different-jsx-ids/output.swc.js +24 -0
  24. package/transform/tests/fixture/dynamic-element/output.swc.js +40 -0
  25. package/transform/tests/fixture/dynamic-element-class/output.swc.js +25 -0
  26. package/transform/tests/fixture/dynamic-element-external/output.swc.js +12 -0
  27. package/transform/tests/fixture/dynamic-this-in-arrow/output.swc.js +39 -0
  28. package/transform/tests/fixture/exported-jsx-style/output.swc.js +1 -0
  29. package/transform/tests/fixture/exported-non-jsx-style/output.swc.js +1 -0
  30. package/transform/tests/fixture/external-nested-scope/output.swc.js +7 -0
  31. package/transform/tests/fixture/external-stylesheet/output.swc.js +34 -0
  32. package/transform/tests/fixture/external-stylesheet-global/output.swc.js +18 -0
  33. package/transform/tests/fixture/external-stylesheet-multi-line/output.swc.js +9 -0
  34. package/transform/tests/fixture/fragment/output.swc.js +47 -0
  35. package/transform/tests/fixture/global/output.swc.js +7 -0
  36. package/transform/tests/fixture/global-child-selector/output.swc.js +8 -0
  37. package/transform/tests/fixture/global-redundant/output.swc.js +10 -0
  38. package/transform/tests/fixture/issue-30480/output.swc.js +15 -0
  39. package/transform/tests/fixture/issue-30570/output.swc.js +12 -0
  40. package/transform/tests/fixture/issue-31562-interpolation-in-mdea/output.swc.js +43 -0
  41. package/transform/tests/fixture/mixed-global-scoped/output.swc.js +11 -0
  42. package/transform/tests/fixture/multiple-jsx/output.swc.js +32 -0
  43. package/transform/tests/fixture/next-54653/output.swc.js +3 -0
  44. package/transform/tests/fixture/non-styled-jsx-style/output.swc.js +12 -0
  45. package/transform/tests/fixture/not-styled-jsx-tagged-templates/{output.js → output.lightningcss.js} +1 -2
  46. package/transform/tests/fixture/not-styled-jsx-tagged-templates/output.swc.js +23 -0
  47. package/transform/tests/fixture/number-after-placeholder/output.swc.js +17 -0
  48. package/transform/tests/fixture/one-off-global-selectors/output.swc.js +8 -0
  49. package/transform/tests/fixture/source-maps/output.swc.js +8 -0
  50. package/transform/tests/fixture/styles/output.swc.js +39 -0
  51. package/transform/tests/fixture/styles-external-invalid/output.swc.js +9 -0
  52. package/transform/tests/fixture/styles-external-invalid2/output.swc.js +8 -0
  53. package/transform/tests/fixture/styles2/output.swc.js +5 -0
  54. package/transform/tests/fixture/too-many/output.swc.js +49 -0
  55. package/transform/tests/fixture/tpl-escape-1/output.swc.js +12 -0
  56. package/transform/tests/fixture/tpl-escape-2/output.swc.js +17 -0
  57. package/transform/tests/fixture/tpl-placeholder-1-as-property/output.swc.js +28 -0
  58. package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/output.swc.js +34 -0
  59. package/transform/tests/fixture/tpl-placeholder-3-as-value/output.swc.js +28 -0
  60. package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/output.swc.js +31 -0
  61. package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/output.swc.js +31 -0
  62. package/transform/tests/fixture/transform-css/output.swc.js +8 -0
  63. package/transform/tests/fixture/transform-css-complex-selector/output.swc.js +8 -0
  64. package/transform/tests/fixture/transform-css-complex-selector-2/output.swc.js +8 -0
  65. package/transform/tests/fixture/transform-css-global/output.swc.js +8 -0
  66. package/transform/tests/fixture/transform-css-media-query/output.swc.js +8 -0
  67. package/transform/tests/fixture/transform-css-normal/output.swc.js +8 -0
  68. package/transform/tests/fixture/transform-css-nth-1/output.swc.js +8 -0
  69. package/transform/tests/fixture/whitespace/output.lightningcss.js +12 -0
  70. package/transform/tests/fixture/whitespace/output.swc.js +12 -0
  71. package/transform/tests/fixture.rs +60 -49
  72. package/transform/tests/fixture/.expressions/output.js +0 -91
  73. package/transform/tests/fixture/nested-style-tags/output.js +0 -0
  74. /package/transform/tests/fixture/absent/{output.js → output.lightningcss.js} +0 -0
  75. /package/transform/tests/fixture/attribute-generation-classname-rewriting/{output.js → output.lightningcss.js} +0 -0
  76. /package/transform/tests/fixture/attribute-generation-modes/{output.js → output.lightningcss.js} +0 -0
  77. /package/transform/tests/fixture/class/{output.js → output.lightningcss.js} +0 -0
  78. /package/transform/tests/fixture/comments/{output.js → output.lightningcss.js} +0 -0
  79. /package/transform/tests/fixture/component-attribute/{output.js → output.lightningcss.js} +0 -0
  80. /package/transform/tests/fixture/conflicts/{output.js → output.lightningcss.js} +0 -0
  81. /package/transform/tests/fixture/css-selector-after-pseudo/{output.js → output.lightningcss.js} +0 -0
  82. /package/transform/tests/fixture/css-tag-same-file/{output.js → output.lightningcss.js} +0 -0
  83. /package/transform/tests/fixture/different-jsx-ids/{output.js → output.lightningcss.js} +0 -0
  84. /package/transform/tests/fixture/dynamic-element/{output.js → output.lightningcss.js} +0 -0
  85. /package/transform/tests/fixture/dynamic-element-class/{output.js → output.lightningcss.js} +0 -0
  86. /package/transform/tests/fixture/dynamic-element-external/{output.js → output.lightningcss.js} +0 -0
  87. /package/transform/tests/fixture/dynamic-this-in-arrow/{output.js → output.lightningcss.js} +0 -0
  88. /package/transform/tests/fixture/exported-jsx-style/{output.js → output.lightningcss.js} +0 -0
  89. /package/transform/tests/fixture/exported-non-jsx-style/{output.js → output.lightningcss.js} +0 -0
  90. /package/transform/tests/fixture/external-nested-scope/{output.js → output.lightningcss.js} +0 -0
  91. /package/transform/tests/fixture/external-stylesheet/{output.js → output.lightningcss.js} +0 -0
  92. /package/transform/tests/fixture/external-stylesheet-global/{output.js → output.lightningcss.js} +0 -0
  93. /package/transform/tests/fixture/external-stylesheet-multi-line/{output.js → output.lightningcss.js} +0 -0
  94. /package/transform/tests/fixture/fragment/{output.js → output.lightningcss.js} +0 -0
  95. /package/transform/tests/fixture/global/{output.js → output.lightningcss.js} +0 -0
  96. /package/transform/tests/fixture/global-child-selector/{output.js → output.lightningcss.js} +0 -0
  97. /package/transform/tests/fixture/global-redundant/{output.js → output.lightningcss.js} +0 -0
  98. /package/transform/tests/fixture/issue-30480/{output.js → output.lightningcss.js} +0 -0
  99. /package/transform/tests/fixture/issue-30570/{output.js → output.lightningcss.js} +0 -0
  100. /package/transform/tests/fixture/issue-31562-interpolation-in-mdea/{output.js → output.lightningcss.js} +0 -0
  101. /package/transform/tests/fixture/mixed-global-scoped/{output.js → output.lightningcss.js} +0 -0
  102. /package/transform/tests/fixture/multiple-jsx/{output.js → output.lightningcss.js} +0 -0
  103. /package/transform/tests/fixture/next-54653/{output.js → output.lightningcss.js} +0 -0
  104. /package/transform/tests/fixture/non-styled-jsx-style/{output.js → output.lightningcss.js} +0 -0
  105. /package/transform/tests/fixture/number-after-placeholder/{output.js → output.lightningcss.js} +0 -0
  106. /package/transform/tests/fixture/one-off-global-selectors/{output.js → output.lightningcss.js} +0 -0
  107. /package/transform/tests/fixture/source-maps/{output.js → output.lightningcss.js} +0 -0
  108. /package/transform/tests/fixture/stateless/{output.js → output.lightningcss.js} +0 -0
  109. /package/transform/tests/fixture/{whitespace/output.js → stateless/output.swc.js} +0 -0
  110. /package/transform/tests/fixture/styles/{output.js → output.lightningcss.js} +0 -0
  111. /package/transform/tests/fixture/styles-external-invalid/{output.js → output.lightningcss.js} +0 -0
  112. /package/transform/tests/fixture/styles-external-invalid2/{output.js → output.lightningcss.js} +0 -0
  113. /package/transform/tests/fixture/styles2/{output.js → output.lightningcss.js} +0 -0
  114. /package/transform/tests/fixture/too-many/{output.js → output.lightningcss.js} +0 -0
  115. /package/transform/tests/fixture/tpl-escape-1/{output.js → output.lightningcss.js} +0 -0
  116. /package/transform/tests/fixture/tpl-escape-2/{output.js → output.lightningcss.js} +0 -0
  117. /package/transform/tests/fixture/tpl-placeholder-1-as-property/{output.js → output.lightningcss.js} +0 -0
  118. /package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/{output.js → output.lightningcss.js} +0 -0
  119. /package/transform/tests/fixture/tpl-placeholder-3-as-value/{output.js → output.lightningcss.js} +0 -0
  120. /package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/{output.js → output.lightningcss.js} +0 -0
  121. /package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/{output.js → output.lightningcss.js} +0 -0
  122. /package/transform/tests/fixture/transform-css/{output.js → output.lightningcss.js} +0 -0
  123. /package/transform/tests/fixture/transform-css-complex-selector/{output.js → output.lightningcss.js} +0 -0
  124. /package/transform/tests/fixture/transform-css-complex-selector-2/{output.js → output.lightningcss.js} +0 -0
  125. /package/transform/tests/fixture/transform-css-global/{output.js → output.lightningcss.js} +0 -0
  126. /package/transform/tests/fixture/transform-css-media-query/{output.js → output.lightningcss.js} +0 -0
  127. /package/transform/tests/fixture/transform-css-normal/{output.js → output.lightningcss.js} +0 -0
  128. /package/transform/tests/fixture/transform-css-nth-1/{output.js → output.lightningcss.js} +0 -0
package/Cargo.toml CHANGED
@@ -11,22 +11,23 @@ version = "0.14.3"
11
11
  crate-type = ["cdylib", "rlib"]
12
12
 
13
13
  [features]
14
- custom_transform = ["swc_core/common_concurrent"]
14
+ custom_transform = ["swc_common/concurrent"]
15
15
 
16
16
  [dependencies]
17
17
  easy-error = "1.0.0"
18
18
  styled_jsx = { path = "./transform" }
19
- swc_core = { version = "0.83.0", features = [
20
- "common",
21
- "ecma_ast",
22
- "ecma_plugin_transform",
23
- "ecma_parser",
24
- "ecma_minifier",
25
- "ecma_utils",
26
- "ecma_visit",
27
- ] }
28
19
  tracing = { version = "0.1.37", features = ["release_max_level_off"] }
20
+ serde_json = "1"
21
+ swc_common = "0.32.1"
22
+ swc_ecma_ast = "0.109.1"
23
+ swc_ecma_parser = "0.140.0"
24
+ swc_ecma_minifier = "0.187.4"
25
+ swc_ecma_utils = "0.123.0"
26
+ swc_ecma_visit = "0.95.1"
27
+ swc_plugin_macro = "0.9.15"
28
+ swc_atoms = "0.5.9"
29
+ swc_core = { version = "0.83.5", features = ["ecma_plugin_transform"] }
29
30
 
30
31
  [dev-dependencies]
31
- swc_core = { features = ["testing_transform"], version = "0.83.0" }
32
+ swc_ecma_transforms_testing = "0.136.2"
32
33
  testing = "0.34.1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swc/plugin-styled-jsx",
3
- "version": "1.5.76",
3
+ "version": "1.5.78",
4
4
  "description": "SWC plugin for styled-jsx",
5
5
  "main": "swc_plugin_styled_jsx.wasm",
6
6
  "scripts": {
package/src/lib.rs CHANGED
@@ -1,7 +1,7 @@
1
1
  #![allow(clippy::not_unsafe_ptr_arg_deref)]
2
2
  #![feature(box_patterns)]
3
3
 
4
- use styled_jsx::visitor;
4
+ use styled_jsx::{visitor, visitor::Config};
5
5
  use swc_core::{
6
6
  common::{sync::Lrc, FileName, SourceMap},
7
7
  ecma::{ast::Program, visit::FoldWith},
@@ -9,9 +9,16 @@ use swc_core::{
9
9
  };
10
10
 
11
11
  #[plugin_transform]
12
- fn styled_jsx_plugin(program: Program, _: TransformPluginProgramMetadata) -> Program {
12
+ fn styled_jsx_plugin(program: Program, data: TransformPluginProgramMetadata) -> Program {
13
+ let config = serde_json::from_str::<Config>(
14
+ &data
15
+ .get_transform_plugin_config()
16
+ .expect("failed to get plugin config for styled-jsx"),
17
+ )
18
+ .expect("invalid config for styled-jsx");
19
+
13
20
  // TODO(kdy1): This is wrong, but it does not use cm
14
21
  let cm = Lrc::new(SourceMap::default());
15
22
 
16
- program.fold_with(&mut visitor::styled_jsx(cm, FileName::Anon))
23
+ program.fold_with(&mut visitor::styled_jsx(cm, FileName::Anon, config))
17
24
  }
Binary file
@@ -4,29 +4,36 @@ description = "AST transforms visitor for styled-jsx"
4
4
  edition = "2021"
5
5
  license = "Apache-2.0"
6
6
  name = "styled_jsx"
7
- version = "0.43.0"
7
+ version = "0.45.0"
8
8
 
9
9
  [features]
10
- custom_transform = ["swc_core/common_concurrent"]
10
+ custom_transform = ["swc_common/concurrent"]
11
11
 
12
12
  [dependencies]
13
13
  easy-error = "1.0.0"
14
14
  tracing = "0.1.37"
15
- lightningcss = { version = "1.0.0-alpha.44", features = [
15
+ lightningcss = { version = "1.0.0-alpha.46", features = [
16
16
  "visitor",
17
17
  "into_owned",
18
18
  ] }
19
19
  parcel_selectors = "0.26.0"
20
+ serde = { version = "1", features = ["derive"] }
20
21
 
21
- swc_core = { version = "0.83.0", features = [
22
- "common",
23
- "ecma_ast",
24
- "ecma_parser",
25
- "ecma_minifier",
26
- "ecma_utils",
27
- "ecma_visit",
28
- ] }
22
+ swc_common = "0.32.1"
23
+ swc_ecma_ast = "0.109.1"
24
+ swc_ecma_utils = "0.123.0"
25
+ swc_ecma_visit = "0.95.1"
26
+ swc_plugin_macro = "0.9.15"
27
+ swc_ecma_parser = "0.140.0"
28
+ swc_ecma_minifier = "0.187.4"
29
+ swc_css_ast = "0.139.1"
30
+ swc_css_codegen = "0.149.1"
31
+ swc_css_parser = "0.148.1"
32
+ swc_css_prefixer = "0.151.1"
33
+ swc_css_minifier = "0.114.1"
34
+ swc_css_visit = "0.138.1"
29
35
 
30
36
  [dev-dependencies]
31
37
  testing = "0.34.1"
32
- swc_core = { features = ["testing_transform"], version = "0.83.0" }
38
+ swc_ecma_transforms_testing = "0.136.1"
39
+ swc_ecma_transforms = "0.224.4"
@@ -1,6 +1,7 @@
1
1
  #![feature(box_patterns)]
2
2
  mod lifetime;
3
3
  pub mod style;
4
- mod transform_css;
4
+ mod transform_css_lightningcss;
5
+ mod transform_css_swc;
5
6
  mod utils;
6
7
  pub mod visitor;
@@ -1,4 +1,5 @@
1
- use swc_core::{common::Span, ecma::ast::*};
1
+ use swc_common::Span;
2
+ use swc_ecma_ast::*;
2
3
 
3
4
  pub struct ExternalStyle {
4
5
  pub expr: Expr,
@@ -18,10 +18,8 @@ use lightningcss::{
18
18
  visitor::{Visit, VisitTypes, Visitor},
19
19
  };
20
20
  use parcel_selectors::{parser::SelectorIter, SelectorImpl};
21
- use swc_core::{
22
- common::{errors::HANDLER, SourceMap, DUMMY_SP},
23
- ecma::ast::{Expr, Tpl, TplElement},
24
- };
21
+ use swc_common::{errors::HANDLER, SourceMap, DUMMY_SP};
22
+ use swc_ecma_ast::*;
25
23
  use tracing::{debug, error, trace};
26
24
 
27
25
  use crate::{
@@ -182,7 +180,9 @@ struct CssNamespace {
182
180
  impl<'i> Visitor<'i> for CssNamespace {
183
181
  type Error = Infallible;
184
182
 
185
- const TYPES: VisitTypes = visit_types!(SELECTORS);
183
+ fn visit_types(&self) -> VisitTypes {
184
+ visit_types!(SELECTORS)
185
+ }
186
186
 
187
187
  fn visit_selector(&mut self, selector: &mut Selector<'i>) -> Result<(), Self::Error> {
188
188
  let mut new_selectors = vec![];
@@ -0,0 +1,392 @@
1
+ use std::{panic, sync::Arc};
2
+
3
+ use easy_error::{bail, Error};
4
+ use swc_common::{
5
+ errors::HANDLER, source_map::Pos, util::take::Take, BytePos, SourceMap, Span, Spanned,
6
+ SyntaxContext, DUMMY_SP,
7
+ };
8
+ use swc_css_ast::{
9
+ ClassSelector, Combinator, CombinatorValue, ComplexSelector, ComplexSelectorChildren,
10
+ CompoundSelector, Ident, PseudoClassSelector, PseudoClassSelectorChildren, Stylesheet,
11
+ SubclassSelector, Token, TokenAndSpan,
12
+ };
13
+ use swc_css_codegen::{
14
+ writer::basic::{BasicCssWriter, BasicCssWriterConfig},
15
+ CodeGenerator, CodegenConfig, Emit,
16
+ };
17
+ use swc_css_parser::{
18
+ lexer::Lexer,
19
+ parse_input,
20
+ parser::{
21
+ input::{InputType, Tokens},
22
+ Parser, ParserConfig,
23
+ },
24
+ };
25
+ use swc_css_prefixer::prefixer;
26
+ use swc_css_visit::{VisitMut, VisitMutWith};
27
+ use swc_ecma_ast::*;
28
+ use swc_ecma_parser::StringInput;
29
+ use tracing::{debug, trace};
30
+
31
+ use crate::{
32
+ style::LocalStyle,
33
+ utils::{hash_string, string_literal_expr},
34
+ };
35
+
36
+ pub fn transform_css(
37
+ _cm: Arc<SourceMap>,
38
+ style_info: &LocalStyle,
39
+ is_global: bool,
40
+ class_name: &Option<String>,
41
+ ) -> Result<Expr, Error> {
42
+ debug!("CSS: \n{}", style_info.css);
43
+
44
+ // TODO use `parse_string_input` in future
45
+ let config = ParserConfig {
46
+ allow_wrong_line_comments: true,
47
+ css_modules: false,
48
+ ..Default::default()
49
+ };
50
+ let lexer = Lexer::new(
51
+ StringInput::new(
52
+ &style_info.css,
53
+ style_info.css_span.lo,
54
+ style_info.css_span.hi,
55
+ ),
56
+ config,
57
+ );
58
+ let mut parser = Parser::new(lexer, config);
59
+
60
+ let result: Result<Stylesheet, _> = parser.parse_all();
61
+ let mut ss = match result {
62
+ Ok(ss) => ss,
63
+ Err(err) => {
64
+ HANDLER.with(|handler| {
65
+ // Print css parsing errors
66
+ err.to_diagnostics(handler).emit();
67
+
68
+ // TODO(kdy1): We may print css so the user can see the error, and report it.
69
+
70
+ handler
71
+ .struct_span_err(
72
+ style_info.css_span,
73
+ "Failed to parse css in styled jsx component",
74
+ )
75
+ .note(&format!("Input to the css parser is {}", style_info.css))
76
+ .emit()
77
+ });
78
+ bail!("Failed to parse css");
79
+ }
80
+ };
81
+ // ? Do we need to support optionally prefixing?
82
+ ss.visit_mut_with(&mut prefixer(Default::default()));
83
+ ss.visit_mut_with(&mut Namespacer {
84
+ class_name: match class_name {
85
+ Some(s) => s.clone(),
86
+ None => format!("jsx-{}", &hash_string(&style_info.hash)),
87
+ },
88
+ is_global,
89
+ is_dynamic: style_info.is_dynamic,
90
+ });
91
+
92
+ let mut s = String::new();
93
+ {
94
+ let mut wr = BasicCssWriter::new(&mut s, None, BasicCssWriterConfig::default());
95
+ let mut gen = CodeGenerator::new(&mut wr, CodegenConfig { minify: true });
96
+
97
+ gen.emit(&ss).unwrap();
98
+ }
99
+
100
+ if style_info.expressions.is_empty() {
101
+ return Ok(string_literal_expr(&s));
102
+ }
103
+
104
+ let mut parts: Vec<&str> = s.split("__styled-jsx-placeholder-").collect();
105
+ let mut final_expressions = vec![];
106
+ for i in parts.iter_mut().skip(1) {
107
+ let (num_len, expression_index) = read_number(i);
108
+ final_expressions.push(style_info.expressions[expression_index].clone());
109
+ let substr = &i[(num_len + 2)..];
110
+ *i = substr;
111
+ }
112
+
113
+ Ok(Expr::Tpl(Tpl {
114
+ quasis: parts
115
+ .iter()
116
+ .map(|quasi| {
117
+ TplElement {
118
+ cooked: None, // ? Do we need cooked as well
119
+ raw: quasi.replace('`', "\\`").into(),
120
+ span: DUMMY_SP,
121
+ tail: false,
122
+ }
123
+ })
124
+ .collect(),
125
+ exprs: final_expressions,
126
+ span: DUMMY_SP,
127
+ }))
128
+ }
129
+
130
+ /// Returns `(length, value)`
131
+ fn read_number(s: &str) -> (usize, usize) {
132
+ for (idx, c) in s.char_indices() {
133
+ if c.is_ascii_digit() {
134
+ continue;
135
+ }
136
+
137
+ // For 10, we reach here after `0`.
138
+ let value = s[0..idx].parse().expect("failed to parse");
139
+
140
+ return (idx, value);
141
+ }
142
+
143
+ unreachable!("read_number(`{}`) is invalid because it is empty", s)
144
+ }
145
+
146
+ struct Namespacer {
147
+ class_name: String,
148
+ is_global: bool,
149
+ is_dynamic: bool,
150
+ }
151
+
152
+ impl VisitMut for Namespacer {
153
+ fn visit_mut_complex_selector(&mut self, node: &mut ComplexSelector) {
154
+ #[cfg(debug_assertions)]
155
+ let _tracing = {
156
+ // This will add information to the log messages, only for debug build.
157
+ // Note that we use cargo feature to remove all logging on production builds.
158
+
159
+ let mut code = String::new();
160
+ {
161
+ let mut wr = BasicCssWriter::new(&mut code, None, BasicCssWriterConfig::default());
162
+ let mut gen = CodeGenerator::new(&mut wr, CodegenConfig { minify: true });
163
+
164
+ gen.emit(&*node).unwrap();
165
+ }
166
+
167
+ tracing::span!(
168
+ tracing::Level::TRACE,
169
+ "Namespacer::visit_mut_complex_selector",
170
+ class_name = &*self.class_name,
171
+ is_global = self.is_global,
172
+ is_dynamic = self.is_dynamic,
173
+ input = &*code
174
+ )
175
+ .entered()
176
+ };
177
+
178
+ let mut new_selectors = vec![];
179
+ let mut combinator = None;
180
+
181
+ for sel in node.children.take() {
182
+ match &sel {
183
+ ComplexSelectorChildren::CompoundSelector(selector) => {
184
+ match self.get_transformed_selectors(combinator, selector.clone()) {
185
+ Ok(transformed_selectors) => new_selectors.extend(transformed_selectors),
186
+ Err(_) => {
187
+ HANDLER.with(|handler| {
188
+ handler
189
+ .struct_span_err(
190
+ selector.span,
191
+ "Failed to transform one off global selector",
192
+ )
193
+ .emit()
194
+ });
195
+ new_selectors.push(sel);
196
+ }
197
+ }
198
+
199
+ combinator = None;
200
+ }
201
+ ComplexSelectorChildren::Combinator(v) => {
202
+ combinator = Some(v.clone());
203
+ }
204
+ };
205
+ }
206
+
207
+ node.children = new_selectors;
208
+ }
209
+ }
210
+
211
+ impl Namespacer {
212
+ fn get_transformed_selectors(
213
+ &mut self,
214
+ combinator: Option<Combinator>,
215
+ mut node: CompoundSelector,
216
+ ) -> Result<Vec<ComplexSelectorChildren>, Error> {
217
+ let mut pseudo_index = None;
218
+
219
+ for (i, selector) in node.subclass_selectors.iter().enumerate() {
220
+ let (name, children) = match &selector {
221
+ SubclassSelector::PseudoClass(PseudoClassSelector {
222
+ name,
223
+ children: Some(children),
224
+ ..
225
+ }) if &name.value == "global" => (name, children),
226
+ SubclassSelector::PseudoClass(_) | SubclassSelector::PseudoElement(_) => {
227
+ if pseudo_index.is_none() {
228
+ pseudo_index = Some(i);
229
+ }
230
+
231
+ continue;
232
+ }
233
+ _ => continue,
234
+ };
235
+
236
+ // One off global selector
237
+ if &name.value == "global" {
238
+ // TODO(alexander-akait): in future we should use list of component values
239
+ let tokens = children
240
+ .iter()
241
+ .map(|v| match v {
242
+ PseudoClassSelectorChildren::PreservedToken(v) => v.clone(),
243
+ _ => {
244
+ unreachable!();
245
+ }
246
+ })
247
+ .collect::<Vec<TokenAndSpan>>();
248
+ let mut tokens = {
249
+ let lo = tokens.first().map(|v| v.span_lo()).unwrap_or(BytePos(0));
250
+ let hi = tokens.last().map(|v| v.span_hi()).unwrap_or(BytePos(0));
251
+
252
+ Tokens {
253
+ span: Span::new(lo, hi, Default::default()),
254
+ tokens,
255
+ }
256
+ };
257
+
258
+ // Because it is allowed to write `.bar :global(> .foo) {}` or .bar
259
+ // :global(.foo) {}`, so selector can be complex or relative (it violates the
260
+ // specification), but it is popular usage, so we just add `a >` at top and then
261
+ // remove it
262
+ let mut front_tokens = get_front_selector_tokens(&tokens);
263
+
264
+ front_tokens.extend(tokens.tokens);
265
+
266
+ tokens.tokens = front_tokens;
267
+
268
+ let complex_selectors = panic::catch_unwind(|| {
269
+ let x: ComplexSelector = parse_input(
270
+ InputType::Tokens(&tokens),
271
+ ParserConfig {
272
+ allow_wrong_line_comments: true,
273
+ css_modules: true,
274
+ ..Default::default()
275
+ },
276
+ // TODO(kdy1): We might be able to report syntax errors.
277
+ &mut vec![],
278
+ )
279
+ .unwrap();
280
+ x
281
+ });
282
+
283
+ return match complex_selectors {
284
+ Ok(complex_selectors) => {
285
+ let mut v = complex_selectors.children[1..].to_vec();
286
+
287
+ if let ComplexSelectorChildren::Combinator(Combinator {
288
+ value: CombinatorValue::Descendant,
289
+ ..
290
+ }) = v[0]
291
+ {
292
+ v.remove(0);
293
+ }
294
+
295
+ if v.is_empty() {
296
+ bail!("Failed to transform one off global selector");
297
+ }
298
+
299
+ trace!("Combinator: {:?}", combinator);
300
+ trace!("v[0]: {:?}", v[0]);
301
+
302
+ let mut result = vec![];
303
+
304
+ if let Some(combinator) = combinator {
305
+ match v.get(0) {
306
+ // `Descendant` combinator can't be the first because we removed it
307
+ // above
308
+ Some(ComplexSelectorChildren::Combinator(..))
309
+ if combinator.value == CombinatorValue::Descendant => {}
310
+ _ => {
311
+ result.push(ComplexSelectorChildren::Combinator(combinator));
312
+ }
313
+ }
314
+ }
315
+
316
+ v.iter_mut().for_each(|sel| {
317
+ if i < node.subclass_selectors.len() {
318
+ if let ComplexSelectorChildren::CompoundSelector(sel) = sel {
319
+ sel.subclass_selectors
320
+ .extend(node.subclass_selectors[i + 1..].iter().cloned());
321
+ }
322
+ }
323
+ });
324
+
325
+ result.extend(v);
326
+
327
+ Ok(result)
328
+ }
329
+ Err(_) => bail!("Failed to transform one off global selector"),
330
+ };
331
+ }
332
+ }
333
+
334
+ let subclass_selector = match self.is_dynamic {
335
+ true => "__jsx-style-dynamic-selector",
336
+ false => &self.class_name,
337
+ };
338
+ let insert_index = match pseudo_index {
339
+ None => node.subclass_selectors.len(),
340
+ Some(i) => i,
341
+ };
342
+
343
+ if !self.is_global {
344
+ node.subclass_selectors.insert(
345
+ insert_index,
346
+ SubclassSelector::Class(ClassSelector {
347
+ span: DUMMY_SP,
348
+ text: Ident {
349
+ raw: Some(subclass_selector.into()),
350
+ value: subclass_selector.into(),
351
+ span: DUMMY_SP,
352
+ },
353
+ }),
354
+ );
355
+ }
356
+
357
+ let mut result = vec![];
358
+
359
+ if let Some(combinator) = combinator {
360
+ result.push(ComplexSelectorChildren::Combinator(combinator));
361
+ }
362
+
363
+ result.push(ComplexSelectorChildren::CompoundSelector(node));
364
+
365
+ Ok(result)
366
+ }
367
+ }
368
+
369
+ fn get_front_selector_tokens(selector_tokens: &Tokens) -> Vec<TokenAndSpan> {
370
+ let start_pos = selector_tokens.span.lo.to_u32() - 2;
371
+ vec![
372
+ TokenAndSpan {
373
+ span: Span {
374
+ lo: BytePos(start_pos),
375
+ hi: BytePos(start_pos + 1),
376
+ ctxt: SyntaxContext::empty(),
377
+ },
378
+ token: Token::Ident {
379
+ raw: "a".into(),
380
+ value: "a".into(),
381
+ },
382
+ },
383
+ TokenAndSpan {
384
+ span: Span {
385
+ lo: BytePos(start_pos + 1),
386
+ hi: BytePos(start_pos + 2),
387
+ ctxt: SyntaxContext::empty(),
388
+ },
389
+ token: Token::WhiteSpace { value: " ".into() },
390
+ },
391
+ ]
392
+ }
@@ -1,6 +1,7 @@
1
1
  use std::{collections::hash_map::DefaultHasher, hash::Hasher};
2
2
 
3
- use swc_core::{common::DUMMY_SP, ecma::ast::*};
3
+ use swc_common::DUMMY_SP;
4
+ use swc_ecma_ast::*;
4
5
 
5
6
  use crate::style::{ExternalStyle, JSXStyle, LocalStyle};
6
7
 
@@ -6,31 +6,33 @@ use std::{
6
6
  };
7
7
 
8
8
  use easy_error::{bail, Error};
9
- use swc_core::{
10
- common::{collections::AHashSet, errors::HANDLER, FileName, SourceMap, Span, DUMMY_SP},
11
- ecma::{
12
- ast::*,
13
- minifier::{
14
- eval::{EvalResult, Evaluator},
15
- marks::Marks,
16
- },
17
- utils::{collect_decls, drop_span, prepend_stmt, private_ident},
18
- visit::{Fold, FoldWith},
19
- },
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,
20
15
  };
16
+ use swc_ecma_utils::{collect_decls, drop_span, prepend_stmt, private_ident};
17
+ use swc_ecma_visit::{Fold, FoldWith};
21
18
 
22
19
  use crate::{
23
20
  style::{ExternalStyle, JSXStyle, LocalStyle},
24
- transform_css::transform_css,
25
21
  utils::{
26
22
  add, and, compute_class_names, get_usable_import_specifier, hash_string, ident,
27
23
  is_capitalized, make_external_styled_jsx_el, make_local_styled_jsx_el, not_eq, or,
28
24
  string_literal_expr, styled_jsx_import_decl,
29
25
  },
30
26
  };
31
- //use external::external_styles;
32
27
 
33
- pub fn styled_jsx(cm: Arc<SourceMap>, file_name: FileName) -> impl Fold {
28
+ #[derive(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 {
34
36
  let file_name = match file_name {
35
37
  FileName::Real(real_file_name) => real_file_name
36
38
  .to_str()
@@ -40,6 +42,7 @@ pub fn styled_jsx(cm: Arc<SourceMap>, file_name: FileName) -> impl Fold {
40
42
 
41
43
  StyledJSXTransformer {
42
44
  cm,
45
+ config,
43
46
  file_name,
44
47
  styles: Default::default(),
45
48
  static_class_name: Default::default(),
@@ -63,6 +66,8 @@ pub fn styled_jsx(cm: Arc<SourceMap>, file_name: FileName) -> impl Fold {
63
66
 
64
67
  struct StyledJSXTransformer {
65
68
  cm: Arc<SourceMap>,
69
+ config: Config,
70
+
66
71
  file_name: Option<String>,
67
72
  styles: Vec<JSXStyle>,
68
73
  static_class_name: Option<String>,
@@ -564,12 +569,22 @@ impl StyledJSXTransformer {
564
569
 
565
570
  match &style_info {
566
571
  JSXStyle::Local(style_info) => {
567
- let css = transform_css(
568
- self.cm.clone(),
569
- style_info,
570
- is_global,
571
- &self.static_class_name,
572
- )?;
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
+
573
588
  Ok(make_local_styled_jsx_el(
574
589
  style_info,
575
590
  css,
@@ -618,7 +633,21 @@ impl StyledJSXTransformer {
618
633
  } else {
619
634
  bail!("This shouldn't happen, we already know that this is a template literal");
620
635
  };
621
- let css = transform_css(self.cm.clone(), style, tag == "global", &static_class_name)?;
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
+ };
622
651
  if tag == "resolve" {
623
652
  self.file_has_css_resolve = true;
624
653
  return Ok(Expr::Object(ObjectLit {