babel-plugin-transform-taroapi 3.6.6-alpha.3 → 3.6.7
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/__tests__/__snapshots__/index.spec.ts.snap +10 -40
- package/__tests__/index.spec.ts +144 -185
- package/dist/index.js +16 -83
- package/{jest.config.ts → jest.config.js} +1 -5
- package/package.json +1 -4
- package/src/index.ts +20 -99
- package/types.d.ts +5 -0
|
@@ -1,47 +1,17 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`
|
|
4
|
-
"import { canIUse as _canUse } from '@tarojs/taro-h5';
|
|
5
|
-
// 对象的属性或方法
|
|
6
|
-
false;
|
|
7
|
-
false;
|
|
8
|
-
false;
|
|
9
|
-
false;
|
|
10
|
-
|
|
11
|
-
// 接口参数、回调或者返回值
|
|
12
|
-
false;
|
|
13
|
-
false;
|
|
14
|
-
false;
|
|
15
|
-
false;
|
|
16
|
-
false;
|
|
17
|
-
true;
|
|
18
|
-
|
|
19
|
-
// 组件的属性
|
|
20
|
-
false;
|
|
21
|
-
false;
|
|
22
|
-
false;"
|
|
23
|
-
`;
|
|
24
|
-
|
|
25
|
-
exports[`babel-plugin-transform-taroapi should canIUse work or skip! 1`] = `
|
|
26
|
-
"import Taro from '@tarojs/taro-h5';
|
|
27
|
-
function canIUse() {}
|
|
28
|
-
false;
|
|
29
|
-
false;
|
|
30
|
-
canIUse('showToast.object.image');"
|
|
31
|
-
`;
|
|
32
|
-
|
|
33
|
-
exports[`babel-plugin-transform-taroapi should leave other apis untouched 1`] = `
|
|
3
|
+
exports[`should leave other apis untouched 1`] = `
|
|
34
4
|
"import Taro from '@tarojs/taro-h5';
|
|
35
5
|
Taro.noop;"
|
|
36
6
|
`;
|
|
37
7
|
|
|
38
|
-
exports[`
|
|
8
|
+
exports[`should move static apis under "Taro" 1`] = `
|
|
39
9
|
"import Taro from '@tarojs/taro-h5';
|
|
40
10
|
Taro.noop;
|
|
41
11
|
Taro.noop();"
|
|
42
12
|
`;
|
|
43
13
|
|
|
44
|
-
exports[`
|
|
14
|
+
exports[`should not go wrong when using an api twice 1`] = `
|
|
45
15
|
"import Taro, { createAnimation as _createAnimation } from '@tarojs/taro-h5';
|
|
46
16
|
const animation = _createAnimation({
|
|
47
17
|
duration: dura * 1000,
|
|
@@ -53,14 +23,14 @@ const resetAnimation = _createAnimation({
|
|
|
53
23
|
});"
|
|
54
24
|
`;
|
|
55
25
|
|
|
56
|
-
exports[`
|
|
57
|
-
"import Taro, { createAnimation as _createAnimation, initPxTransform as _initPxTransform } from
|
|
26
|
+
exports[`should not import taro duplicatly 1`] = `
|
|
27
|
+
"import Taro, { createAnimation as _createAnimation, initPxTransform as _initPxTransform } from "@tarojs/taro-h5";
|
|
58
28
|
Taro.Component;
|
|
59
29
|
_createAnimation();
|
|
60
30
|
_initPxTransform();"
|
|
61
31
|
`;
|
|
62
32
|
|
|
63
|
-
exports[`
|
|
33
|
+
exports[`should preserve assignments in lefthands 1`] = `
|
|
64
34
|
"import Taro, { createAnimation as _createAnimation, request as _request } from '@tarojs/taro-h5';
|
|
65
35
|
let animation;
|
|
66
36
|
animation = _createAnimation({
|
|
@@ -74,18 +44,18 @@ Taro.request = '';
|
|
|
74
44
|
Taro['request'] = '';"
|
|
75
45
|
`;
|
|
76
46
|
|
|
77
|
-
exports[`
|
|
47
|
+
exports[`should preserve default imports 1`] = `
|
|
78
48
|
"import Taro from '@tarojs/taro-h5';
|
|
79
49
|
console.log(Taro);"
|
|
80
50
|
`;
|
|
81
51
|
|
|
82
|
-
exports[`
|
|
52
|
+
exports[`should support rename of imported names 1`] = `
|
|
83
53
|
"// import { inject as mobxInject, observer as mobxObserver } from '@tarojs/mobx'
|
|
84
|
-
import Taro from
|
|
54
|
+
import Taro from "@tarojs/taro-h5";
|
|
85
55
|
export class Connected extends Taro.Component {}"
|
|
86
56
|
`;
|
|
87
57
|
|
|
88
|
-
exports[`
|
|
58
|
+
exports[`should work! 1`] = `
|
|
89
59
|
"import Taro, { setStorage as _setStorage, initPxTransform as _initPxTransform, getStorage as _getStorage } from '@tarojs/taro-h5';
|
|
90
60
|
_initPxTransform(Taro.param);
|
|
91
61
|
_initPxTransform();
|
package/__tests__/index.spec.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import * as babel from '@babel/core'
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
|
-
import * as
|
|
3
|
+
import * as apis from '@tarojs/plugin-platform-h5/dist/taroApis'
|
|
4
4
|
|
|
5
5
|
import plugin from '../src'
|
|
6
6
|
|
|
7
7
|
type ImportType = babel.types.ImportSpecifier | babel.types.ImportDefaultSpecifier | babel.types.ImportNamespaceSpecifier
|
|
8
8
|
|
|
9
|
-
const packageName = '@tarojs/taro-h5'
|
|
10
9
|
const pluginOptions = [
|
|
11
10
|
plugin,
|
|
12
11
|
{
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
apis,
|
|
13
|
+
packageName: '@tarojs/taro-h5'
|
|
15
14
|
}
|
|
16
15
|
]
|
|
17
16
|
const getNamedImports = (importSpecifiers: (t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier)[]) => {
|
|
@@ -22,188 +21,148 @@ const getNamedImports = (importSpecifiers: (t.ImportSpecifier | t.ImportDefaultS
|
|
|
22
21
|
return prev
|
|
23
22
|
}, new Set())
|
|
24
23
|
}
|
|
25
|
-
const babelTransform = (code = '') => babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
26
|
-
|
|
27
|
-
describe('babel-plugin-transform-taroapi', () => {
|
|
28
|
-
test.skip('should work!', function () {
|
|
29
|
-
const code = `
|
|
30
|
-
import Taro, { setStorage, initPxTransform, param } from '${packageName}';
|
|
31
|
-
initPxTransform(param)
|
|
32
|
-
Taro.initPxTransform()
|
|
33
|
-
Taro.initPxTransform()
|
|
34
|
-
Taro['getStorage']()
|
|
35
|
-
setStorage()
|
|
36
|
-
export { Taro }
|
|
37
|
-
`
|
|
38
|
-
const result = babelTransform(code)
|
|
39
|
-
expect(result?.code).toMatchSnapshot()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test.skip('should leave other apis untouched', function () {
|
|
43
|
-
const code = `
|
|
44
|
-
import Taro from '${packageName}'
|
|
45
|
-
Taro.noop
|
|
46
|
-
`
|
|
47
|
-
const result = babelTransform(code)
|
|
48
|
-
expect(result?.code).toMatchSnapshot()
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
t.identifier('noop'),
|
|
65
|
-
)
|
|
66
|
-
delete obj.optional
|
|
67
|
-
|
|
68
|
-
expect((body[1].expression as t.MemberExpression)).toMatchObject(obj)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
test.skip('should move static apis under "Taro"', function () {
|
|
72
|
-
const code = `
|
|
73
|
-
import { noop } from '${packageName}';
|
|
74
|
-
noop;
|
|
75
|
-
noop();
|
|
76
|
-
`
|
|
77
|
-
|
|
78
|
-
const result = babelTransform(code)
|
|
79
|
-
expect(result?.code).toMatchSnapshot()
|
|
25
|
+
it('should work!', function () {
|
|
26
|
+
const code = `
|
|
27
|
+
import Taro, { setStorage, initPxTransform, param } from '@tarojs/taro-h5';
|
|
28
|
+
initPxTransform(param)
|
|
29
|
+
Taro.initPxTransform()
|
|
30
|
+
Taro.initPxTransform()
|
|
31
|
+
Taro['getStorage']()
|
|
32
|
+
setStorage()
|
|
33
|
+
export { Taro }
|
|
34
|
+
`
|
|
35
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
36
|
+
|
|
37
|
+
expect(result?.code).toMatchSnapshot()
|
|
38
|
+
})
|
|
80
39
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
test('should canIUse work or skip!', function () {
|
|
173
|
-
const code = `
|
|
174
|
-
import Taro from '${packageName}'
|
|
175
|
-
function canIUse() {}
|
|
176
|
-
Taro.canIUse('showToast.object.image')
|
|
177
|
-
Taro['canIUse']('showToast.object.image')
|
|
178
|
-
canIUse('showToast.object.image')
|
|
179
|
-
`
|
|
180
|
-
const result = babelTransform(code)
|
|
181
|
-
expect(result?.code).toMatchSnapshot()
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('should canIUse support!', function () {
|
|
185
|
-
const code = `
|
|
186
|
-
import { canIUse as canUse } from '${packageName}';
|
|
187
|
-
// 对象的属性或方法
|
|
188
|
-
canUse('console.log')
|
|
189
|
-
canUse('CameraContext.onCameraFrame')
|
|
190
|
-
canUse('CameraFrameListener.start')
|
|
191
|
-
canUse('Image.src')
|
|
192
|
-
|
|
193
|
-
// 接口参数、回调或者返回值
|
|
194
|
-
canUse('openBluetoothAdapter')
|
|
195
|
-
canUse('getSystemInfoSync.return.safeArea.left')
|
|
196
|
-
canUse('getSystemInfo.success.screenWidth')
|
|
197
|
-
canUse('showToast.object.image')
|
|
198
|
-
canUse('onCompassChange.callback.direction')
|
|
199
|
-
canUse('request.object.method.GET')
|
|
200
|
-
|
|
201
|
-
// 组件的属性
|
|
202
|
-
canUse('live-player')
|
|
203
|
-
canUse('text.selectable')
|
|
204
|
-
canUse('button.open-type.contact')
|
|
205
|
-
`
|
|
206
|
-
const result = babelTransform(code)
|
|
40
|
+
it('should leave other apis untouched', function () {
|
|
41
|
+
const code = `
|
|
42
|
+
import Taro from '@tarojs/taro-h5'
|
|
43
|
+
Taro.noop
|
|
44
|
+
`
|
|
45
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] }) as babel.BabelFileResult
|
|
46
|
+
expect(result.code).toMatchSnapshot()
|
|
47
|
+
|
|
48
|
+
const ast = result.ast as t.File
|
|
49
|
+
const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement]
|
|
50
|
+
expect(t.isImportDeclaration(body[0])).toBeTruthy()
|
|
51
|
+
expect(t.isExpressionStatement(body[1])).toBeTruthy()
|
|
52
|
+
const defaultImport = body[0].specifiers.find(v => t.isImportDefaultSpecifier(v)) as ImportType
|
|
53
|
+
expect(defaultImport).toBeTruthy()
|
|
54
|
+
|
|
55
|
+
const taroName = defaultImport.local.name
|
|
56
|
+
const namedImports = getNamedImports(body[0].specifiers)
|
|
57
|
+
expect(namedImports).toEqual(new Set())
|
|
58
|
+
expect(t.isMemberExpression(body[1].expression)).toBeTruthy()
|
|
59
|
+
|
|
60
|
+
const obj = t.memberExpression(
|
|
61
|
+
t.identifier(taroName),
|
|
62
|
+
t.identifier('noop'),
|
|
63
|
+
)
|
|
64
|
+
delete obj.optional
|
|
65
|
+
|
|
66
|
+
expect((body[1].expression as t.MemberExpression)).toMatchObject(obj)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should move static apis under "Taro"', function () {
|
|
70
|
+
const code = `
|
|
71
|
+
import { noop } from '@tarojs/taro-h5';
|
|
72
|
+
noop;
|
|
73
|
+
noop();
|
|
74
|
+
`
|
|
75
|
+
|
|
76
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
77
|
+
expect(result?.code).toMatchSnapshot()
|
|
78
|
+
|
|
79
|
+
const ast = result?.ast as t.File
|
|
80
|
+
const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement]
|
|
81
|
+
expect(t.isImportDeclaration(body[0])).toBeTruthy()
|
|
82
|
+
expect(t.isExpressionStatement(body[1])).toBeTruthy()
|
|
83
|
+
const defaultImport = body[0].specifiers.find(v => t.isImportDefaultSpecifier(v))
|
|
84
|
+
expect(defaultImport).toBeTruthy()
|
|
85
|
+
|
|
86
|
+
const taroName = defaultImport!.local.name
|
|
87
|
+
let memberExpression: any = body[1].expression
|
|
88
|
+
if (t.isCallExpression(body[1])) {
|
|
89
|
+
memberExpression = ((body[1] as t.ExpressionStatement).expression as t.CallExpression).callee
|
|
90
|
+
}
|
|
91
|
+
expect(memberExpression).toMatchObject(t.memberExpression(
|
|
92
|
+
t.identifier(taroName),
|
|
93
|
+
t.identifier('noop')
|
|
94
|
+
))
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('should not import taro duplicatly', function () {
|
|
98
|
+
const code = `
|
|
99
|
+
import { Component } from "@tarojs/taro-h5";
|
|
100
|
+
import Taro from '@tarojs/taro-h5';
|
|
101
|
+
Component
|
|
102
|
+
Taro.createAnimation()
|
|
103
|
+
Taro.initPxTransform()
|
|
104
|
+
`
|
|
105
|
+
|
|
106
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
107
|
+
expect(result?.code).toMatchSnapshot()
|
|
108
|
+
const ast = result?.ast as t.File
|
|
109
|
+
const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement, t.ExpressionStatement]
|
|
110
|
+
expect(t.isImportDeclaration(body[0])).toBeTruthy()
|
|
111
|
+
expect(t.isExpressionStatement(body[1])).toBeTruthy()
|
|
112
|
+
expect(t.isExpressionStatement(body[2])).toBeTruthy()
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should not go wrong when using an api twice', function () {
|
|
116
|
+
const code = `
|
|
117
|
+
import Taro from '@tarojs/taro-h5';
|
|
118
|
+
const animation = Taro.createAnimation({
|
|
119
|
+
duration: dura * 1000,
|
|
120
|
+
timingFunction: 'linear'
|
|
121
|
+
})
|
|
122
|
+
const resetAnimation = Taro.createAnimation({
|
|
123
|
+
duration: 0,
|
|
124
|
+
timingFunction: 'linear'
|
|
125
|
+
})
|
|
126
|
+
`
|
|
127
|
+
expect(() => {
|
|
128
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
207
129
|
expect(result?.code).toMatchSnapshot()
|
|
208
|
-
})
|
|
130
|
+
}).not.toThrowError()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should preserve default imports', function () {
|
|
134
|
+
const code = `
|
|
135
|
+
import Taro from '@tarojs/taro-h5'
|
|
136
|
+
console.log(Taro)
|
|
137
|
+
`
|
|
138
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
139
|
+
expect(result?.code).toMatchSnapshot()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should preserve assignments in lefthands', function () {
|
|
143
|
+
const code = `
|
|
144
|
+
import Taro from '@tarojs/taro-h5'
|
|
145
|
+
let animation
|
|
146
|
+
animation = Taro.createAnimation({
|
|
147
|
+
transformOrigin: "50% 50%",
|
|
148
|
+
duration: 1000,
|
|
149
|
+
timingFunction: "ease",
|
|
150
|
+
delay: 0
|
|
151
|
+
});
|
|
152
|
+
Taro.request()
|
|
153
|
+
Taro.request = ''
|
|
154
|
+
Taro['request'] = ''
|
|
155
|
+
`
|
|
156
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
157
|
+
expect(result?.code).toMatchSnapshot()
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('should support rename of imported names', function () {
|
|
161
|
+
const code = `
|
|
162
|
+
// import { inject as mobxInject, observer as mobxObserver } from '@tarojs/mobx'
|
|
163
|
+
import { Component as TaroComponent } from "@tarojs/taro-h5";
|
|
164
|
+
export class Connected extends TaroComponent {}
|
|
165
|
+
`
|
|
166
|
+
const result = babel.transform(code, { ast: true, configFile: false, plugins: [pluginOptions] })
|
|
167
|
+
expect(result?.code).toMatchSnapshot()
|
|
209
168
|
})
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const lodash_1 = require("lodash");
|
|
4
3
|
const plugin = function (babel) {
|
|
5
4
|
const t = babel.types;
|
|
6
5
|
// 这些变量需要在每个 program 里重置
|
|
@@ -8,43 +7,13 @@ const plugin = function (babel) {
|
|
|
8
7
|
let taroName;
|
|
9
8
|
let needDefault;
|
|
10
9
|
let referTaro;
|
|
11
|
-
function canIUse(definition, scheme = '') {
|
|
12
|
-
if (!scheme)
|
|
13
|
-
return false;
|
|
14
|
-
const o = (0, lodash_1.set)({}, scheme, true);
|
|
15
|
-
return (0, lodash_1.isMatchWith)(definition, o, (a, _) => {
|
|
16
|
-
if (a === '*')
|
|
17
|
-
return true;
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
function replaceCanIUse(ast, definition) {
|
|
21
|
-
const args = ast.node.arguments;
|
|
22
|
-
if (args.length < 1)
|
|
23
|
-
return;
|
|
24
|
-
// Note: 暂不考虑其他类型的参数映射
|
|
25
|
-
if (t.isStringLiteral(args[0])) {
|
|
26
|
-
const isSupported = canIUse(definition, args[0].value);
|
|
27
|
-
ast.replaceInline(t.booleanLiteral(isSupported));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
10
|
return {
|
|
31
11
|
name: 'babel-plugin-transform-taro-api',
|
|
32
|
-
pre() {
|
|
33
|
-
const { opts = {} } = this;
|
|
34
|
-
const { apis = new Set(), bindingName = 'Taro', packageName = '@tarojs/taro-h5', definition = {} } = opts;
|
|
35
|
-
this.definition = Object.assign(Object.assign(Object.assign({}, definition.apis), definition.components), { [this.canIUse]: '*' });
|
|
36
|
-
this.bindingName = bindingName;
|
|
37
|
-
this.packageName = packageName;
|
|
38
|
-
this.canIUse = 'canIUse';
|
|
39
|
-
if (apis.size < 1) {
|
|
40
|
-
apis.add(this.canIUse);
|
|
41
|
-
Object.keys(definition.apis || {}).forEach(key => apis.add(key));
|
|
42
|
-
}
|
|
43
|
-
this.apis = apis;
|
|
44
|
-
},
|
|
45
12
|
visitor: {
|
|
46
|
-
ImportDeclaration(ast) {
|
|
47
|
-
|
|
13
|
+
ImportDeclaration(ast, state) {
|
|
14
|
+
const packageName = state.opts.packageName;
|
|
15
|
+
const apis = state.opts.apis;
|
|
16
|
+
if (ast.node.source.value !== packageName)
|
|
48
17
|
return;
|
|
49
18
|
ast.node.specifiers.forEach(node => {
|
|
50
19
|
if (t.isImportDefaultSpecifier(node)) {
|
|
@@ -52,9 +21,8 @@ const plugin = function (babel) {
|
|
|
52
21
|
taroName = node.local.name;
|
|
53
22
|
}
|
|
54
23
|
else if (t.isImportSpecifier(node)) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
if (this.apis.has(propertyName)) { // 记录api名字
|
|
24
|
+
const propertyName = node.imported.name;
|
|
25
|
+
if (apis.has(propertyName)) { // 记录api名字
|
|
58
26
|
ast.scope.rename(node.local.name);
|
|
59
27
|
invokedApis.set(propertyName, node.local.name);
|
|
60
28
|
}
|
|
@@ -71,8 +39,9 @@ const plugin = function (babel) {
|
|
|
71
39
|
}
|
|
72
40
|
});
|
|
73
41
|
},
|
|
74
|
-
MemberExpression(ast) {
|
|
42
|
+
MemberExpression(ast, state) {
|
|
75
43
|
/* 处理Taro.xxx */
|
|
44
|
+
const apis = state.opts.apis;
|
|
76
45
|
const isTaro = t.isIdentifier(ast.node.object, { name: taroName });
|
|
77
46
|
const property = ast.node.property;
|
|
78
47
|
let propertyName = null;
|
|
@@ -87,7 +56,7 @@ const plugin = function (babel) {
|
|
|
87
56
|
if (!propertyName)
|
|
88
57
|
return;
|
|
89
58
|
// 同一api使用多次, 读取变量名
|
|
90
|
-
if (
|
|
59
|
+
if (apis.has(propertyName)) {
|
|
91
60
|
const parentNode = ast.parent;
|
|
92
61
|
const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === ast.node;
|
|
93
62
|
if (!isAssignment) {
|
|
@@ -108,42 +77,16 @@ const plugin = function (babel) {
|
|
|
108
77
|
needDefault = true;
|
|
109
78
|
}
|
|
110
79
|
},
|
|
111
|
-
CallExpression(ast) {
|
|
112
|
-
if (!ast.scope.hasReference(this.canIUse))
|
|
113
|
-
return;
|
|
114
|
-
const callee = ast.node.callee;
|
|
115
|
-
if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: taroName })) {
|
|
116
|
-
let propertyName = null;
|
|
117
|
-
let propName = 'name';
|
|
118
|
-
// 兼容一下 Taro['xxx']
|
|
119
|
-
if (t.isStringLiteral(callee.property)) {
|
|
120
|
-
propName = 'value';
|
|
121
|
-
}
|
|
122
|
-
propertyName = callee.property[propName];
|
|
123
|
-
if (propertyName === this.canIUse) {
|
|
124
|
-
// Taro.canIUse or Taro['canIUse']
|
|
125
|
-
replaceCanIUse(ast, this.definition);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else if (invokedApis.has(this.canIUse)) {
|
|
129
|
-
const { name } = t.identifier(invokedApis.get(this.canIUse));
|
|
130
|
-
const isCanIUse = t.isIdentifier(callee, { name });
|
|
131
|
-
// canIUse as _canIUse
|
|
132
|
-
if (isCanIUse)
|
|
133
|
-
replaceCanIUse(ast, this.definition);
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
80
|
Program: {
|
|
137
81
|
enter(ast) {
|
|
138
82
|
needDefault = false;
|
|
139
83
|
referTaro = [];
|
|
140
84
|
invokedApis.clear();
|
|
141
|
-
taroName = ast.scope.getBinding(
|
|
142
|
-
? ast.scope.generateUid(
|
|
143
|
-
:
|
|
85
|
+
taroName = ast.scope.getBinding('Taro')
|
|
86
|
+
? ast.scope.generateUid('Taro')
|
|
87
|
+
: 'Taro';
|
|
144
88
|
},
|
|
145
|
-
exit(ast) {
|
|
146
|
-
const that = this;
|
|
89
|
+
exit(ast, state) {
|
|
147
90
|
// 防止重复引入
|
|
148
91
|
let isTaroApiImported = false;
|
|
149
92
|
referTaro.forEach(node => {
|
|
@@ -151,7 +94,8 @@ const plugin = function (babel) {
|
|
|
151
94
|
});
|
|
152
95
|
ast.traverse({
|
|
153
96
|
ImportDeclaration(ast) {
|
|
154
|
-
const
|
|
97
|
+
const packageName = state.opts.packageName;
|
|
98
|
+
const isImportingTaroApi = ast.node.source.value === packageName;
|
|
155
99
|
if (!isImportingTaroApi)
|
|
156
100
|
return;
|
|
157
101
|
if (isTaroApiImported)
|
|
@@ -169,18 +113,7 @@ const plugin = function (babel) {
|
|
|
169
113
|
else {
|
|
170
114
|
ast.node.specifiers = namedImports;
|
|
171
115
|
}
|
|
172
|
-
}
|
|
173
|
-
CallExpression(ast) {
|
|
174
|
-
if (!invokedApis.has(that.canIUse))
|
|
175
|
-
return;
|
|
176
|
-
const callee = ast.node.callee;
|
|
177
|
-
const { name } = t.identifier(invokedApis.get(that.canIUse));
|
|
178
|
-
const isCanIUse = t.isIdentifier(callee, { name });
|
|
179
|
-
if (isCanIUse) {
|
|
180
|
-
// canIUse as _use
|
|
181
|
-
replaceCanIUse(ast, that.definition);
|
|
182
|
-
}
|
|
183
|
-
},
|
|
116
|
+
}
|
|
184
117
|
});
|
|
185
118
|
}
|
|
186
119
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const config: Config = {
|
|
1
|
+
module.exports = {
|
|
4
2
|
collectCoverage: false,
|
|
5
3
|
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'],
|
|
6
4
|
preset: 'ts-jest',
|
|
@@ -20,5 +18,3 @@ const config: Config = {
|
|
|
20
18
|
},
|
|
21
19
|
transformIgnorePatterns: ['<rootDir>/node_modules/']
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
export default config
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
interface IState extends BabelCore.PluginPass {
|
|
6
|
-
apis: Set<string>
|
|
7
|
-
bindingName: string
|
|
8
|
-
packageName: string
|
|
9
|
-
canIUse: string
|
|
10
|
-
definition: Record<string, any>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
1
|
+
const plugin = function (babel: {
|
|
2
|
+
types: any
|
|
3
|
+
}) {
|
|
14
4
|
const t = babel.types
|
|
15
5
|
|
|
16
6
|
// 这些变量需要在每个 program 里重置
|
|
@@ -20,57 +10,21 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
20
10
|
|
|
21
11
|
let referTaro: any[]
|
|
22
12
|
|
|
23
|
-
function canIUse (definition, scheme = '') {
|
|
24
|
-
if (!scheme) return false
|
|
25
|
-
const o = set({}, scheme, true)
|
|
26
|
-
return isMatchWith(definition, o, (a, _) => {
|
|
27
|
-
if (a === '*') return true
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function replaceCanIUse (ast: BabelCore.NodePath<BabelCore.types.CallExpression>, definition) {
|
|
32
|
-
const args = ast.node.arguments
|
|
33
|
-
|
|
34
|
-
if (args.length < 1) return
|
|
35
|
-
|
|
36
|
-
// Note: 暂不考虑其他类型的参数映射
|
|
37
|
-
if (t.isStringLiteral(args[0])) {
|
|
38
|
-
const isSupported = canIUse(definition, args[0].value)
|
|
39
|
-
ast.replaceInline(t.booleanLiteral(isSupported))
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
13
|
return {
|
|
44
14
|
name: 'babel-plugin-transform-taro-api',
|
|
45
|
-
pre () {
|
|
46
|
-
const { opts = {} as any } = this
|
|
47
|
-
const { apis = new Set<string>(), bindingName = 'Taro', packageName = '@tarojs/taro-h5', definition = {} } = opts
|
|
48
|
-
this.definition = {
|
|
49
|
-
...definition.apis,
|
|
50
|
-
...definition.components,
|
|
51
|
-
[this.canIUse]: '*'
|
|
52
|
-
}
|
|
53
|
-
this.bindingName = bindingName
|
|
54
|
-
this.packageName = packageName
|
|
55
|
-
this.canIUse = 'canIUse'
|
|
56
|
-
if (apis.size < 1) {
|
|
57
|
-
apis.add(this.canIUse)
|
|
58
|
-
Object.keys(definition.apis || {}).forEach(key => apis.add(key))
|
|
59
|
-
}
|
|
60
|
-
this.apis = apis
|
|
61
|
-
},
|
|
62
15
|
visitor: {
|
|
63
|
-
ImportDeclaration (ast) {
|
|
64
|
-
|
|
16
|
+
ImportDeclaration (ast, state) {
|
|
17
|
+
const packageName = state.opts.packageName
|
|
18
|
+
const apis = state.opts.apis
|
|
19
|
+
if (ast.node.source.value !== packageName) return
|
|
65
20
|
|
|
66
21
|
ast.node.specifiers.forEach(node => {
|
|
67
22
|
if (t.isImportDefaultSpecifier(node)) {
|
|
68
23
|
needDefault = true
|
|
69
24
|
taroName = node.local.name
|
|
70
25
|
} else if (t.isImportSpecifier(node)) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
if (this.apis.has(propertyName)) { // 记录api名字
|
|
26
|
+
const propertyName = node.imported.name
|
|
27
|
+
if (apis.has(propertyName)) { // 记录api名字
|
|
74
28
|
ast.scope.rename(node.local.name)
|
|
75
29
|
invokedApis.set(propertyName, node.local.name)
|
|
76
30
|
} else { // 如果是未实现的api 改成Taro.xxx
|
|
@@ -91,8 +45,9 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
91
45
|
}
|
|
92
46
|
})
|
|
93
47
|
},
|
|
94
|
-
MemberExpression (ast) {
|
|
48
|
+
MemberExpression (ast, state) {
|
|
95
49
|
/* 处理Taro.xxx */
|
|
50
|
+
const apis = state.opts.apis
|
|
96
51
|
const isTaro = t.isIdentifier(ast.node.object, { name: taroName })
|
|
97
52
|
const property = ast.node.property
|
|
98
53
|
let propertyName: string | null = null
|
|
@@ -109,12 +64,12 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
109
64
|
if (!propertyName) return
|
|
110
65
|
|
|
111
66
|
// 同一api使用多次, 读取变量名
|
|
112
|
-
if (
|
|
67
|
+
if (apis.has(propertyName)) {
|
|
113
68
|
const parentNode = ast.parent
|
|
114
69
|
const isAssignment = t.isAssignmentExpression(parentNode) && parentNode.left === ast.node
|
|
115
70
|
|
|
116
71
|
if (!isAssignment) {
|
|
117
|
-
let identifier:
|
|
72
|
+
let identifier: any
|
|
118
73
|
if (invokedApis.has(propertyName)) {
|
|
119
74
|
identifier = t.identifier(invokedApis.get(propertyName)!)
|
|
120
75
|
} else {
|
|
@@ -129,41 +84,17 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
129
84
|
needDefault = true
|
|
130
85
|
}
|
|
131
86
|
},
|
|
132
|
-
CallExpression (ast) {
|
|
133
|
-
if (!ast.scope.hasReference(this.canIUse)) return
|
|
134
|
-
const callee = ast.node.callee
|
|
135
|
-
if (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: taroName })) {
|
|
136
|
-
let propertyName: string | null = null
|
|
137
|
-
let propName = 'name'
|
|
138
|
-
|
|
139
|
-
// 兼容一下 Taro['xxx']
|
|
140
|
-
if (t.isStringLiteral(callee.property)) {
|
|
141
|
-
propName = 'value'
|
|
142
|
-
}
|
|
143
|
-
propertyName = callee.property[propName]
|
|
144
|
-
if (propertyName === this.canIUse) {
|
|
145
|
-
// Taro.canIUse or Taro['canIUse']
|
|
146
|
-
replaceCanIUse(ast, this.definition)
|
|
147
|
-
}
|
|
148
|
-
} else if (invokedApis.has(this.canIUse)) {
|
|
149
|
-
const { name } = t.identifier(invokedApis.get(this.canIUse)!)
|
|
150
|
-
const isCanIUse = t.isIdentifier(callee, { name })
|
|
151
|
-
// canIUse as _canIUse
|
|
152
|
-
if (isCanIUse) replaceCanIUse(ast, this.definition)
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
87
|
Program: {
|
|
156
88
|
enter (ast) {
|
|
157
89
|
needDefault = false
|
|
158
90
|
referTaro = []
|
|
159
91
|
invokedApis.clear()
|
|
160
92
|
|
|
161
|
-
taroName = ast.scope.getBinding(
|
|
162
|
-
? ast.scope.generateUid(
|
|
163
|
-
:
|
|
93
|
+
taroName = ast.scope.getBinding('Taro')
|
|
94
|
+
? ast.scope.generateUid('Taro')
|
|
95
|
+
: 'Taro'
|
|
164
96
|
},
|
|
165
|
-
exit (ast) {
|
|
166
|
-
const that = this
|
|
97
|
+
exit (ast, state) {
|
|
167
98
|
// 防止重复引入
|
|
168
99
|
let isTaroApiImported = false
|
|
169
100
|
referTaro.forEach(node => {
|
|
@@ -172,7 +103,8 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
172
103
|
|
|
173
104
|
ast.traverse({
|
|
174
105
|
ImportDeclaration (ast) {
|
|
175
|
-
const
|
|
106
|
+
const packageName = state.opts.packageName
|
|
107
|
+
const isImportingTaroApi = ast.node.source.value === packageName
|
|
176
108
|
if (!isImportingTaroApi) return
|
|
177
109
|
if (isTaroApiImported) return ast.remove()
|
|
178
110
|
isTaroApiImported = true
|
|
@@ -187,22 +119,11 @@ const plugin = function (babel: typeof BabelCore): BabelCore.PluginObj<IState> {
|
|
|
187
119
|
} else {
|
|
188
120
|
ast.node.specifiers = namedImports
|
|
189
121
|
}
|
|
190
|
-
}
|
|
191
|
-
CallExpression (ast) {
|
|
192
|
-
if (!invokedApis.has(that.canIUse)) return
|
|
193
|
-
const callee = ast.node.callee
|
|
194
|
-
const { name } = t.identifier(invokedApis.get(that.canIUse)!)
|
|
195
|
-
const isCanIUse = t.isIdentifier(callee, { name })
|
|
196
|
-
if (isCanIUse) {
|
|
197
|
-
// canIUse as _use
|
|
198
|
-
replaceCanIUse(ast, that.definition)
|
|
199
|
-
}
|
|
200
|
-
},
|
|
122
|
+
}
|
|
201
123
|
})
|
|
202
124
|
}
|
|
203
125
|
}
|
|
204
126
|
}
|
|
205
127
|
}
|
|
206
128
|
}
|
|
207
|
-
|
|
208
129
|
export default plugin
|