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.
@@ -1,47 +1,17 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`babel-plugin-transform-taroapi should canIUse support! 1`] = `
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[`babel-plugin-transform-taroapi should move static apis under "Taro" 1`] = `
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[`babel-plugin-transform-taroapi should not go wrong when using an api twice 1`] = `
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[`babel-plugin-transform-taroapi should not import taro duplicity 1`] = `
57
- "import Taro, { createAnimation as _createAnimation, initPxTransform as _initPxTransform } from '@tarojs/taro-h5';
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[`babel-plugin-transform-taroapi should preserve assignments in left hands 1`] = `
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[`babel-plugin-transform-taroapi should preserve default imports 1`] = `
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[`babel-plugin-transform-taroapi should support rename of imported names 1`] = `
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 '@tarojs/taro-h5';
54
+ import Taro from "@tarojs/taro-h5";
85
55
  export class Connected extends Taro.Component {}"
86
56
  `;
87
57
 
88
- exports[`babel-plugin-transform-taroapi should work! 1`] = `
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();
@@ -1,17 +1,16 @@
1
1
  import * as babel from '@babel/core'
2
2
  import * as t from '@babel/types'
3
- import * as definition from '@tarojs/plugin-platform-h5/dist/definition.json'
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
- packageName,
14
- definition,
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
- const ast = result?.ast as t.File
51
- const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement]
52
- expect(t.isImportDeclaration(body[0])).toBeTruthy()
53
- expect(t.isExpressionStatement(body[1])).toBeTruthy()
54
- const defaultImport = body[0].specifiers.find(v => t.isImportDefaultSpecifier(v)) as ImportType
55
- expect(defaultImport).toBeTruthy()
56
-
57
- const taroName = defaultImport.local.name
58
- const namedImports = getNamedImports(body[0].specifiers)
59
- expect(namedImports).toEqual(new Set())
60
- expect(t.isMemberExpression(body[1].expression)).toBeTruthy()
61
-
62
- const obj = t.memberExpression(
63
- t.identifier(taroName),
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
- const ast = result?.ast as t.File
82
- const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement]
83
- expect(t.isImportDeclaration(body[0])).toBeTruthy()
84
- expect(t.isExpressionStatement(body[1])).toBeTruthy()
85
- const defaultImport = body[0].specifiers.find(v => t.isImportDefaultSpecifier(v))
86
- expect(defaultImport).toBeTruthy()
87
-
88
- const taroName = defaultImport!.local.name
89
- let memberExpression: any = body[1].expression
90
- if (t.isCallExpression(body[1])) {
91
- memberExpression = ((body[1] as t.ExpressionStatement).expression as t.CallExpression).callee
92
- }
93
- expect(memberExpression).toMatchObject(t.memberExpression(
94
- t.identifier(taroName),
95
- t.identifier('noop')
96
- ))
97
- })
98
-
99
- test.skip('should not import taro duplicity', function () {
100
- const code = `
101
- import { Component } from '${packageName}';
102
- import Taro from '${packageName}';
103
- Component
104
- Taro.createAnimation()
105
- Taro.initPxTransform()
106
- `
107
-
108
- const result = babelTransform(code)
109
- expect(result?.code).toMatchSnapshot()
110
- const ast = result?.ast as t.File
111
- const body = ast.program.body as [t.ImportDeclaration, t.ExpressionStatement, t.ExpressionStatement]
112
- expect(t.isImportDeclaration(body[0])).toBeTruthy()
113
- expect(t.isExpressionStatement(body[1])).toBeTruthy()
114
- expect(t.isExpressionStatement(body[2])).toBeTruthy()
115
- })
116
-
117
- test.skip('should not go wrong when using an api twice', function () {
118
- const code = `
119
- import Taro from '${packageName}';
120
- const animation = Taro.createAnimation({
121
- duration: dura * 1000,
122
- timingFunction: 'linear'
123
- })
124
- const resetAnimation = Taro.createAnimation({
125
- duration: 0,
126
- timingFunction: 'linear'
127
- })
128
- `
129
- expect(() => {
130
- const result = babelTransform(code)
131
- expect(result?.code).toMatchSnapshot()
132
- }).not.toThrowError()
133
- })
134
-
135
- test.skip('should preserve default imports', function () {
136
- const code = `
137
- import Taro from '${packageName}'
138
- console.log(Taro)
139
- `
140
- const result = babelTransform(code)
141
- expect(result?.code).toMatchSnapshot()
142
- })
143
-
144
- test.skip('should preserve assignments in left hands', function () {
145
- const code = `
146
- import Taro from '${packageName}'
147
- let animation
148
- animation = Taro.createAnimation({
149
- transformOrigin: "50% 50%",
150
- duration: 1000,
151
- timingFunction: "ease",
152
- delay: 0
153
- });
154
- Taro.request()
155
- Taro.request = ''
156
- Taro['request'] = ''
157
- `
158
- const result = babelTransform(code)
159
- expect(result?.code).toMatchSnapshot()
160
- })
161
-
162
- test.skip('should support rename of imported names', function () {
163
- const code = `
164
- // import { inject as mobxInject, observer as mobxObserver } from '@tarojs/mobx'
165
- import { Component as TaroComponent } from '${packageName}';
166
- export class Connected extends TaroComponent {}
167
- `
168
- const result = babelTransform(code)
169
- expect(result?.code).toMatchSnapshot()
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
- if (ast.node.source.value !== this.packageName)
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 { imported } = node;
56
- const propertyName = t.isIdentifier(imported) ? imported.name : imported.value;
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 (this.apis.has(propertyName)) {
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(this.bindingName)
142
- ? ast.scope.generateUid(this.bindingName)
143
- : this.bindingName;
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 isImportingTaroApi = ast.node.source.value === that.packageName;
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
- import type { Config } from 'jest'
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
@@ -1,10 +1,7 @@
1
1
  {
2
2
  "name": "babel-plugin-transform-taroapi",
3
- "version": "3.6.6-alpha.3",
3
+ "version": "3.6.7",
4
4
  "main": "dist/index.js",
5
- "dependencies": {
6
- "lodash": "^4.17.21"
7
- },
8
5
  "devDependencies": {
9
6
  "@babel/core": "^7.14.5",
10
7
  "@babel/types": "^7.14.5",
package/src/index.ts CHANGED
@@ -1,16 +1,6 @@
1
- import { isMatchWith, set } from 'lodash'
2
-
3
- import type * as BabelCore from '@babel/core'
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
- if (ast.node.source.value !== this.packageName) return
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 { imported } = node
72
- const propertyName = t.isIdentifier(imported) ? imported.name : imported.value
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 (this.apis.has(propertyName)) {
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: BabelCore.types.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(this.bindingName)
162
- ? ast.scope.generateUid(this.bindingName)
163
- : this.bindingName
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 isImportingTaroApi = ast.node.source.value === that.packageName
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
package/types.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ declare module '@tarojs/taro-h5/dist/taroApis' {
2
+ export const apis: {
3
+ [key: string]: boolean
4
+ }
5
+ }