@oceanbase/codemod 0.2.5 → 0.2.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/README.md +140 -2
- package/bin/cli.js +12 -7
- package/package.json +6 -4
- package/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.input.less +12 -0
- package/transforms/__testfixtures__/less-to-token/antd-v4-less-to-token.output.less +13 -0
- package/transforms/__testfixtures__/less-to-token/obui-less-to-token.input.less +14 -0
- package/transforms/__testfixtures__/less-to-token/obui-less-to-token.output.less +13 -0
- package/transforms/__testfixtures__/obui-to-oceanbase-design-and-ui/locale.input.js +8 -0
- package/transforms/__testfixtures__/obui-to-oceanbase-design-and-ui/locale.output.js +8 -0
- package/transforms/__testfixtures__/obui-to-oceanbase-design-and-ui/obui.input.js +2 -1
- package/transforms/__testfixtures__/obui-to-oceanbase-design-and-ui/obui.output.js +3 -2
- package/transforms/__testfixtures__/style-to-token/class-component.input.js +20 -0
- package/transforms/__testfixtures__/style-to-token/class-component.output.js +20 -0
- package/transforms/__testfixtures__/style-to-token/function-component.input.js +13 -0
- package/transforms/__testfixtures__/style-to-token/function-component.output.js +14 -0
- package/transforms/__testfixtures__/style-to-token/static.input.js +32 -0
- package/transforms/__testfixtures__/style-to-token/static.output.js +33 -0
- package/transforms/__tests__/less-to-token.test.ts +21 -0
- package/transforms/__tests__/obui-to-oceanbase-design-and-ui.test.ts +1 -1
- package/transforms/__tests__/style-to-token.test.ts +10 -0
- package/transforms/less-to-token.js +87 -0
- package/transforms/obui-to-oceanbase-design-and-ui.js +30 -0
- package/transforms/style-to-token.js +77 -0
- package/transforms/utils/config.js +1 -0
- package/transforms/utils/import-component.js +15 -11
- package/transforms/utils/index.js +4 -2
- package/transforms/utils/token.js +62 -0
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# OceanBase Codemod
|
|
2
2
|
|
|
3
|
-
A collection of codemod scripts that help migrate to OceanBase Design using [jscodeshift](https://github.com/facebook/jscodeshift) and [postcss](https://github.com/postcss/postcss).(Inspired by [@
|
|
3
|
+
A collection of codemod scripts that help migrate from `antd`, `@alipay/ob-ui`, `@alipay/tech-ui`, `@ant-design/pro-components` and `@ant-design/charts` to OceanBase Design System by using [jscodeshift](https://github.com/facebook/jscodeshift) and [postcss](https://github.com/postcss/postcss). (Inspired by [@ant-design/codemod-v5](https://github.com/ant-design/codemod-v5))
|
|
4
4
|
|
|
5
|
-
[](https://npmjs.org/package/@oceanbase/codemod) [](https://npmjs.org/package/@oceanbase/codemod) [](https://github.com/oceanbase/design/actions/workflows/ci.yml)
|
|
5
|
+
[](https://npmjs.org/package/@oceanbase/codemod) [](https://npmjs.org/package/@oceanbase/codemod) [](https://github.com/oceanbase/oceanbase-design/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
## Prerequisite
|
|
8
|
+
|
|
9
|
+
- `antd v5` is the prerequisite. If you are using `antd v4`, please refer to [Upgrade Guideline](https://ant-design.antgroup.com/docs/react/migration-v5).
|
|
6
10
|
|
|
7
11
|
## Usage
|
|
8
12
|
|
|
@@ -133,3 +137,137 @@ import utils and hooks from `@alipay/ob-util` to `@oceanbase/util`. Additionally
|
|
|
133
137
|
|
|
134
138
|
export default Demo;
|
|
135
139
|
```
|
|
140
|
+
|
|
141
|
+
### `style-to-token`
|
|
142
|
+
|
|
143
|
+
transform fixed style to antd v5 design token.
|
|
144
|
+
|
|
145
|
+
- React function components:
|
|
146
|
+
|
|
147
|
+
```diff
|
|
148
|
+
import React from 'react';
|
|
149
|
+
- import { Alert, Button } from '@oceanbase/design';
|
|
150
|
+
+ import { Alert, Button, theme } from '@oceanbase/design';
|
|
151
|
+
|
|
152
|
+
const Demo = () => {
|
|
153
|
+
+ const { token } = theme.useToken();
|
|
154
|
+
return (
|
|
155
|
+
- <div>
|
|
156
|
+
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
|
|
157
|
+
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
|
|
158
|
+
- </div>
|
|
159
|
+
+ (<div>
|
|
160
|
+
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
|
|
161
|
+
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
|
|
162
|
+
+ </div>)
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default Demo;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- React class components:
|
|
170
|
+
|
|
171
|
+
```diff
|
|
172
|
+
import React from 'react';
|
|
173
|
+
- import { Alert, Button } from '@oceanbase/design';
|
|
174
|
+
+ import { Alert, Button, token } from '@oceanbase/design';
|
|
175
|
+
|
|
176
|
+
class Demo extends React.PureComponent {
|
|
177
|
+
constructor(props) {
|
|
178
|
+
super(props);
|
|
179
|
+
this.state = {};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
render() {
|
|
183
|
+
return (
|
|
184
|
+
- <div>
|
|
185
|
+
- <Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '#d9d9d9' }} />
|
|
186
|
+
- <Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
|
|
187
|
+
- </div>
|
|
188
|
+
+ (<div>
|
|
189
|
+
+ <Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBgLayout}` }} />
|
|
190
|
+
+ <Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
|
|
191
|
+
+ </div>)
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default Demo;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- Static file (not react components):
|
|
200
|
+
|
|
201
|
+
```diff
|
|
202
|
+
+ import { token } from '@oceanbase/design';
|
|
203
|
+
const colorMap = {
|
|
204
|
+
- info: '#1890ff',
|
|
205
|
+
- success: '#52c41a',
|
|
206
|
+
- warning: '#faad14',
|
|
207
|
+
- error: '#ff4D4F',
|
|
208
|
+
- border: '1px solid #d9d9d9',
|
|
209
|
+
+ info: token.colorInfo,
|
|
210
|
+
+ success: token.colorSuccess,
|
|
211
|
+
+ warning: token.colorWarning,
|
|
212
|
+
+ error: token.colorError,
|
|
213
|
+
+ border: `1px solid ${token.colorBorder}`,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
function getColorList() {
|
|
217
|
+
return [
|
|
218
|
+
{
|
|
219
|
+
type: 'info',
|
|
220
|
+
- color: '#1890ff',
|
|
221
|
+
+ color: token.colorInfo,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
type: 'success',
|
|
225
|
+
- color: '#52c41a',
|
|
226
|
+
+ color: token.colorSuccess,
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
type: 'warning',
|
|
230
|
+
- color: '#faad14',
|
|
231
|
+
+ color: token.colorWarning,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
type: 'error',
|
|
235
|
+
- color: '#ff4D4F',
|
|
236
|
+
+ color: token.colorError,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
type: 'border',
|
|
240
|
+
- color: '1px solid #d9d9d9',
|
|
241
|
+
+ color: `1px solid ${token.colorBorder}`,
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### `less-to-token`
|
|
248
|
+
|
|
249
|
+
transform fixed less style to antd v5 design token.
|
|
250
|
+
|
|
251
|
+
```diff
|
|
252
|
+
+ @import '~@oceanbase/design/es/theme/index.less';
|
|
253
|
+
.container {
|
|
254
|
+
- color: #1890ff;
|
|
255
|
+
- background: #52c41a;
|
|
256
|
+
- background-color: #faad14;
|
|
257
|
+
- border-color: #ff4D4F;
|
|
258
|
+
+ color: @colorInfo;
|
|
259
|
+
+ background: @colorSuccess;
|
|
260
|
+
+ background-color: @colorWarning;
|
|
261
|
+
+ border-color: @colorError;
|
|
262
|
+
.content {
|
|
263
|
+
- color: rgba(0, 0, 0, 0.85);
|
|
264
|
+
- background: rgba(0, 0, 0,0.65);
|
|
265
|
+
- background-color: rgba(0,0,0,0.45);
|
|
266
|
+
- border: 1px solid #d9d9d9;
|
|
267
|
+
+ color: @colorText;
|
|
268
|
+
+ background: @colorTextSecondary;
|
|
269
|
+
+ background-color: @colorTextTertiary;
|
|
270
|
+
+ border: 1px solid @colorBorder;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
package/bin/cli.js
CHANGED
|
@@ -8,7 +8,6 @@ const _ = require('lodash');
|
|
|
8
8
|
const chalk = require('chalk');
|
|
9
9
|
const isGitClean = require('is-git-clean');
|
|
10
10
|
const updateCheck = require('update-check');
|
|
11
|
-
const findUp = require('find-up');
|
|
12
11
|
const semver = require('semver');
|
|
13
12
|
const { run: jscodeshift } = require('jscodeshift/src/Runner');
|
|
14
13
|
const execa = require('execa');
|
|
@@ -18,6 +17,7 @@ const commandExistsSync = require('command-exists').sync;
|
|
|
18
17
|
const pkg = require('../package.json');
|
|
19
18
|
const pkgUpgradeList = require('./upgrade-list');
|
|
20
19
|
const { getDependencies } = require('../transforms/utils/marker');
|
|
20
|
+
const { lessToToken } = require('../transforms/less-to-token');
|
|
21
21
|
|
|
22
22
|
// jscodeshift codemod scripts dir
|
|
23
23
|
const transformersDir = path.join(__dirname, '../transforms');
|
|
@@ -31,6 +31,8 @@ const transformers = [
|
|
|
31
31
|
'obui-to-oceanbase-design-and-ui',
|
|
32
32
|
'obutil-to-oceanbase-util',
|
|
33
33
|
'page-container-to-oceanbase-ui',
|
|
34
|
+
'style-to-token',
|
|
35
|
+
'less-to-token',
|
|
34
36
|
];
|
|
35
37
|
|
|
36
38
|
const dependencyProperties = [
|
|
@@ -113,12 +115,15 @@ async function transform(transformer, parser, filePath, options) {
|
|
|
113
115
|
});
|
|
114
116
|
|
|
115
117
|
try {
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
+
if (transformer === 'less-to-token') {
|
|
119
|
+
await lessToToken(filePath);
|
|
120
|
+
} else {
|
|
121
|
+
if (process.env.NODE_ENV === 'local') {
|
|
122
|
+
console.log(`Running jscodeshift with: ${JSON.stringify(args)}`);
|
|
123
|
+
}
|
|
124
|
+
// js part
|
|
125
|
+
await jscodeshift(transformerPath, [filePath], args);
|
|
118
126
|
}
|
|
119
|
-
|
|
120
|
-
// js part
|
|
121
|
-
await jscodeshift(transformerPath, [filePath], args);
|
|
122
127
|
console.log();
|
|
123
128
|
} catch (err) {
|
|
124
129
|
console.error(err);
|
|
@@ -286,7 +291,7 @@ async function bootstrap() {
|
|
|
286
291
|
console.log('[Prettier] format files running...');
|
|
287
292
|
try {
|
|
288
293
|
const isDir = isDirectory.sync(dir);
|
|
289
|
-
const path = isDir ? '**/*.{js,jsx,tsx,
|
|
294
|
+
const path = isDir ? path.join(dir, '**/*.{js,jsx,ts,tsx,d.ts}') : dir;
|
|
290
295
|
const npxCommand = commandExistsSync('tnpx') ? 'tnpx' : 'npx';
|
|
291
296
|
await execa(npxCommand, ['prettier', '--write', path], { stdio: 'inherit' });
|
|
292
297
|
console.log('\n[Prettier] format files completed!\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oceanbase/codemod",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Codemod for OceanBase Design upgrade",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oceanbase",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://github.com/oceanbase/oceanbase-design/packages/codemod",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "git@github.com:oceanbase/design.git"
|
|
13
|
+
"url": "git@github.com:oceanbase/oceanbase-design.git"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"registry": "https://registry.npmjs.org",
|
|
@@ -32,8 +32,10 @@
|
|
|
32
32
|
"is-git-clean": "^1.1.0",
|
|
33
33
|
"jscodeshift": "^0.15.0",
|
|
34
34
|
"lodash": "^4.17.21",
|
|
35
|
+
"postcss": "^8.4.31",
|
|
36
|
+
"postcss-less": "^6.0.0",
|
|
35
37
|
"prettier": "^3.0.3",
|
|
36
|
-
"read-pkg-up": "^
|
|
38
|
+
"read-pkg-up": "^10.1.0",
|
|
37
39
|
"semver": "^7.5.4",
|
|
38
40
|
"update-check": "^1.5.4",
|
|
39
41
|
"yargs-parser": "^21.1.1"
|
|
@@ -44,5 +46,5 @@
|
|
|
44
46
|
"enzyme": "^3.11.0",
|
|
45
47
|
"enzyme-to-json": "^3.6.2"
|
|
46
48
|
},
|
|
47
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "641619d79cb7980279179b21905141950c604c54"
|
|
48
50
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
color: #1890ff;
|
|
3
|
+
background: #52c41a;
|
|
4
|
+
background-color: #faad14;
|
|
5
|
+
border-color: #ff4D4F;
|
|
6
|
+
.content {
|
|
7
|
+
color: rgba(0, 0, 0, 0.85);
|
|
8
|
+
background: rgba(0, 0, 0,0.65);
|
|
9
|
+
background-color: rgba(0,0,0,0.45);
|
|
10
|
+
border: 1px solid #d9d9d9;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@import '~@oceanbase/design/es/theme/index.less';
|
|
2
|
+
.container {
|
|
3
|
+
color: @colorInfo;
|
|
4
|
+
background: @colorSuccess;
|
|
5
|
+
background-color: @colorWarning;
|
|
6
|
+
border-color: @colorError;
|
|
7
|
+
.content {
|
|
8
|
+
color: @colorText;
|
|
9
|
+
background: @colorTextSecondary;
|
|
10
|
+
background-color: @colorTextTertiary;
|
|
11
|
+
border: 1px solid @colorBorder;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
@import '~@alipay/ob-ui/es/theme/index.less';
|
|
2
|
+
|
|
3
|
+
.container {
|
|
4
|
+
color: @colorInfo;
|
|
5
|
+
background: @colorSuccess;
|
|
6
|
+
background-color: @colorWarning;
|
|
7
|
+
border-color: @colorError;
|
|
8
|
+
.content {
|
|
9
|
+
color: rgba(0, 0, 0, 0.85);
|
|
10
|
+
background: rgba(0, 0, 0,0.65);
|
|
11
|
+
background-color: rgba(0,0,0,0.45);
|
|
12
|
+
border: 1px solid #d9d9d9;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@import '~@oceanbase/design/es/theme/index.less';
|
|
2
|
+
.container {
|
|
3
|
+
color: @colorInfo;
|
|
4
|
+
background: @colorSuccess;
|
|
5
|
+
background-color: @colorWarning;
|
|
6
|
+
border-color: @colorError;
|
|
7
|
+
.content {
|
|
8
|
+
color: @colorText;
|
|
9
|
+
background: @colorTextSecondary;
|
|
10
|
+
background-color: @colorTextTertiary;
|
|
11
|
+
border: 1px solid @colorBorder;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Alert, Button, BasicLayout, Login, PageContainer } from '@alipay/ob-ui';
|
|
2
|
+
import { Alert, Button, BackgroundTaskManager, BackgroundTaskManagerConstants, BasicLayout, Boundary, ConfigProvider, ContentWithQuestion, IconFont, Login, PageContainer, Ranger, theme, TreeSearch } from '@alipay/ob-ui';
|
|
3
|
+
import type { BackgroundTaskManagerRef, ITaskMgrPreset, ITaskMgrQueue, TaskMgrID } from '@alipay/ob-ui';
|
|
3
4
|
import type { BasicLayoutProps } from '@alipay/ob-ui/es/BasicLayout';
|
|
4
5
|
import type { LoginProps } from '@alipay/ob-ui/es/Login';
|
|
5
6
|
import type { PageContainerProps } from '@alipay/ob-ui/es/PageContainer';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Alert, Button } from '@oceanbase/design';
|
|
3
|
-
import { BasicLayout, Login, PageContainer } from '@oceanbase/ui';
|
|
2
|
+
import { Alert, Button, ConfigProvider, theme } from '@oceanbase/design';
|
|
3
|
+
import { BackgroundTaskManager, BackgroundTaskManagerConstants, BasicLayout, Boundary, ContentWithQuestion, IconFont, Login, PageContainer, Ranger, TreeSearch } from '@oceanbase/ui';
|
|
4
|
+
import type { BackgroundTaskManagerRef, ITaskMgrPreset, ITaskMgrQueue, TaskMgrID } from '@oceanbase/ui';
|
|
4
5
|
import type { BasicLayoutProps } from '@oceanbase/ui/es/BasicLayout';
|
|
5
6
|
import type { LoginProps } from '@oceanbase/ui/es/Login';
|
|
6
7
|
import type { PageContainerProps } from '@oceanbase/ui/es/PageContainer';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert, Button } from '@oceanbase/design';
|
|
3
|
+
|
|
4
|
+
class Demo extends React.PureComponent {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props);
|
|
7
|
+
this.state = {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
render() {
|
|
11
|
+
return (
|
|
12
|
+
<div>
|
|
13
|
+
<Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
|
|
14
|
+
<Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Demo;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert, Button, token } from '@oceanbase/design';
|
|
3
|
+
|
|
4
|
+
class Demo extends React.PureComponent {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props);
|
|
7
|
+
this.state = {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
render() {
|
|
11
|
+
return (
|
|
12
|
+
(<div>
|
|
13
|
+
<Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
|
|
14
|
+
<Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
|
|
15
|
+
</div>)
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Demo;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert, Button } from '@oceanbase/design';
|
|
3
|
+
|
|
4
|
+
const Demo = () => {
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<Alert style={{ color: 'rgba(0, 0, 0, 0.85)', background: 'rgba(0, 0, 0,0.65)', backgroundColor: 'rgba(0,0,0,0.45)', border: '1px solid #d9d9d9' }} />
|
|
8
|
+
<Button style={{ color: '#1890ff', background: '#52c41a', backgroundColor: '#faad14', borderColor: '#ff4D4F' }}></Button>
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default Demo;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert, Button, theme } from '@oceanbase/design';
|
|
3
|
+
|
|
4
|
+
const Demo = () => {
|
|
5
|
+
const { token } = theme.useToken();
|
|
6
|
+
return (
|
|
7
|
+
(<div>
|
|
8
|
+
<Alert style={{ color: token.colorText, background: token.colorTextSecondary, backgroundColor: token.colorTextTertiary, border: `1px solid ${token.colorBorder}` }} />
|
|
9
|
+
<Button style={{ color: token.colorInfo, background: token.colorSuccess, backgroundColor: token.colorWarning, borderColor: token.colorError }}></Button>
|
|
10
|
+
</div>)
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default Demo;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const colorMap = {
|
|
2
|
+
info: '#1890ff',
|
|
3
|
+
success: '#52c41a',
|
|
4
|
+
warning: '#faad14',
|
|
5
|
+
error: '#ff4D4F',
|
|
6
|
+
border: '1px solid #d9d9d9',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function getColorList() {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
type: 'info',
|
|
13
|
+
color: '#1890ff',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: 'success',
|
|
17
|
+
color: '#52c41a',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'warning',
|
|
21
|
+
color: '#faad14',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'error',
|
|
25
|
+
color: '#ff4D4F',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'border',
|
|
29
|
+
color: '1px solid #d9d9d9',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { token } from '@oceanbase/design';
|
|
2
|
+
const colorMap = {
|
|
3
|
+
info: token.colorInfo,
|
|
4
|
+
success: token.colorSuccess,
|
|
5
|
+
warning: token.colorWarning,
|
|
6
|
+
error: token.colorError,
|
|
7
|
+
border: `1px solid ${token.colorBorder}`,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function getColorList() {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
type: 'info',
|
|
14
|
+
color: token.colorInfo,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'success',
|
|
18
|
+
color: token.colorSuccess,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: 'warning',
|
|
22
|
+
color: token.colorWarning,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'error',
|
|
26
|
+
color: token.colorError,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'border',
|
|
30
|
+
color: `1px solid ${token.colorBorder}`,
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { transform } from '../less-to-token';
|
|
4
|
+
|
|
5
|
+
const testUnit = 'less-to-token';
|
|
6
|
+
const tests = ['antd-v4-less-to-token', 'obui-less-to-token'];
|
|
7
|
+
|
|
8
|
+
describe(testUnit, () => {
|
|
9
|
+
tests.forEach(test => {
|
|
10
|
+
it(test, async () => {
|
|
11
|
+
const result = await transform(
|
|
12
|
+
path.join(__dirname, `../__testfixtures__/less-to-token/${test}.input.less`)
|
|
13
|
+
);
|
|
14
|
+
const output = fs.readFileSync(
|
|
15
|
+
path.join(__dirname, `../__testfixtures__/less-to-token/${test}.output.less`),
|
|
16
|
+
'utf-8'
|
|
17
|
+
);
|
|
18
|
+
expect(result).toEqual(output);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineTest } from 'jscodeshift/src/testUtils';
|
|
2
|
+
|
|
3
|
+
const testUnit = 'style-to-token';
|
|
4
|
+
const tests = ['function-component', 'class-component', 'static'];
|
|
5
|
+
|
|
6
|
+
describe(testUnit, () => {
|
|
7
|
+
tests.forEach(test =>
|
|
8
|
+
defineTest(__dirname, testUnit, {}, `${testUnit}/${test}`, { parser: 'babylon' })
|
|
9
|
+
);
|
|
10
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const postcss = require('postcss');
|
|
4
|
+
const postcssLess = require('postcss-less');
|
|
5
|
+
const isDirectory = require('is-directory');
|
|
6
|
+
const { tokenParse } = require('./utils/token');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 搜索目录下所有的less文件
|
|
10
|
+
* @param dir
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
const findAllLessFiles = dir => {
|
|
14
|
+
const lessFiles = [];
|
|
15
|
+
const isDir = isDirectory.sync(dir);
|
|
16
|
+
if (isDir) {
|
|
17
|
+
const files = fs.readdirSync(dir);
|
|
18
|
+
files.forEach(file => {
|
|
19
|
+
const filePath = path.join(dir, file);
|
|
20
|
+
if (isDirectory.sync(filePath)) {
|
|
21
|
+
if (filePath.includes('.umi')) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
lessFiles.push(...findAllLessFiles(filePath));
|
|
25
|
+
} else if (file.endsWith('.less')) {
|
|
26
|
+
lessFiles.push(filePath);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
lessFiles.push(dir);
|
|
31
|
+
}
|
|
32
|
+
return lessFiles;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 将 lesscode 转化为 ast
|
|
37
|
+
* @returns ASR
|
|
38
|
+
*/
|
|
39
|
+
const less2AST = code =>
|
|
40
|
+
postcss([])
|
|
41
|
+
.process(code, {
|
|
42
|
+
parser: postcssLess.parse,
|
|
43
|
+
from: undefined,
|
|
44
|
+
})
|
|
45
|
+
.then(result => result.root);
|
|
46
|
+
|
|
47
|
+
async function transform(file) {
|
|
48
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
49
|
+
const ast = await less2AST(content);
|
|
50
|
+
let modified = false;
|
|
51
|
+
let tokenLessImported = false;
|
|
52
|
+
// 遍历 AST
|
|
53
|
+
ast.walk(node => {
|
|
54
|
+
const { key, token, formattedValue } = tokenParse(node.value);
|
|
55
|
+
if (node.type === 'decl' && token) {
|
|
56
|
+
node.value = formattedValue.replace(key, `@${token}`);
|
|
57
|
+
modified = true;
|
|
58
|
+
} else if (node.type === 'atrule' && node.name === 'import') {
|
|
59
|
+
if (node.params === "'~@oceanbase/design/es/theme/index.less'") {
|
|
60
|
+
tokenLessImported = true;
|
|
61
|
+
} else if (node.params === "'~@alipay/ob-ui/es/theme/index.less'") {
|
|
62
|
+
node.remove();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// prepend @import '~@oceanbase/design/es/theme/index.less';
|
|
67
|
+
if (modified && !tokenLessImported) {
|
|
68
|
+
ast.prepend({
|
|
69
|
+
name: 'import',
|
|
70
|
+
params: "'~@oceanbase/design/es/theme/index.less'",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return ast.toString();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function lessToToken(file) {
|
|
77
|
+
const allLessFiles = findAllLessFiles(file);
|
|
78
|
+
for await (const item of allLessFiles) {
|
|
79
|
+
const content = await transform(item);
|
|
80
|
+
fs.writeFileSync(file, content);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = {
|
|
85
|
+
transform,
|
|
86
|
+
lessToToken,
|
|
87
|
+
};
|
|
@@ -12,32 +12,62 @@ module.exports = (file, api, options) => {
|
|
|
12
12
|
'PageContainer',
|
|
13
13
|
'Action',
|
|
14
14
|
'BackgroundTaskManager',
|
|
15
|
+
'BackgroundTaskManagerConstants',
|
|
15
16
|
'BasicLayout',
|
|
16
17
|
'BatchOperationBar',
|
|
17
18
|
'Boundary',
|
|
18
19
|
'ContentWithQuestion',
|
|
19
20
|
'Dialog',
|
|
20
21
|
'DocDialog',
|
|
22
|
+
'FullscreenBox',
|
|
23
|
+
'Highlight',
|
|
21
24
|
'GraphToolbar',
|
|
25
|
+
'IconFont',
|
|
22
26
|
'Login',
|
|
23
27
|
'Lottie',
|
|
24
28
|
'NavMenu',
|
|
29
|
+
'Password',
|
|
30
|
+
'Ranger',
|
|
31
|
+
'SideTip',
|
|
32
|
+
'TaskGraph',
|
|
33
|
+
'TreeSearch',
|
|
34
|
+
'Welcome',
|
|
25
35
|
],
|
|
26
36
|
types: [
|
|
27
37
|
'PageContainerProps',
|
|
28
38
|
'ActionProps',
|
|
39
|
+
// BackgroundTaskManager
|
|
29
40
|
'BackgroundTaskManagerProps',
|
|
41
|
+
'BackgroundTaskManagerRef',
|
|
42
|
+
'ITaskMgrPreset',
|
|
43
|
+
'ITaskMgrQueue',
|
|
44
|
+
'TaskMgrID',
|
|
30
45
|
'BasicLayoutProps',
|
|
31
46
|
'BatchOperationBarProps',
|
|
32
47
|
'BoundaryProps',
|
|
33
48
|
'ContentWithQuestionProps',
|
|
34
49
|
'DialogProps',
|
|
35
50
|
'DocDialogProps',
|
|
51
|
+
'FullscreenBoxProps',
|
|
36
52
|
'GraphToolbarProps',
|
|
53
|
+
'HighlightProps',
|
|
54
|
+
'IconFontProps',
|
|
37
55
|
'LoginProps',
|
|
38
56
|
'LottieProps',
|
|
39
57
|
'NavMenuProps',
|
|
58
|
+
'PasswordProps',
|
|
59
|
+
// Ranger
|
|
60
|
+
'RangerProps',
|
|
61
|
+
'QuickPickerProps',
|
|
62
|
+
'SideTipProps',
|
|
63
|
+
'TaskGraphProps',
|
|
64
|
+
// TreeSearch
|
|
65
|
+
'TreeSearchProps',
|
|
66
|
+
'TreeSearchRef',
|
|
67
|
+
'Node',
|
|
68
|
+
'WelcomeProps',
|
|
40
69
|
],
|
|
70
|
+
paths: ['/locale/', '/locale/'],
|
|
41
71
|
},
|
|
42
72
|
{
|
|
43
73
|
name: '@oceanbase/design',
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { addSubmoduleImport } = require('./utils');
|
|
2
|
+
const { tokenParse } = require('./utils/token');
|
|
3
|
+
const { printOptions } = require('./utils/config');
|
|
4
|
+
|
|
5
|
+
function importComponent(j, root, options) {
|
|
6
|
+
let hasChanged = false;
|
|
7
|
+
|
|
8
|
+
const stringList = root.find(j.StringLiteral, {
|
|
9
|
+
value: value => {
|
|
10
|
+
const { token } = tokenParse(value);
|
|
11
|
+
return !!token;
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
if (stringList.length > 0) {
|
|
15
|
+
// replace fixed style to token
|
|
16
|
+
stringList.replaceWith(path => {
|
|
17
|
+
hasChanged = true;
|
|
18
|
+
const { key, token, formattedValue } = tokenParse(path.value.value);
|
|
19
|
+
return formattedValue === key
|
|
20
|
+
? j.identifier(`token.${token}`)
|
|
21
|
+
: j.templateLiteral(
|
|
22
|
+
[
|
|
23
|
+
j.templateElement(
|
|
24
|
+
{
|
|
25
|
+
raw: formattedValue.replace(key, `\${token.${token}}`),
|
|
26
|
+
cooked: formattedValue.replace(key, `\${token.${token}}`),
|
|
27
|
+
},
|
|
28
|
+
true
|
|
29
|
+
),
|
|
30
|
+
],
|
|
31
|
+
[]
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
root.find(j.BlockStatement).forEach(path => {
|
|
36
|
+
const includeToken =
|
|
37
|
+
j(path).find(j.Identifier, {
|
|
38
|
+
name: name => name?.includes('token.'),
|
|
39
|
+
}).length > 0;
|
|
40
|
+
if (includeToken) {
|
|
41
|
+
const includeJsxElementList = j(path).find(j.JSXElement).length > 0;
|
|
42
|
+
const parentType = path.parentPath.value?.type;
|
|
43
|
+
// React function component
|
|
44
|
+
if (includeJsxElementList && parentType !== 'ClassMethod') {
|
|
45
|
+
const importString = `const { token } = theme.useToken()`;
|
|
46
|
+
path.get('body').value.unshift(j.expressionStatement(j.identifier(importString)));
|
|
47
|
+
// import theme from @oceanbase/design
|
|
48
|
+
addSubmoduleImport(j, root, {
|
|
49
|
+
moduleName: '@oceanbase/design',
|
|
50
|
+
importedName: 'theme',
|
|
51
|
+
importKind: 'value',
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
// React class component and static file (not react component)
|
|
55
|
+
// import token from @oceanbase/design
|
|
56
|
+
addSubmoduleImport(j, root, {
|
|
57
|
+
moduleName: '@oceanbase/design',
|
|
58
|
+
importedName: 'token',
|
|
59
|
+
importKind: 'value',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return hasChanged;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = (file, api, options) => {
|
|
70
|
+
const j = api.jscodeshift;
|
|
71
|
+
const root = j(file.source);
|
|
72
|
+
|
|
73
|
+
let hasChanged = false;
|
|
74
|
+
hasChanged = importComponent(j, root, options) || hasChanged;
|
|
75
|
+
|
|
76
|
+
return hasChanged ? root.toSource(options.printOptions || printOptions) : null;
|
|
77
|
+
};
|
|
@@ -3,6 +3,7 @@ const { markDependency } = require('./marker');
|
|
|
3
3
|
const { printOptions } = require('./config');
|
|
4
4
|
const { isPlainObject } = require('lodash');
|
|
5
5
|
const { flatten } = require('lodash');
|
|
6
|
+
const { some } = require('lodash');
|
|
6
7
|
|
|
7
8
|
function importComponent(j, root, options) {
|
|
8
9
|
const { fromPkgNames, toPkgList } = options;
|
|
@@ -19,15 +20,18 @@ function importComponent(j, root, options) {
|
|
|
19
20
|
path.value.specifiers.forEach(specifier => {
|
|
20
21
|
const toPkgByComponents = toPkgList.find(
|
|
21
22
|
toPkg =>
|
|
22
|
-
toPkg.components?.includes(specifier.imported
|
|
23
|
-
toPkg.components?.find(component => component[specifier.imported
|
|
23
|
+
toPkg.components?.includes(specifier.imported?.name) ||
|
|
24
|
+
toPkg.components?.find(component => component[specifier.imported?.name])
|
|
24
25
|
);
|
|
25
26
|
const toPkgByTypes = toPkgList.find(
|
|
26
27
|
toPkg =>
|
|
27
|
-
toPkg.types?.includes(specifier.imported
|
|
28
|
-
toPkg.types?.find(type => type[specifier.imported
|
|
28
|
+
toPkg.types?.includes(specifier.imported?.name) ||
|
|
29
|
+
toPkg.types?.find(type => type[specifier.imported?.name])
|
|
29
30
|
);
|
|
30
|
-
const
|
|
31
|
+
const toPkgByPaths = toPkgList.find(toPkg =>
|
|
32
|
+
some(toPkg.paths, pathString => path.value.source.value?.includes(pathString))
|
|
33
|
+
);
|
|
34
|
+
const toPkg = toPkgByComponents || toPkgByTypes || toPkgByPaths;
|
|
31
35
|
if (toPkg) {
|
|
32
36
|
// replace to toPkg for xxx/es/xxx、xxx/lib/xxx
|
|
33
37
|
if (new RegExp(`${fromPkgName}/(es|lib|locale)/`).test(path.value.source.value)) {
|
|
@@ -35,17 +39,17 @@ function importComponent(j, root, options) {
|
|
|
35
39
|
} else {
|
|
36
40
|
// remove old imports
|
|
37
41
|
path.value.specifiers = path.value.specifiers.filter(
|
|
38
|
-
item => !item.imported || item.imported
|
|
42
|
+
item => !item.imported || item.imported?.name !== specifier.imported?.name
|
|
39
43
|
);
|
|
40
44
|
const renameComponent = toPkg.components?.find(
|
|
41
|
-
component => component[specifier.imported
|
|
45
|
+
component => component[specifier.imported?.name]
|
|
42
46
|
);
|
|
43
|
-
const renameType = toPkg.types?.find(type => type[specifier.imported
|
|
47
|
+
const renameType = toPkg.types?.find(type => type[specifier.imported?.name]);
|
|
44
48
|
const rename = renameComponent || renameType;
|
|
45
49
|
// add and rename new imports
|
|
46
50
|
addSubmoduleImport(j, root, {
|
|
47
51
|
moduleName: toPkg.name,
|
|
48
|
-
importedName: rename ? rename[specifier.imported
|
|
52
|
+
importedName: rename ? rename[specifier.imported?.name] : specifier.imported?.name,
|
|
49
53
|
importKind: toPkgByTypes ? 'type' : 'value',
|
|
50
54
|
after: fromPkgName,
|
|
51
55
|
});
|
|
@@ -53,10 +57,10 @@ function importComponent(j, root, options) {
|
|
|
53
57
|
if (rename) {
|
|
54
58
|
root
|
|
55
59
|
.find(j.Identifier, {
|
|
56
|
-
name: specifier.imported
|
|
60
|
+
name: specifier.imported?.name,
|
|
57
61
|
})
|
|
58
62
|
.forEach(path => {
|
|
59
|
-
path.node.name = rename[specifier.imported
|
|
63
|
+
path.node.name = rename[specifier.imported?.name];
|
|
60
64
|
});
|
|
61
65
|
}
|
|
62
66
|
}
|
|
@@ -138,7 +138,9 @@ function addModuleImport(j, root, { pkgName, importSpecifier, importKind, before
|
|
|
138
138
|
|
|
139
139
|
return a.imported.name.localeCompare(b.imported.name);
|
|
140
140
|
});
|
|
141
|
-
|
|
141
|
+
const importStatement = j.importDeclaration(mergedImportSpecifiers, j.literal(pkgName));
|
|
142
|
+
importStatement.importKind = importKind;
|
|
143
|
+
return importStatement;
|
|
142
144
|
});
|
|
143
145
|
return true;
|
|
144
146
|
}
|
|
@@ -149,7 +151,7 @@ function addModuleImport(j, root, { pkgName, importSpecifier, importKind, before
|
|
|
149
151
|
|
|
150
152
|
if (before) {
|
|
151
153
|
insertImportBefore(j, root, { importStatement, importKind, beforeModule: before });
|
|
152
|
-
} else
|
|
154
|
+
} else {
|
|
153
155
|
insertImportAfter(j, root, { importStatement, importKind, afterModule: after });
|
|
154
156
|
}
|
|
155
157
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { toLower } = require('lodash');
|
|
2
|
+
|
|
3
|
+
const TOKEN_MAP = {
|
|
4
|
+
// antd style => token
|
|
5
|
+
'#1677ff': 'colorInfo',
|
|
6
|
+
'#1890ff': 'colorInfo',
|
|
7
|
+
'#73d13d': 'colorSuccess',
|
|
8
|
+
'#52c41a': 'colorSuccess',
|
|
9
|
+
'#faad14': 'colorWarning',
|
|
10
|
+
'#ff4d4f': 'colorError',
|
|
11
|
+
'#F5222D': 'colorError',
|
|
12
|
+
'#F8636B': 'colorError',
|
|
13
|
+
'#d9d9d9': 'colorBorder',
|
|
14
|
+
'#bfbfbf': 'colorBorder',
|
|
15
|
+
'#f0f2f5': 'colorBgLayout',
|
|
16
|
+
'#fafafa': 'colorBgLayout',
|
|
17
|
+
'#fff': 'colorBgContainer',
|
|
18
|
+
'#ffffff': 'colorBgContainer',
|
|
19
|
+
'rgba(0,0,0,0.85)': 'colorText',
|
|
20
|
+
'rgba(0,0,0,0.65)': 'colorTextSecondary',
|
|
21
|
+
'rgba(0,0,0,0.45)': 'colorTextTertiary',
|
|
22
|
+
'rgba(0,0,0,0.25)': 'colorTextQuaternary',
|
|
23
|
+
'rgba(0,0,0,0.2)': 'colorFillQuaternary',
|
|
24
|
+
'rgba(0,0,0,0.04)': 'colorBgLayout',
|
|
25
|
+
// obui style => token
|
|
26
|
+
'#006aff': 'colorInfo',
|
|
27
|
+
'#0ac185': 'colorSuccess',
|
|
28
|
+
'#ffac33': 'colorWarning',
|
|
29
|
+
'#ff4b4b': 'colorError',
|
|
30
|
+
'#CDD5E4': 'colorBorder',
|
|
31
|
+
'#F5F8FE': 'colorBgLayout',
|
|
32
|
+
'#132039': 'colorText',
|
|
33
|
+
'#364563': 'colorTextSecondary',
|
|
34
|
+
'#8592AD': 'colorTextTertiary',
|
|
35
|
+
'#F8FAFE': 'colorFillQuaternary',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const TOKEN_MAP_KEYS = Object.keys(TOKEN_MAP);
|
|
39
|
+
|
|
40
|
+
function customTrim(str) {
|
|
41
|
+
return str?.replace(/(\s)*([,\(\)])(\s)*/g, '$2');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function formatValue(value) {
|
|
45
|
+
return customTrim(toLower(value));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function tokenParse(value) {
|
|
49
|
+
const formattedValue = formatValue(value);
|
|
50
|
+
const key = TOKEN_MAP_KEYS.find(item => formattedValue.includes(item));
|
|
51
|
+
return {
|
|
52
|
+
key,
|
|
53
|
+
token: TOKEN_MAP[key],
|
|
54
|
+
formattedValue,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
TOKEN_MAP,
|
|
60
|
+
TOKEN_MAP_KEYS,
|
|
61
|
+
tokenParse,
|
|
62
|
+
};
|