@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.
- package/Cargo.toml +12 -11
- package/package.json +1 -1
- package/src/lib.rs +10 -3
- package/swc_plugin_styled_jsx.wasm +0 -0
- package/transform/Cargo.toml +19 -12
- package/transform/src/lib.rs +2 -1
- package/transform/src/style.rs +2 -1
- package/transform/src/{transform_css.rs → transform_css_lightningcss.rs} +5 -5
- package/transform/src/transform_css_swc.rs +392 -0
- package/transform/src/utils.rs +2 -1
- package/transform/src/visitor.rs +50 -21
- package/transform/tests/errors/nested-style-tags/output.js +31 -4
- package/transform/tests/errors/ts-with-css-resolve/output.js +1 -1
- package/transform/tests/fixture/absent/output.swc.js +7 -0
- package/transform/tests/fixture/attribute-generation-classname-rewriting/output.swc.js +112 -0
- package/transform/tests/fixture/attribute-generation-modes/output.swc.js +228 -0
- package/transform/tests/fixture/class/output.swc.js +12 -0
- package/transform/tests/fixture/comments/output.swc.js +12 -0
- package/transform/tests/fixture/component-attribute/output.swc.js +10 -0
- package/transform/tests/fixture/conflicts/output.swc.js +14 -0
- package/transform/tests/fixture/css-selector-after-pseudo/output.swc.js +11 -0
- package/transform/tests/fixture/css-tag-same-file/output.swc.js +21 -0
- package/transform/tests/fixture/different-jsx-ids/output.swc.js +24 -0
- package/transform/tests/fixture/dynamic-element/output.swc.js +40 -0
- package/transform/tests/fixture/dynamic-element-class/output.swc.js +25 -0
- package/transform/tests/fixture/dynamic-element-external/output.swc.js +12 -0
- package/transform/tests/fixture/dynamic-this-in-arrow/output.swc.js +39 -0
- package/transform/tests/fixture/exported-jsx-style/output.swc.js +1 -0
- package/transform/tests/fixture/exported-non-jsx-style/output.swc.js +1 -0
- package/transform/tests/fixture/external-nested-scope/output.swc.js +7 -0
- package/transform/tests/fixture/external-stylesheet/output.swc.js +34 -0
- package/transform/tests/fixture/external-stylesheet-global/output.swc.js +18 -0
- package/transform/tests/fixture/external-stylesheet-multi-line/output.swc.js +9 -0
- package/transform/tests/fixture/fragment/output.swc.js +47 -0
- package/transform/tests/fixture/global/output.swc.js +7 -0
- package/transform/tests/fixture/global-child-selector/output.swc.js +8 -0
- package/transform/tests/fixture/global-redundant/output.swc.js +10 -0
- package/transform/tests/fixture/issue-30480/output.swc.js +15 -0
- package/transform/tests/fixture/issue-30570/output.swc.js +12 -0
- package/transform/tests/fixture/issue-31562-interpolation-in-mdea/output.swc.js +43 -0
- package/transform/tests/fixture/mixed-global-scoped/output.swc.js +11 -0
- package/transform/tests/fixture/multiple-jsx/output.swc.js +32 -0
- package/transform/tests/fixture/next-54653/output.swc.js +3 -0
- package/transform/tests/fixture/non-styled-jsx-style/output.swc.js +12 -0
- package/transform/tests/fixture/not-styled-jsx-tagged-templates/{output.js → output.lightningcss.js} +1 -2
- package/transform/tests/fixture/not-styled-jsx-tagged-templates/output.swc.js +23 -0
- package/transform/tests/fixture/number-after-placeholder/output.swc.js +17 -0
- package/transform/tests/fixture/one-off-global-selectors/output.swc.js +8 -0
- package/transform/tests/fixture/source-maps/output.swc.js +8 -0
- package/transform/tests/fixture/styles/output.swc.js +39 -0
- package/transform/tests/fixture/styles-external-invalid/output.swc.js +9 -0
- package/transform/tests/fixture/styles-external-invalid2/output.swc.js +8 -0
- package/transform/tests/fixture/styles2/output.swc.js +5 -0
- package/transform/tests/fixture/too-many/output.swc.js +49 -0
- package/transform/tests/fixture/tpl-escape-1/output.swc.js +12 -0
- package/transform/tests/fixture/tpl-escape-2/output.swc.js +17 -0
- package/transform/tests/fixture/tpl-placeholder-1-as-property/output.swc.js +28 -0
- package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/output.swc.js +34 -0
- package/transform/tests/fixture/tpl-placeholder-3-as-value/output.swc.js +28 -0
- package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/output.swc.js +31 -0
- package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/output.swc.js +31 -0
- package/transform/tests/fixture/transform-css/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-complex-selector/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-complex-selector-2/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-global/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-media-query/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-normal/output.swc.js +8 -0
- package/transform/tests/fixture/transform-css-nth-1/output.swc.js +8 -0
- package/transform/tests/fixture/whitespace/output.lightningcss.js +12 -0
- package/transform/tests/fixture/whitespace/output.swc.js +12 -0
- package/transform/tests/fixture.rs +60 -49
- package/transform/tests/fixture/.expressions/output.js +0 -91
- package/transform/tests/fixture/nested-style-tags/output.js +0 -0
- /package/transform/tests/fixture/absent/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/attribute-generation-classname-rewriting/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/attribute-generation-modes/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/class/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/comments/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/component-attribute/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/conflicts/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/css-selector-after-pseudo/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/css-tag-same-file/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/different-jsx-ids/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/dynamic-element/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/dynamic-element-class/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/dynamic-element-external/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/dynamic-this-in-arrow/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/exported-jsx-style/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/exported-non-jsx-style/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/external-nested-scope/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/external-stylesheet/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/external-stylesheet-global/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/external-stylesheet-multi-line/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/fragment/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/global/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/global-child-selector/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/global-redundant/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/issue-30480/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/issue-30570/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/issue-31562-interpolation-in-mdea/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/mixed-global-scoped/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/multiple-jsx/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/next-54653/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/non-styled-jsx-style/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/number-after-placeholder/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/one-off-global-selectors/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/source-maps/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/stateless/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/{whitespace/output.js → stateless/output.swc.js} +0 -0
- /package/transform/tests/fixture/styles/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/styles-external-invalid/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/styles-external-invalid2/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/styles2/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/too-many/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-escape-1/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-escape-2/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-placeholder-1-as-property/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-placeholder-2-as-part-of-value/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-placeholder-3-as-value/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-placeholder-4-as-part-of-value-in-multiple/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/tpl-placeholder-5-values-of-multiple-properties/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css-complex-selector/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css-complex-selector-2/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css-global/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css-media-query/{output.js → output.lightningcss.js} +0 -0
- /package/transform/tests/fixture/transform-css-normal/{output.js → output.lightningcss.js} +0 -0
- /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 = ["
|
|
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
|
-
|
|
32
|
+
swc_ecma_transforms_testing = "0.136.2"
|
|
32
33
|
testing = "0.34.1"
|
package/package.json
CHANGED
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,
|
|
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
|
package/transform/Cargo.toml
CHANGED
|
@@ -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.
|
|
7
|
+
version = "0.45.0"
|
|
8
8
|
|
|
9
9
|
[features]
|
|
10
|
-
custom_transform = ["
|
|
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.
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
38
|
+
swc_ecma_transforms_testing = "0.136.1"
|
|
39
|
+
swc_ecma_transforms = "0.224.4"
|
package/transform/src/lib.rs
CHANGED
package/transform/src/style.rs
CHANGED
|
@@ -18,10 +18,8 @@ use lightningcss::{
|
|
|
18
18
|
visitor::{Visit, VisitTypes, Visitor},
|
|
19
19
|
};
|
|
20
20
|
use parcel_selectors::{parser::SelectorIter, SelectorImpl};
|
|
21
|
-
use
|
|
22
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/transform/src/utils.rs
CHANGED
package/transform/src/visitor.rs
CHANGED
|
@@ -6,31 +6,33 @@ use std::{
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
use easy_error::{bail, Error};
|
|
9
|
-
use
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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 =
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
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 =
|
|
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 {
|