@tarojs/helper 4.0.0-beta.0 → 4.0.0-canary.1
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/dist/esbuild/index.js +2 -2
- package/dist/esbuild/index.js.map +1 -1
- package/dist/utils.js +3 -6
- package/dist/utils.js.map +1 -1
- package/package.json +4 -3
- package/swc/.gitkeep +0 -0
- package/swc/swc_plugin_compile_mode.wasm +0 -0
- package/swc/swc_plugin_define_config.wasm +0 -0
- package/swc/plugin-compile-mode/.cargo/config +0 -5
- package/swc/plugin-compile-mode/.editorconfig +0 -6
- package/swc/plugin-compile-mode/.vscode/settings.json +0 -3
- package/swc/plugin-compile-mode/Cargo.lock +0 -2021
- package/swc/plugin-compile-mode/Cargo.toml +0 -22
- package/swc/plugin-compile-mode/package.json +0 -15
- package/swc/plugin-compile-mode/src/lib.rs +0 -71
- package/swc/plugin-compile-mode/src/tests/attributes.rs +0 -54
- package/swc/plugin-compile-mode/src/tests/children.rs +0 -86
- package/swc/plugin-compile-mode/src/tests/condition.rs +0 -50
- package/swc/plugin-compile-mode/src/tests/entry.rs +0 -20
- package/swc/plugin-compile-mode/src/tests/harmony/attributes.rs +0 -45
- package/swc/plugin-compile-mode/src/tests/harmony/children.rs +0 -74
- package/swc/plugin-compile-mode/src/tests/harmony/condition.rs +0 -79
- package/swc/plugin-compile-mode/src/tests/harmony/entry.rs +0 -67
- package/swc/plugin-compile-mode/src/tests/harmony/looping.rs +0 -62
- package/swc/plugin-compile-mode/src/tests/harmony/mod.rs +0 -45
- package/swc/plugin-compile-mode/src/tests/looping.rs +0 -84
- package/swc/plugin-compile-mode/src/tests/mod.rs +0 -100
- package/swc/plugin-compile-mode/src/tests/shake.rs +0 -27
- package/swc/plugin-compile-mode/src/transform.rs +0 -474
- package/swc/plugin-compile-mode/src/transform_harmony.rs +0 -526
- package/swc/plugin-compile-mode/src/utils/constants.rs +0 -152
- package/swc/plugin-compile-mode/src/utils/harmony/components.rs +0 -61
- package/swc/plugin-compile-mode/src/utils/harmony/mod.rs +0 -1
- package/swc/plugin-compile-mode/src/utils/mod.rs +0 -347
- package/swc/plugin-compile-mode/target/wasm32-wasi/release/swc_plugin_compile_mode.wasm +0 -0
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/attributes.rs/should_handle_events.js +0 -8
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/attributes.rs/should_keep_static_attrs_only_in_templates.js +0 -8
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/attributes.rs/should_turn_dynamic_attrs.js +0 -11
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/children.rs/should_render_native_component.js +0 -7
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/children.rs/should_render_react_component.js +0 -7
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/children.rs/should_support_fragment.js +0 -44
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/children.rs/should_support_render_fn.js +0 -8
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/condition.rs/should_support_and_expr.js +0 -14
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/condition.rs/should_support_conditional_expr.js +0 -15
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/entry.rs/should_support_multi_compile_mode.js +0 -10
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/attributes.rs/should_handle_events.js +0 -183
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/attributes.rs/should_turn_dynamic_attrs.js +0 -186
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/children.rs/should_render_react_component.js +0 -76
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/children.rs/should_support_fragment.js +0 -341
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/children.rs/should_support_render_fn.js +0 -186
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/condition.rs/should_support_and_expr.js +0 -211
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/condition.rs/should_support_complex_condition.js +0 -244
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/condition.rs/should_support_conditional_and_unkonw_component.js +0 -139
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/condition.rs/should_support_conditional_expr.js +0 -344
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/entry.rs/should_support_compile_child_node.js +0 -141
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/entry.rs/should_support_component_not_in_config.js +0 -91
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/entry.rs/should_support_multi_compile_mode.js +0 -209
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/entry.rs/should_support_single_compile_mode.js +0 -66
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/looping.rs/should_loop_with_arrow_function_with_blockstmt.js +0 -76
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/looping.rs/should_loop_with_arrow_function_with_blockstmt_and_set_parent_dynamic_id.js +0 -89
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/harmony/looping.rs/should_loop_with_function_expr.js +0 -86
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/looping.rs/should_loop_with_arrow_function_with_blockstmt.js +0 -8
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/looping.rs/should_loop_with_arrow_function_with_expr.js +0 -6
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/looping.rs/should_loop_with_function_expr.js +0 -20
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/looping.rs/should_support_nested_loop.js +0 -15
- package/swc/plugin-compile-mode/tests/__swc_snapshots__/src/tests/shake.rs/should_static_jsx_being_shaked.js +0 -20
- package/swc/plugin-define-config/.cargo/config +0 -5
- package/swc/plugin-define-config/Cargo.lock +0 -2110
- package/swc/plugin-define-config/Cargo.toml +0 -18
- package/swc/plugin-define-config/src/lib.rs +0 -141
- package/swc/plugin-define-config/target/wasm32-wasi/release/swc_plugin_define_config.wasm +0 -0
- package/swc/plugin-define-config/tests/__swc_snapshots__/src/lib.rs/module_decl_default_app.js +0 -2
- package/swc/plugin-define-config/tests/__swc_snapshots__/src/lib.rs/module_decl_default_page.js +0 -2
- package/swc/plugin-define-config/tests/__swc_snapshots__/src/lib.rs/module_exports.js +0 -11
- package/swc/plugin-define-config/tests/__swc_snapshots__/src/lib.rs/var_decl_app.js +0 -3
- package/swc/plugin-define-config/tests/__swc_snapshots__/src/lib.rs/var_decl_page.js +0 -3
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
use swc_core::ecma::transforms::testing::test;
|
|
2
|
-
use super::{tr, get_syntax_config};
|
|
3
|
-
|
|
4
|
-
test!(
|
|
5
|
-
get_syntax_config(),
|
|
6
|
-
|_| tr(),
|
|
7
|
-
should_loop_with_function_expr,
|
|
8
|
-
r#"
|
|
9
|
-
function Index () {
|
|
10
|
-
return (
|
|
11
|
-
<View compileMode>
|
|
12
|
-
{list.map(function(item, index) {
|
|
13
|
-
return (
|
|
14
|
-
<View hoverClass={myClass}>
|
|
15
|
-
<Text>index:</Text>
|
|
16
|
-
<Text>{index}</Text>
|
|
17
|
-
<Text>item:</Text>
|
|
18
|
-
<Text>{item}</Text>
|
|
19
|
-
</View>
|
|
20
|
-
)
|
|
21
|
-
})}
|
|
22
|
-
</View>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
"#
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
test!(
|
|
29
|
-
get_syntax_config(),
|
|
30
|
-
|_| tr(),
|
|
31
|
-
should_loop_with_arrow_function_with_blockstmt,
|
|
32
|
-
r#"
|
|
33
|
-
function Index () {
|
|
34
|
-
return (
|
|
35
|
-
<View compileMode>
|
|
36
|
-
{list.map(item => {
|
|
37
|
-
return <View>{item}</View>
|
|
38
|
-
})}
|
|
39
|
-
</View>
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
"#
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
test!(
|
|
46
|
-
get_syntax_config(),
|
|
47
|
-
|_| tr(),
|
|
48
|
-
should_loop_with_arrow_function_with_expr,
|
|
49
|
-
r#"
|
|
50
|
-
function Index () {
|
|
51
|
-
return (
|
|
52
|
-
<View compileMode>
|
|
53
|
-
{list.map(item => <View>{item}</View>)}
|
|
54
|
-
</View>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
"#
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
test!(
|
|
61
|
-
get_syntax_config(),
|
|
62
|
-
|_| tr(),
|
|
63
|
-
should_support_nested_loop,
|
|
64
|
-
r#"
|
|
65
|
-
function Index () {
|
|
66
|
-
return (
|
|
67
|
-
<View compileMode>
|
|
68
|
-
{list.map(function(item, index) {
|
|
69
|
-
return (
|
|
70
|
-
<View hoverClass={myClass} key={index}>
|
|
71
|
-
<View>title: {item}</View>
|
|
72
|
-
<View>
|
|
73
|
-
{sublist.map(function(c) {
|
|
74
|
-
return <Text selectable={isSelectable}>content: {c}</Text>
|
|
75
|
-
})}
|
|
76
|
-
</View>
|
|
77
|
-
</View>
|
|
78
|
-
)
|
|
79
|
-
})}
|
|
80
|
-
</View>
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
"#
|
|
84
|
-
);
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
use swc_core::ecma::{
|
|
2
|
-
parser,
|
|
3
|
-
visit::{as_folder, Fold},
|
|
4
|
-
};
|
|
5
|
-
use crate::{
|
|
6
|
-
PluginConfig,
|
|
7
|
-
transform::*,
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
mod entry;
|
|
11
|
-
mod attributes;
|
|
12
|
-
mod shake;
|
|
13
|
-
mod condition;
|
|
14
|
-
mod looping;
|
|
15
|
-
mod children;
|
|
16
|
-
mod harmony;
|
|
17
|
-
|
|
18
|
-
pub fn tr () -> impl Fold {
|
|
19
|
-
let config = serde_json::from_str::<PluginConfig>(
|
|
20
|
-
r#"
|
|
21
|
-
{
|
|
22
|
-
"tmpl_prefix": "f0",
|
|
23
|
-
"components": {
|
|
24
|
-
"block": {},
|
|
25
|
-
"image": {
|
|
26
|
-
"src": "i.p3",
|
|
27
|
-
"mode": "xs.b(i.p1,'scaleToFill')",
|
|
28
|
-
"lazy-load": "xs.b(i.p0,!1)",
|
|
29
|
-
"binderror": "eh",
|
|
30
|
-
"bindload": "eh",
|
|
31
|
-
"bindtouchstart": "eh",
|
|
32
|
-
"bindtouchmove": "eh",
|
|
33
|
-
"bindtouchend": "eh",
|
|
34
|
-
"bindtouchcancel": "eh",
|
|
35
|
-
"bindlongpress": "eh",
|
|
36
|
-
"webp": "xs.b(i.p4,false)",
|
|
37
|
-
"show-menu-by-longpress": "xs.b(i.p2,false)",
|
|
38
|
-
"style": "i.st",
|
|
39
|
-
"class": "i.cl",
|
|
40
|
-
"bindtap": "eh"
|
|
41
|
-
},
|
|
42
|
-
"view": {
|
|
43
|
-
"hover-class": "xs.b(i.p1,'none')",
|
|
44
|
-
"hover-stop-propagation": "xs.b(i.p4,!1)",
|
|
45
|
-
"hover-start-time": "xs.b(i.p2,50)",
|
|
46
|
-
"hover-stay-time": "xs.b(i.p3,400)",
|
|
47
|
-
"bindtouchstart": "eh",
|
|
48
|
-
"bindtouchmove": "eh",
|
|
49
|
-
"bindtouchend": "eh",
|
|
50
|
-
"bindtouchcancel": "eh",
|
|
51
|
-
"bindlongpress": "eh",
|
|
52
|
-
"animation": "i.p0",
|
|
53
|
-
"bindanimationstart": "eh",
|
|
54
|
-
"bindanimationiteration": "eh",
|
|
55
|
-
"bindanimationend": "eh",
|
|
56
|
-
"bindtransitionend": "eh",
|
|
57
|
-
"style": "i.st",
|
|
58
|
-
"class": "i.cl",
|
|
59
|
-
"bindtap": "eh"
|
|
60
|
-
},
|
|
61
|
-
"text": {
|
|
62
|
-
"selectable": "xs.b(i.p1,!1)",
|
|
63
|
-
"space": "i.p2",
|
|
64
|
-
"decode": "xs.b(i.p0,!1)",
|
|
65
|
-
"user-select": "xs.b(i.p3,false)",
|
|
66
|
-
"style": "i.st",
|
|
67
|
-
"class": "i.cl",
|
|
68
|
-
"bindtap": "eh"
|
|
69
|
-
},
|
|
70
|
-
"movable-area": {
|
|
71
|
-
"scale-area": "xs.b(i.p0,!1)",
|
|
72
|
-
"style": "i.st",
|
|
73
|
-
"class": "i.cl",
|
|
74
|
-
"bindtap": "eh"
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
"adapter": {
|
|
78
|
-
"if": "wx:if",
|
|
79
|
-
"else": "wx:else",
|
|
80
|
-
"elseif": "wx:elif",
|
|
81
|
-
"for": "wx:for",
|
|
82
|
-
"forItem": "wx:for-item",
|
|
83
|
-
"forIndex": "wx:for-index",
|
|
84
|
-
"key": "wx:key",
|
|
85
|
-
"xs": "wxs",
|
|
86
|
-
"type": "weapp"
|
|
87
|
-
}
|
|
88
|
-
}"#
|
|
89
|
-
)
|
|
90
|
-
.unwrap();
|
|
91
|
-
let visitor = TransformVisitor::new(config);
|
|
92
|
-
as_folder(visitor)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
pub fn get_syntax_config () -> parser::Syntax {
|
|
96
|
-
parser::Syntax::Es(parser::EsConfig {
|
|
97
|
-
jsx: true,
|
|
98
|
-
..Default::default()
|
|
99
|
-
})
|
|
100
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
use swc_core::ecma::transforms::testing::test;
|
|
2
|
-
use super::{tr, get_syntax_config};
|
|
3
|
-
|
|
4
|
-
test!(
|
|
5
|
-
get_syntax_config(),
|
|
6
|
-
|_| tr(),
|
|
7
|
-
should_static_jsx_being_shaked,
|
|
8
|
-
r#"
|
|
9
|
-
function Index () {
|
|
10
|
-
return (
|
|
11
|
-
<View compileMode>
|
|
12
|
-
<Text>Hello World!</Text>
|
|
13
|
-
<Text>Hello{T1}World{T2}!</Text>
|
|
14
|
-
<View>
|
|
15
|
-
<Text></Text>
|
|
16
|
-
</View>
|
|
17
|
-
<View style="color: red" hoverStopPropagation>
|
|
18
|
-
<Text>Hello World!</Text>
|
|
19
|
-
</View>
|
|
20
|
-
<View style={myStyle}>
|
|
21
|
-
<Text>Hello World!</Text>
|
|
22
|
-
</View>
|
|
23
|
-
</View>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
"#
|
|
27
|
-
);
|
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
use swc_core::{
|
|
3
|
-
common::{
|
|
4
|
-
iter::IdentifyLast,
|
|
5
|
-
util::take::Take,
|
|
6
|
-
DUMMY_SP as span,
|
|
7
|
-
},
|
|
8
|
-
ecma::{
|
|
9
|
-
self,
|
|
10
|
-
ast::*,
|
|
11
|
-
visit::{VisitMut, VisitMutWith},
|
|
12
|
-
utils::{quote_ident, quote_str},
|
|
13
|
-
},
|
|
14
|
-
atoms::Atom,
|
|
15
|
-
};
|
|
16
|
-
use std::collections::HashMap;
|
|
17
|
-
use crate::PluginConfig;
|
|
18
|
-
use crate::utils::{self, constants::*};
|
|
19
|
-
|
|
20
|
-
struct PreVisitor {
|
|
21
|
-
is_in_and_expr: bool,
|
|
22
|
-
}
|
|
23
|
-
impl PreVisitor {
|
|
24
|
-
fn new () -> Self {
|
|
25
|
-
Self {
|
|
26
|
-
is_in_and_expr: false
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
impl VisitMut for PreVisitor {
|
|
31
|
-
fn visit_mut_jsx_element_child (&mut self, child: &mut JSXElementChild) {
|
|
32
|
-
if let JSXElementChild::JSXExprContainer(JSXExprContainer { expr: JSXExpr::Expr(expr), .. }) = child {
|
|
33
|
-
let mut is_first_and_expr = false;
|
|
34
|
-
|
|
35
|
-
if let Expr::Paren(ParenExpr { expr: e, .. }) = &mut **expr {
|
|
36
|
-
*expr = e.take();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
match &mut **expr {
|
|
40
|
-
Expr::Bin(BinExpr { op, left, right, ..}) => {
|
|
41
|
-
// C&&A 替换为 C?A:A',原因是为了无论显示还是隐藏都保留一个元素,从而不影响兄弟节点的变量路径
|
|
42
|
-
if *op == op!("&&") && !self.is_in_and_expr {
|
|
43
|
-
is_first_and_expr = true;
|
|
44
|
-
fn inject_compile_if (el: &mut Box<JSXElement>, condition: &mut Box<Expr>) -> () {
|
|
45
|
-
el.opening.attrs.push(utils::create_jsx_expr_attr(COMPILE_IF, condition.clone()));
|
|
46
|
-
}
|
|
47
|
-
fn get_element_double (element_name: JSXElementName, condition: &mut Box<Expr>, right: &mut Box<Expr>) -> Expr {
|
|
48
|
-
Expr::Cond(CondExpr {
|
|
49
|
-
span,
|
|
50
|
-
test: condition.take(),
|
|
51
|
-
cons: right.take(),
|
|
52
|
-
alt: Box::new(utils::create_self_closing_jsx_element_expr(
|
|
53
|
-
element_name, // element 替换为同类型的元素。在显示/隐藏切换时,让运行时 diff 只更新必要属性而不是整个节点刷新
|
|
54
|
-
Some(vec![utils::create_jsx_bool_attr(COMPILE_IGNORE)]
|
|
55
|
-
)))
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
match &mut **right {
|
|
59
|
-
Expr::JSXElement(el) => {
|
|
60
|
-
let element_name = el.opening.name.clone();
|
|
61
|
-
inject_compile_if(el, left);
|
|
62
|
-
**expr = get_element_double(element_name, left, right);
|
|
63
|
-
},
|
|
64
|
-
Expr::Paren(ParenExpr { expr: paren_expr, .. }) => {
|
|
65
|
-
if paren_expr.is_jsx_element() {
|
|
66
|
-
let el: &mut Box<JSXElement> = paren_expr.as_mut_jsx_element().unwrap();
|
|
67
|
-
let element_name = el.opening.name.clone();
|
|
68
|
-
inject_compile_if(el, left);
|
|
69
|
-
**expr = get_element_double(element_name, left, paren_expr);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
Expr::Lit(_) => {
|
|
73
|
-
**expr = Expr::Cond(CondExpr {
|
|
74
|
-
span,
|
|
75
|
-
test: left.take(),
|
|
76
|
-
cons: right.take(),
|
|
77
|
-
alt: Box::new(Expr::Lit(Lit::Str(quote_str!(COMPILE_IGNORE))))
|
|
78
|
-
})
|
|
79
|
-
},
|
|
80
|
-
_ => {
|
|
81
|
-
let jsx_el_name = JSXElementName::Ident(quote_ident!("block"));
|
|
82
|
-
let mut block = Box::new(JSXElement {
|
|
83
|
-
span,
|
|
84
|
-
opening: JSXOpeningElement { name: jsx_el_name.clone(), span, attrs: vec![], self_closing: false, type_args: None },
|
|
85
|
-
children: vec![JSXElementChild::JSXExprContainer(JSXExprContainer { span, expr: JSXExpr::Expr(right.take()) })],
|
|
86
|
-
closing: Some(JSXClosingElement { span, name: jsx_el_name.clone() })
|
|
87
|
-
});
|
|
88
|
-
inject_compile_if(&mut block, left);
|
|
89
|
-
**expr = get_element_double(jsx_el_name, left, &mut Box::new(Expr::JSXElement(block)));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
Expr::Cond(CondExpr { test, cons, alt, ..}) => {
|
|
95
|
-
let compile_if = utils::create_jsx_expr_attr(COMPILE_IF, test.clone());
|
|
96
|
-
let compile_else = utils::create_jsx_bool_attr(COMPILE_ELSE);
|
|
97
|
-
let process_cond_arm = |arm: &mut Box<Expr>, attr: JSXAttrOrSpread| {
|
|
98
|
-
match &mut **arm {
|
|
99
|
-
Expr::JSXElement(el) => {
|
|
100
|
-
el.opening.attrs.push(attr);
|
|
101
|
-
},
|
|
102
|
-
_ => {
|
|
103
|
-
let temp = arm.take();
|
|
104
|
-
let jsx_el_name = JSXElementName::Ident(quote_ident!("block"));
|
|
105
|
-
**arm = Expr::JSXElement(Box::new(JSXElement {
|
|
106
|
-
span,
|
|
107
|
-
opening: JSXOpeningElement { name: jsx_el_name.clone(), span, attrs: vec![attr], self_closing: false, type_args: None },
|
|
108
|
-
children: vec![JSXElementChild::JSXExprContainer(JSXExprContainer { span, expr: JSXExpr::Expr(temp)})],
|
|
109
|
-
closing: Some(JSXClosingElement { span, name: jsx_el_name })
|
|
110
|
-
}))
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
process_cond_arm(cons, compile_if);
|
|
115
|
-
process_cond_arm(alt, compile_else);
|
|
116
|
-
},
|
|
117
|
-
_ => (),
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if is_first_and_expr {
|
|
121
|
-
self.is_in_and_expr = true;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
expr.visit_mut_children_with(self);
|
|
125
|
-
|
|
126
|
-
if is_first_and_expr {
|
|
127
|
-
self.is_in_and_expr = false;
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
child.visit_mut_children_with(self);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
pub struct TransformVisitor {
|
|
136
|
-
pub config: PluginConfig,
|
|
137
|
-
pub is_compile_mode: bool,
|
|
138
|
-
pub node_stack: Vec<i32>,
|
|
139
|
-
pub templates: HashMap<String, String>,
|
|
140
|
-
pub get_tmpl_name: Box<dyn FnMut() -> String>
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
impl TransformVisitor {
|
|
144
|
-
pub fn new (config: PluginConfig) -> Self {
|
|
145
|
-
let get_tmpl_name = Box::new(utils::named_iter(
|
|
146
|
-
format!("{}t", config.tmpl_prefix)
|
|
147
|
-
));
|
|
148
|
-
Self {
|
|
149
|
-
config,
|
|
150
|
-
is_compile_mode: false,
|
|
151
|
-
node_stack: vec![],
|
|
152
|
-
templates: HashMap::new(),
|
|
153
|
-
get_tmpl_name
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
fn build_xml_element (&mut self, el: &mut JSXElement) -> String {
|
|
158
|
-
let opening_element = &mut el.opening;
|
|
159
|
-
match &opening_element.name {
|
|
160
|
-
JSXElementName::Ident(ident) => {
|
|
161
|
-
let name = utils::to_kebab_case(ident.as_ref());
|
|
162
|
-
match self.config.components.get(&name) {
|
|
163
|
-
// 内置组件
|
|
164
|
-
Some(attrs_map) => {
|
|
165
|
-
let attrs = self.build_xml_attrs(opening_element, attrs_map);
|
|
166
|
-
if attrs.is_none() { return String::new() };
|
|
167
|
-
let (children, ..) = self.build_xml_children(&mut el.children, None);
|
|
168
|
-
format!("<{}{}>{}</{}>", name, attrs.unwrap(), children, name)
|
|
169
|
-
},
|
|
170
|
-
None => {
|
|
171
|
-
// React 组件
|
|
172
|
-
// 原生自定义组件
|
|
173
|
-
let node_path = self.get_current_node_path();
|
|
174
|
-
format!(r#"<template is="{{{{xs.a(c, {}.nn, l)}}}}" data="{{{{i:{},c:c+1,l:xs.f(l,{}.nn)}}}}" />"#, node_path, node_path, node_path)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
_ => String::new()
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
fn build_xml_attrs (&self, opening_element: &mut JSXOpeningElement, attrs_map: &HashMap<String, String>) -> Option<String> {
|
|
183
|
-
let mut props = HashMap::new();
|
|
184
|
-
let mut attrs_string = String::new();
|
|
185
|
-
|
|
186
|
-
opening_element.attrs.retain_mut(|attr| {
|
|
187
|
-
if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr {
|
|
188
|
-
if let JSXAttrName::Ident(Ident { sym: name, .. }) = &jsx_attr.name {
|
|
189
|
-
let jsx_attr_name = name.to_string();
|
|
190
|
-
|
|
191
|
-
if REACT_RESERVED.contains(&jsx_attr_name.as_str()) {
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
let miniapp_attr_name = utils::convert_jsx_attr_key(&jsx_attr_name, &self.config.adapter);
|
|
196
|
-
let event_name = utils::identify_jsx_event_key(&jsx_attr_name);
|
|
197
|
-
let is_event = event_name.is_some();
|
|
198
|
-
match &jsx_attr.value {
|
|
199
|
-
Some(jsx_attr_value) => {
|
|
200
|
-
match jsx_attr_value {
|
|
201
|
-
JSXAttrValue::Lit(Lit::Str(Str { value, .. })) => {
|
|
202
|
-
// 静态属性在 xml 中保留即可,jsx 中可以删除
|
|
203
|
-
if jsx_attr_name != COMPILE_MODE {
|
|
204
|
-
props.insert(miniapp_attr_name, value.to_string());
|
|
205
|
-
return false
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
JSXAttrValue::JSXExprContainer(..) => {
|
|
209
|
-
let mut node_path = self.get_current_node_path();
|
|
210
|
-
if is_event {
|
|
211
|
-
props.insert(event_name.unwrap(), String::from(EVENT_HANDLER));
|
|
212
|
-
if props.get(DATA_SID).is_none() {
|
|
213
|
-
props.insert(String::from(DATA_SID), format!("{{{{{}.sid}}}}", node_path));
|
|
214
|
-
}
|
|
215
|
-
return true
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 小程序组件标准属性 -> 取 @tarojs/shared 传递过来的属性值;非标准属性 -> 取属性名
|
|
219
|
-
let value: &str = attrs_map.get(&miniapp_attr_name).unwrap_or(&jsx_attr_name);
|
|
220
|
-
// 按当前节点在节点树中的位置换算路径
|
|
221
|
-
node_path.push('.');
|
|
222
|
-
let value = if value.contains(TMPL_DATA_ROOT) {
|
|
223
|
-
value.replace(TMPL_DATA_ROOT, &node_path)
|
|
224
|
-
} else {
|
|
225
|
-
format!("{}{}", node_path, value)
|
|
226
|
-
};
|
|
227
|
-
// 得出最终的模板属性值
|
|
228
|
-
let miniapp_attr_value = format!("{{{{{}}}}}", value);
|
|
229
|
-
|
|
230
|
-
props.insert(miniapp_attr_name, miniapp_attr_value);
|
|
231
|
-
},
|
|
232
|
-
_ => ()
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
None => {
|
|
236
|
-
if
|
|
237
|
-
jsx_attr_name == COMPILE_ELSE ||
|
|
238
|
-
jsx_attr_name == COMPILE_IGNORE
|
|
239
|
-
{
|
|
240
|
-
props.insert(miniapp_attr_name, String::from(jsx_attr_name));
|
|
241
|
-
} else if jsx_attr_name == COMPILE_FOR {
|
|
242
|
-
let current_path = self.get_current_loop_path();
|
|
243
|
-
let miniapp_attr_value = format!("{{{{{}}}}}", current_path);
|
|
244
|
-
props.insert(miniapp_attr_name, miniapp_attr_value);
|
|
245
|
-
} else {
|
|
246
|
-
props.insert(miniapp_attr_name, String::from("true"));
|
|
247
|
-
}
|
|
248
|
-
// 布尔值在 jsx 中也可以删除了
|
|
249
|
-
return false
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return true
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// 组件包含事件,但没有设置自定义 id 的话,把 id 设为 sid
|
|
258
|
-
if props.get(DATA_SID).is_some() && props.get(ID).is_none() {
|
|
259
|
-
props.insert(String::from(ID), props.get(DATA_SID).unwrap().clone());
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// 生成的 template 需要幂等
|
|
263
|
-
let mut keys: Vec<&String> = props.keys().collect();
|
|
264
|
-
keys.sort();
|
|
265
|
-
for key in keys {
|
|
266
|
-
let value = props.get(key).unwrap();
|
|
267
|
-
if value == COMPILE_IGNORE {
|
|
268
|
-
return None
|
|
269
|
-
} else if value == COMPILE_ELSE {
|
|
270
|
-
attrs_string.push_str(&format!(" {}", key));
|
|
271
|
-
} else {
|
|
272
|
-
attrs_string.push_str(&format!(r#" {}="{}""#, key, value));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
Some(attrs_string)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
fn build_xml_children (&mut self, children: &mut Vec<JSXElementChild>, retain_start_from: Option<i32>) -> (String, i32) {
|
|
280
|
-
let mut children_string = String::new();
|
|
281
|
-
let start = if retain_start_from.is_some() { retain_start_from.unwrap() } else { 0 };
|
|
282
|
-
let mut retain_child_counter = start;
|
|
283
|
-
|
|
284
|
-
children
|
|
285
|
-
.retain_mut(|child| {
|
|
286
|
-
let mut is_retain = true;
|
|
287
|
-
self.node_stack.push(retain_child_counter);
|
|
288
|
-
match child {
|
|
289
|
-
JSXElementChild::JSXElement(child_el) => {
|
|
290
|
-
let child_string = self.build_xml_element(&mut **child_el);
|
|
291
|
-
children_string.push_str(&child_string);
|
|
292
|
-
|
|
293
|
-
if utils::is_static_jsx(child_el) && utils::is_inner_component(child_el, &self.config) {
|
|
294
|
-
is_retain = false
|
|
295
|
-
} else {
|
|
296
|
-
retain_child_counter += 1;
|
|
297
|
-
}
|
|
298
|
-
},
|
|
299
|
-
JSXElementChild::JSXExprContainer(JSXExprContainer {
|
|
300
|
-
expr: JSXExpr::Expr(jsx_expr),
|
|
301
|
-
..
|
|
302
|
-
}) => {
|
|
303
|
-
if let Expr::Paren(ParenExpr { expr, .. }) = &mut **jsx_expr {
|
|
304
|
-
*jsx_expr = expr.take();
|
|
305
|
-
}
|
|
306
|
-
let node_path = self.get_current_node_path();
|
|
307
|
-
match &mut **jsx_expr {
|
|
308
|
-
Expr::Cond(CondExpr { cons, alt, ..}) => {
|
|
309
|
-
let mut process_condition_expr = |arm: &mut Box<Expr>| {
|
|
310
|
-
match &mut **arm {
|
|
311
|
-
Expr::JSXElement(el) => {
|
|
312
|
-
let child_string = self.build_xml_element(el);
|
|
313
|
-
children_string.push_str(&child_string);
|
|
314
|
-
},
|
|
315
|
-
Expr::Lit(lit) => {
|
|
316
|
-
if let Lit::Str(Str { value, .. }) = lit {
|
|
317
|
-
if value == COMPILE_IGNORE {
|
|
318
|
-
return ();
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
// {condition1 && 'Hello'} 在预处理时会变成 {condition1 ? 'Hello' : "compileIgnore"}
|
|
322
|
-
// 而普通文本三元则会被 block 标签包裹,因此处理后只有上述情况会存在 lit 类型的表达式
|
|
323
|
-
// 由于这种情况没有办法使用 wx:if 来处理,需要特殊处理成 {{i.cn[3].v==="compileIgnore"?"":i.cn[3].v}} 的形式
|
|
324
|
-
let str = format!(r#"{{{{{}.v==="{}"?"":{}.v}}}}"#, node_path, COMPILE_IGNORE, node_path);
|
|
325
|
-
children_string.push_str(&str);
|
|
326
|
-
},
|
|
327
|
-
_ => ()
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
process_condition_expr(cons);
|
|
331
|
-
process_condition_expr(alt);
|
|
332
|
-
},
|
|
333
|
-
Expr::Call(CallExpr {
|
|
334
|
-
callee: Callee::Expr(callee_expr),
|
|
335
|
-
args,
|
|
336
|
-
..
|
|
337
|
-
}) => {
|
|
338
|
-
// 处理循环
|
|
339
|
-
if let Some(return_value) = utils::extract_jsx_loop(callee_expr, args) {
|
|
340
|
-
self.node_stack.pop();
|
|
341
|
-
self.node_stack.push(LOOP_WRAPPER_ID);
|
|
342
|
-
let child_string = self.build_xml_element(&mut *return_value);
|
|
343
|
-
children_string.push_str(&child_string);
|
|
344
|
-
} else if utils::is_render_fn(callee_expr) {
|
|
345
|
-
let tmpl = format!(r#"<template is="{{{{xs.a(c, {}.nn, l)}}}}" data="{{{{i:{},c:c+1,l:xs.f(l,{}.nn)}}}}" />"#, node_path, node_path, node_path);
|
|
346
|
-
children_string.push_str(&tmpl)
|
|
347
|
-
} else {
|
|
348
|
-
let code = utils::gen_template_v(&node_path);
|
|
349
|
-
children_string.push_str(&code);
|
|
350
|
-
}
|
|
351
|
-
},
|
|
352
|
-
_ => {
|
|
353
|
-
let code = utils::gen_template_v(&node_path);
|
|
354
|
-
children_string.push_str(&code);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
retain_child_counter = retain_child_counter + 1
|
|
358
|
-
},
|
|
359
|
-
JSXElementChild::JSXText(JSXText { value, .. }) => {
|
|
360
|
-
let content = utils::jsx_text_to_string(value);
|
|
361
|
-
if !content.is_empty() {
|
|
362
|
-
children_string.push_str(&content);
|
|
363
|
-
// JSX 过滤掉静态文本节点,只在模板中保留。同时保留用于换行、空格的静态文本节点
|
|
364
|
-
is_retain = false
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
JSXElementChild::JSXFragment(child_el) => {
|
|
368
|
-
self.node_stack.pop();
|
|
369
|
-
let (child_string, inner_retain) = self.build_xml_children(&mut child_el.children, Some(retain_child_counter));
|
|
370
|
-
children_string.push_str(&child_string);
|
|
371
|
-
if inner_retain == 0 {
|
|
372
|
-
// 静态 fragment,在 JSX 中删除
|
|
373
|
-
is_retain = false
|
|
374
|
-
} else {
|
|
375
|
-
retain_child_counter += inner_retain;
|
|
376
|
-
}
|
|
377
|
-
self.node_stack.push(retain_child_counter);
|
|
378
|
-
},
|
|
379
|
-
_ => ()
|
|
380
|
-
}
|
|
381
|
-
self.node_stack.pop();
|
|
382
|
-
return is_retain
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
(children_string, retain_child_counter - start)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
fn get_current_node_path (&self) -> String {
|
|
389
|
-
// return: i.cn[0].cn[0]....
|
|
390
|
-
self.node_stack
|
|
391
|
-
.iter()
|
|
392
|
-
.fold(String::from("i"), |mut acc, item| {
|
|
393
|
-
if item == &LOOP_WRAPPER_ID {
|
|
394
|
-
return String::from("item")
|
|
395
|
-
}
|
|
396
|
-
acc.push_str(&format!(".cn[{}]", item));
|
|
397
|
-
return acc;
|
|
398
|
-
})
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
fn get_current_loop_path (&self) -> String {
|
|
402
|
-
// return: i.cn[0]...cn
|
|
403
|
-
self.node_stack
|
|
404
|
-
.iter()
|
|
405
|
-
.identify_last()
|
|
406
|
-
.fold(String::from("i"), |mut acc, (is_last, item)| {
|
|
407
|
-
let str = if is_last {
|
|
408
|
-
String::from(".cn")
|
|
409
|
-
} else {
|
|
410
|
-
if item == &LOOP_WRAPPER_ID {
|
|
411
|
-
return String::from("item")
|
|
412
|
-
}
|
|
413
|
-
format!(".cn[{}]", item)
|
|
414
|
-
};
|
|
415
|
-
acc.push_str(&str);
|
|
416
|
-
return acc;
|
|
417
|
-
})
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
impl VisitMut for TransformVisitor {
|
|
422
|
-
// Implement necessary visit_mut_* methods for actual custom transform.
|
|
423
|
-
// A comprehensive list of possible visitor methods can be found here:
|
|
424
|
-
// https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html
|
|
425
|
-
fn visit_mut_jsx_element (&mut self, el: &mut JSXElement) {
|
|
426
|
-
let mut tmpl_name = String::new();
|
|
427
|
-
for attr in &mut el.opening.attrs {
|
|
428
|
-
if let JSXAttrOrSpread::JSXAttr(jsx_attr) = attr {
|
|
429
|
-
if let JSXAttrName::Ident(jsx_attr_name) = &jsx_attr.name {
|
|
430
|
-
if jsx_attr_name.sym == COMPILE_MODE {
|
|
431
|
-
self.is_compile_mode = true;
|
|
432
|
-
tmpl_name = (self.get_tmpl_name)();
|
|
433
|
-
jsx_attr.value = Some(JSXAttrValue::Lit(Lit::Str(quote_str!(tmpl_name.as_str()))));
|
|
434
|
-
break;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if self.is_compile_mode {
|
|
440
|
-
el.visit_mut_children_with(&mut PreVisitor::new());
|
|
441
|
-
let tmpl_contents = format!(r#"<template name="tmpl_0_{}">{}</template>"#,
|
|
442
|
-
&tmpl_name,
|
|
443
|
-
self.build_xml_element(el)
|
|
444
|
-
);
|
|
445
|
-
self.templates.insert(tmpl_name, tmpl_contents);
|
|
446
|
-
self.is_compile_mode = false;
|
|
447
|
-
} else {
|
|
448
|
-
el.visit_mut_children_with(self)
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
fn visit_mut_module_items (&mut self, body_stmts: &mut Vec<ModuleItem>) {
|
|
453
|
-
body_stmts.visit_mut_children_with(self);
|
|
454
|
-
|
|
455
|
-
let mut keys: Vec<&String> = self.templates.keys().collect();
|
|
456
|
-
keys.sort();
|
|
457
|
-
let stmts_being_inserted = keys.into_iter()
|
|
458
|
-
.map(|key| {
|
|
459
|
-
let value = self.templates.get(key).unwrap();
|
|
460
|
-
ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl {
|
|
461
|
-
span,
|
|
462
|
-
kind: VarDeclKind::Const,
|
|
463
|
-
declare: false,
|
|
464
|
-
decls: vec![VarDeclarator {
|
|
465
|
-
span,
|
|
466
|
-
name: Pat::Ident(Ident::new(Atom::new(format!("TARO_TEMPLATES_{}", key)), span).into()),
|
|
467
|
-
init: Some(Box::new(Expr::Lit(Lit::Str(quote_str!(value.as_str()))))),
|
|
468
|
-
definite: false,
|
|
469
|
-
}],
|
|
470
|
-
}))))
|
|
471
|
-
});
|
|
472
|
-
ecma::utils::prepend_stmts(body_stmts, stmts_being_inserted);
|
|
473
|
-
}
|
|
474
|
-
}
|