@aiot-toolkit/parser 2.0.6-beta.2 → 2.0.6-beta.20
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/lib/ux/config/IElement.d.ts +14 -0
- package/lib/ux/config/{vela/StyleAttributeConfig.d.ts → StyleBaseConfig.d.ts} +1 -1
- package/lib/ux/config/{vela/StyleAttributeConfig.js → StyleBaseConfig.js} +22 -24
- package/lib/ux/config/vela/ElementConfig.js +17 -0
- package/lib/ux/interface/IE2eConfig.d.ts +49 -0
- package/lib/ux/interface/IE2eConfig.js +1 -0
- package/lib/ux/interface/IStyleError.d.ts +2 -1
- package/lib/ux/parser/ScriptParser.js +2 -1
- package/lib/ux/parser/StyleParser.d.ts +3 -2
- package/lib/ux/parser/StyleParser.js +27 -30
- package/lib/ux/parser/UxParser.d.ts +1 -0
- package/lib/ux/parser/UxParser.js +57 -17
- package/lib/ux/translate/vela/ScriptToTypescript.d.ts +2 -1
- package/lib/ux/translate/vela/ScriptToTypescript.js +14 -7
- package/lib/ux/translate/vela/StyleToTypescript.js +8 -11
- package/lib/ux/translate/vela/plugins/e2e.js +34 -139
- package/lib/ux/translate/vela/utils/AttributeConfig.js +1 -1
- package/lib/ux/translate/vela/utils/TemplateUtil.d.ts +5 -3
- package/lib/ux/translate/vela/utils/TemplateUtil.js +189 -181
- package/lib/ux/utils/StyleMapUtil.d.ts +2 -3
- package/lib/ux/utils/StyleMapUtil.js +6 -5
- package/lib/ux/utils/StyleUtil.d.ts +2 -0
- package/lib/ux/utils/StyleUtil.js +61 -49
- package/lib/ux/utils/UxUtil.d.ts +14 -0
- package/lib/ux/utils/UxUtil.js +41 -0
- package/package.json +4 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Dictionary, Logger } from '@aiot-toolkit/shared-utils';
|
|
2
|
+
import { IAttributeNode } from '../interface/IIdentifierNode';
|
|
2
3
|
interface IElement {
|
|
3
4
|
/**
|
|
4
5
|
* 别名
|
|
@@ -8,6 +9,19 @@ interface IElement {
|
|
|
8
9
|
* @example <img /> 生成为 image
|
|
9
10
|
*/
|
|
10
11
|
aliasName?: string;
|
|
12
|
+
/**
|
|
13
|
+
* 别名属性
|
|
14
|
+
*
|
|
15
|
+
* aliasName 生效时,会将别名属性合并到属性列表中
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```
|
|
19
|
+
* // <button /> 生成为 <input type="button" />
|
|
20
|
+
* aliasName='input'
|
|
21
|
+
* aliasAttributes=[{name:'type',value:'button'}]
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
aliasAttributes?: IAttributeNode[];
|
|
11
25
|
/**
|
|
12
26
|
* 允许文字子节点
|
|
13
27
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Dictionary, Loglevel } from '@aiot-toolkit/shared-utils';
|
|
2
2
|
import { StyleMessage } from '@aiot-toolkit/shared-utils';
|
|
3
|
-
import { BlockItem, StyleItem } from '
|
|
3
|
+
import { BlockItem, StyleItem } from '../interface/IStyleAst';
|
|
4
4
|
type ValidateInfo = {
|
|
5
5
|
level: Loglevel;
|
|
6
6
|
message: StyleMessage[];
|
|
@@ -5,8 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.STYLE_ATTRIBUTE_LIST = exports.STYLE_ATTRIBUTE_CONFIG = void 0;
|
|
7
7
|
var _sharedUtils = require("@aiot-toolkit/shared-utils");
|
|
8
|
-
var _ExtendedBoxStyle = _interopRequireDefault(require("
|
|
9
|
-
var _UxUtil = _interopRequireDefault(require("
|
|
8
|
+
var _ExtendedBoxStyle = _interopRequireDefault(require("../translate/vela/utils/ExtendedBoxStyle"));
|
|
9
|
+
var _UxUtil = _interopRequireDefault(require("../utils/UxUtil"));
|
|
10
10
|
var _cssTree = _interopRequireDefault(require("css-tree"));
|
|
11
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
const REGEXP_NAME = /^([a-zA-Z_]+[a-zA-Z0-9]*\s*,\s*)*[a-zA-Z_]+[a-zA-Z0-9]*$/;
|
|
@@ -1321,6 +1321,12 @@ const STYLE_ATTRIBUTE_CONFIG = exports.STYLE_ATTRIBUTE_CONFIG = {
|
|
|
1321
1321
|
scrollSnapAlign: {
|
|
1322
1322
|
// csstree-validator可校验
|
|
1323
1323
|
// 按照一般转换即可,无需额外转换
|
|
1324
|
+
},
|
|
1325
|
+
selectedFontSize: {
|
|
1326
|
+
validate: validateLengthNode
|
|
1327
|
+
},
|
|
1328
|
+
selectedBackgroundColor: {
|
|
1329
|
+
validate: validColorNode
|
|
1324
1330
|
}
|
|
1325
1331
|
};
|
|
1326
1332
|
/**
|
|
@@ -1345,9 +1351,9 @@ function validateLengthNode(sourceNode) {
|
|
|
1345
1351
|
value[0] = value[0];
|
|
1346
1352
|
const validResult = validLength(value[0]);
|
|
1347
1353
|
if (validResult.message.length > 0) {
|
|
1348
|
-
validateInfo.message = [`The value
|
|
1349
|
-
word: attributeName
|
|
1350
|
-
},
|
|
1354
|
+
validateInfo.message = [`The value of attribute`, {
|
|
1355
|
+
word: `${attributeName}:`
|
|
1356
|
+
}, ...validResult.message];
|
|
1351
1357
|
}
|
|
1352
1358
|
}
|
|
1353
1359
|
return validateInfo;
|
|
@@ -1363,11 +1369,9 @@ function validLength(value) {
|
|
|
1363
1369
|
message: []
|
|
1364
1370
|
};
|
|
1365
1371
|
if (_cssTree.default.lexer.matchType('length', value.value + value.unit).error !== null) {
|
|
1366
|
-
validateInfo.message = [
|
|
1367
|
-
word: value.value
|
|
1368
|
-
},
|
|
1369
|
-
word: value.unit || 'null'
|
|
1370
|
-
}, `, which does not meet the length standard.`];
|
|
1372
|
+
validateInfo.message = [{
|
|
1373
|
+
word: `${value.value}${value.unit}`
|
|
1374
|
+
}, `is invalid.`];
|
|
1371
1375
|
}
|
|
1372
1376
|
return validateInfo;
|
|
1373
1377
|
}
|
|
@@ -1549,30 +1553,24 @@ function validPosition(sourceNode) {
|
|
|
1549
1553
|
name: attributeName
|
|
1550
1554
|
} = sourceNode;
|
|
1551
1555
|
if (value.length <= 0) {
|
|
1552
|
-
validateInfo.message = [`
|
|
1556
|
+
validateInfo.message = [`The value of attribute`, {
|
|
1553
1557
|
word: `${attributeName}`
|
|
1554
|
-
}];
|
|
1558
|
+
}, 'is invalid.'];
|
|
1555
1559
|
} else if (value.length > 3) {
|
|
1556
|
-
validateInfo.message = [`
|
|
1557
|
-
word:
|
|
1558
|
-
}, `is
|
|
1559
|
-
word: value.length
|
|
1560
|
-
}, `, which does not meet the requirement.`];
|
|
1560
|
+
validateInfo.message = [`The value length`, `of attribute`, {
|
|
1561
|
+
word: `${attributeName}: ${value.length}`
|
|
1562
|
+
}, `is invalid.`];
|
|
1561
1563
|
} else {
|
|
1562
1564
|
value.forEach(v => {
|
|
1563
1565
|
v = v;
|
|
1564
1566
|
const validResult = validLength(v);
|
|
1565
1567
|
// 有报错
|
|
1566
1568
|
if (validResult.message.length > 0) {
|
|
1567
|
-
validateInfo.message
|
|
1569
|
+
validateInfo.message = [`The value of attribute`, {
|
|
1570
|
+
word: `${attributeName}:`
|
|
1571
|
+
}, ...validResult.message];
|
|
1568
1572
|
}
|
|
1569
1573
|
});
|
|
1570
|
-
// 如果有报错,添加一下属性名
|
|
1571
|
-
if (validateInfo.message.length > 0) {
|
|
1572
|
-
validateInfo.message.unshift(`The value verification of attribute `, {
|
|
1573
|
-
word: attributeName
|
|
1574
|
-
}, `failed.`);
|
|
1575
|
-
}
|
|
1576
1574
|
}
|
|
1577
1575
|
return validateInfo;
|
|
1578
1576
|
}
|
|
@@ -93,6 +93,12 @@ const elementConfig = {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
|
+
markdown: {
|
|
97
|
+
allowTextChildren: true,
|
|
98
|
+
attributes: {
|
|
99
|
+
value: {}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
96
102
|
'arc-text': {
|
|
97
103
|
allowTextChildren: true,
|
|
98
104
|
attributes: {
|
|
@@ -211,6 +217,17 @@ const elementConfig = {
|
|
|
211
217
|
name: {}
|
|
212
218
|
}
|
|
213
219
|
},
|
|
220
|
+
button: {
|
|
221
|
+
aliasName: 'input',
|
|
222
|
+
aliasAttributes: [{
|
|
223
|
+
name: 'type',
|
|
224
|
+
value: 'button'
|
|
225
|
+
}],
|
|
226
|
+
attributes: {
|
|
227
|
+
name: {},
|
|
228
|
+
value: {}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
214
231
|
input: {
|
|
215
232
|
events: ['change', 'enterkeyclick', 'selectionchange'],
|
|
216
233
|
attributes: {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IE2eConfig
|
|
3
|
+
*/
|
|
4
|
+
export default interface IE2eConfig {
|
|
5
|
+
/**
|
|
6
|
+
* 测试文件的目录
|
|
7
|
+
*
|
|
8
|
+
* 绝对路径 或 相对config文件的路径
|
|
9
|
+
*
|
|
10
|
+
* @default "test"
|
|
11
|
+
*/
|
|
12
|
+
dir: string;
|
|
13
|
+
/**
|
|
14
|
+
* 测试模式打包,入口文件的在manifest中的名称
|
|
15
|
+
*/
|
|
16
|
+
entry: {
|
|
17
|
+
/**
|
|
18
|
+
* 自动化测试文件路径:相对config文件的路径 或 绝对路径
|
|
19
|
+
*
|
|
20
|
+
* @example "pages/index"
|
|
21
|
+
*/
|
|
22
|
+
path: string;
|
|
23
|
+
launchMode?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* 待测试的页面配置
|
|
27
|
+
*/
|
|
28
|
+
testcases?: Array<ITestCase>;
|
|
29
|
+
}
|
|
30
|
+
export interface ITestCase {
|
|
31
|
+
/**
|
|
32
|
+
* 页面名称, 对应manifest中的路由名称
|
|
33
|
+
*
|
|
34
|
+
* @example "pages/index"
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
/**
|
|
38
|
+
* 测试完成后,等待多久回退到上一个页面,单位ms
|
|
39
|
+
*
|
|
40
|
+
* @default 0
|
|
41
|
+
*/
|
|
42
|
+
sleep?: number;
|
|
43
|
+
/**
|
|
44
|
+
* 测试完成后,是否回退到上一个页面
|
|
45
|
+
*
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
back?: boolean;
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -3,7 +3,7 @@ import IOptions from '../config/IOptions';
|
|
|
3
3
|
import { IStyleAst } from '../interface/IStyleAst';
|
|
4
4
|
import ITranslateOption from '../interface/ITranslateOption';
|
|
5
5
|
import { IImageFunction } from '../interface/IImageResource';
|
|
6
|
-
import {
|
|
6
|
+
import { SourceMapConsumer } from 'source-map';
|
|
7
7
|
/**
|
|
8
8
|
* StyleParser
|
|
9
9
|
* 1. 根据语言类型分别转为CSS样式
|
|
@@ -15,9 +15,10 @@ declare class StyleParser implements IParser<IStyleAst> {
|
|
|
15
15
|
readonly compilerOption: ITranslateOption;
|
|
16
16
|
collectImageResource: IImageFunction;
|
|
17
17
|
readonly styleLineOffset: number;
|
|
18
|
-
nodeMap:
|
|
18
|
+
nodeMap: string;
|
|
19
19
|
sourceMapConsumer: SourceMapConsumer;
|
|
20
20
|
private styleMapUtil;
|
|
21
|
+
private isCss;
|
|
21
22
|
readonly QUICKAPP_CONFIG = "quickapp.config.js";
|
|
22
23
|
constructor(options: IOptions, compilerOption: ITranslateOption, collectImageResource: IImageFunction, styleLineOffset: number);
|
|
23
24
|
parser(content: string, fileName: string): Promise<ParserResult<IStyleAst>>;
|
|
@@ -32,19 +32,21 @@ const {
|
|
|
32
32
|
* 3. 把解析结果转换为目标格式
|
|
33
33
|
*/
|
|
34
34
|
class StyleParser {
|
|
35
|
+
// 是否是css样式代码
|
|
36
|
+
isCss = true;
|
|
35
37
|
QUICKAPP_CONFIG = 'quickapp.config.js';
|
|
36
38
|
constructor(options, compilerOption, collectImageResource, styleLineOffset) {
|
|
37
39
|
this.options = options;
|
|
38
40
|
this.compilerOption = compilerOption;
|
|
39
41
|
this.collectImageResource = collectImageResource;
|
|
40
42
|
this.styleLineOffset = styleLineOffset;
|
|
41
|
-
this.nodeMap = {
|
|
43
|
+
this.nodeMap = JSON.stringify({
|
|
42
44
|
version: 3,
|
|
43
45
|
sources: [],
|
|
44
46
|
names: [],
|
|
45
47
|
mappings: '',
|
|
46
48
|
file: ''
|
|
47
|
-
};
|
|
49
|
+
});
|
|
48
50
|
}
|
|
49
51
|
async parser(content, fileName) {
|
|
50
52
|
const {
|
|
@@ -147,7 +149,8 @@ class StyleParser {
|
|
|
147
149
|
relativeUrls: true,
|
|
148
150
|
sourceMap: {
|
|
149
151
|
sourceMapURL: `${baseName}.map`,
|
|
150
|
-
outputSourceFiles: true
|
|
152
|
+
outputSourceFiles: true,
|
|
153
|
+
sourceMapRootpath: 'file:///'
|
|
151
154
|
}
|
|
152
155
|
}, (error, output) => {
|
|
153
156
|
if (error) {
|
|
@@ -161,6 +164,7 @@ class StyleParser {
|
|
|
161
164
|
CSSCode = output?.css ? output.css : '';
|
|
162
165
|
if (output?.map) {
|
|
163
166
|
this.nodeMap = output.map;
|
|
167
|
+
this.isCss && (this.isCss = false);
|
|
164
168
|
}
|
|
165
169
|
resolve(CSSCode);
|
|
166
170
|
}
|
|
@@ -177,7 +181,7 @@ class StyleParser {
|
|
|
177
181
|
onLog,
|
|
178
182
|
filePath
|
|
179
183
|
} = this.options;
|
|
180
|
-
const url = `file
|
|
184
|
+
const url = `file:///${filePath}`;
|
|
181
185
|
const alias = this.getAlias();
|
|
182
186
|
|
|
183
187
|
// sass 的 alias 处理依赖当前文件路径
|
|
@@ -196,6 +200,7 @@ class StyleParser {
|
|
|
196
200
|
});
|
|
197
201
|
if (Result.sourceMap) {
|
|
198
202
|
this.nodeMap = JSON.stringify(Result.sourceMap);
|
|
203
|
+
this.isCss && (this.isCss = false);
|
|
199
204
|
}
|
|
200
205
|
return Result.css;
|
|
201
206
|
} catch (error) {
|
|
@@ -217,23 +222,29 @@ class StyleParser {
|
|
|
217
222
|
onLog,
|
|
218
223
|
filePath
|
|
219
224
|
} = this.options;
|
|
225
|
+
const newFilePath = this.isCss ? filePath : `file:///${filePath}`;
|
|
220
226
|
const alias = this.getAlias();
|
|
221
227
|
try {
|
|
222
228
|
const result = await (0, _postcss.default)([(0, _postcssImport.default)({
|
|
223
|
-
resolve: id => {
|
|
229
|
+
resolve: (id, basedir) => {
|
|
230
|
+
// 处理所有路径中的 file:/// 前缀
|
|
231
|
+
const cleanId = id.replace(/^file:\/\/\//, '');
|
|
232
|
+
const cleanBase = basedir.replace(/^file:\/\/\//, '');
|
|
233
|
+
const filePath = _path.default.resolve(cleanBase, cleanId);
|
|
224
234
|
for (const [key, value] of Object.entries(alias)) {
|
|
225
|
-
if (
|
|
226
|
-
return
|
|
235
|
+
if (filePath.startsWith(key)) {
|
|
236
|
+
return filePath.replace(key, value);
|
|
227
237
|
}
|
|
228
238
|
}
|
|
229
|
-
return
|
|
239
|
+
return filePath;
|
|
230
240
|
}
|
|
231
241
|
}), _postcssUrl.default]).process(sourceContent, {
|
|
232
|
-
from:
|
|
242
|
+
from: newFilePath,
|
|
233
243
|
map: {
|
|
234
244
|
prev: this.nodeMap,
|
|
235
245
|
inline: false,
|
|
236
|
-
|
|
246
|
+
sourcesContent: true,
|
|
247
|
+
absolute: this.isCss
|
|
237
248
|
}
|
|
238
249
|
});
|
|
239
250
|
this.nodeMap = result.map.toString();
|
|
@@ -307,7 +318,7 @@ class StyleParser {
|
|
|
307
318
|
type: '',
|
|
308
319
|
prelude: [],
|
|
309
320
|
block: [],
|
|
310
|
-
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc) : undefined
|
|
321
|
+
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc, false) : undefined
|
|
311
322
|
};
|
|
312
323
|
const {
|
|
313
324
|
type,
|
|
@@ -330,7 +341,7 @@ class StyleParser {
|
|
|
330
341
|
name: '',
|
|
331
342
|
prelude: [],
|
|
332
343
|
rules: [],
|
|
333
|
-
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc) : undefined
|
|
344
|
+
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc, false) : undefined
|
|
334
345
|
};
|
|
335
346
|
const {
|
|
336
347
|
type,
|
|
@@ -376,7 +387,7 @@ class StyleParser {
|
|
|
376
387
|
type: '',
|
|
377
388
|
name: '',
|
|
378
389
|
block: [],
|
|
379
|
-
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc) : undefined
|
|
390
|
+
position: sourceNode.loc ? this.styleMapUtil.transfromLocToPosition(sourceNode.loc, false) : undefined
|
|
380
391
|
};
|
|
381
392
|
const {
|
|
382
393
|
type,
|
|
@@ -494,7 +505,7 @@ class StyleParser {
|
|
|
494
505
|
let value = '';
|
|
495
506
|
nodeValue.children.map(v => {
|
|
496
507
|
let tempTargetValue;
|
|
497
|
-
const tempPosition = v.loc ? this.styleMapUtil.transfromLocToPosition(v.loc) : undefined;
|
|
508
|
+
const tempPosition = v.loc ? this.styleMapUtil.transfromLocToPosition(v.loc, false) : undefined;
|
|
498
509
|
switch (v.type) {
|
|
499
510
|
case 'Operator':
|
|
500
511
|
value = _cssTree.default.generate(v);
|
|
@@ -578,7 +589,7 @@ class StyleParser {
|
|
|
578
589
|
targetList.push({
|
|
579
590
|
name: nodeName,
|
|
580
591
|
value: valueList,
|
|
581
|
-
position: node.loc ? this.styleMapUtil.transfromLocToPosition(node.loc) : undefined
|
|
592
|
+
position: node.loc ? this.styleMapUtil.transfromLocToPosition(node.loc, false) : undefined
|
|
582
593
|
});
|
|
583
594
|
}
|
|
584
595
|
return targetList;
|
|
@@ -587,17 +598,10 @@ class StyleParser {
|
|
|
587
598
|
let errors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
588
599
|
let isParserError = errorType === 'parserError';
|
|
589
600
|
let sourceCodeStyle = _sharedUtils.Loglevel.WARN;
|
|
590
|
-
const {
|
|
591
|
-
onLog,
|
|
592
|
-
filePath
|
|
593
|
-
} = this.options;
|
|
594
601
|
if (isParserError) {
|
|
595
602
|
sourceCodeStyle = _sharedUtils.Loglevel.ERROR;
|
|
596
603
|
}
|
|
597
604
|
errors.forEach(error => {
|
|
598
|
-
const sourceCode = error.source ? [`, source code:`, {
|
|
599
|
-
word: `${error.source}`
|
|
600
|
-
}] : [];
|
|
601
605
|
const position = this.styleMapUtil.transfromLocToPosition({
|
|
602
606
|
start: {
|
|
603
607
|
line: error.startLine,
|
|
@@ -613,14 +617,7 @@ class StyleParser {
|
|
|
613
617
|
});
|
|
614
618
|
position.startColumn++;
|
|
615
619
|
position.endColumn++;
|
|
616
|
-
|
|
617
|
-
level: sourceCodeStyle,
|
|
618
|
-
filePath,
|
|
619
|
-
position,
|
|
620
|
-
message: [{
|
|
621
|
-
word: error.message
|
|
622
|
-
}, ...sourceCode]
|
|
623
|
-
});
|
|
620
|
+
_StyleUtil.default.handleStyleError(sourceCodeStyle, error.messages, this.options, position);
|
|
624
621
|
});
|
|
625
622
|
return [];
|
|
626
623
|
}
|
|
@@ -11,6 +11,7 @@ var _TemplateUtil = _interopRequireDefault(require("../translate/vela/utils/Temp
|
|
|
11
11
|
var _UxUtil = _interopRequireDefault(require("../utils/UxUtil"));
|
|
12
12
|
var _ScriptParser = _interopRequireDefault(require("./ScriptParser"));
|
|
13
13
|
var _StyleParser = _interopRequireDefault(require("./StyleParser"));
|
|
14
|
+
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
16
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
16
17
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
@@ -72,14 +73,51 @@ class UxParser {
|
|
|
72
73
|
};
|
|
73
74
|
break;
|
|
74
75
|
case 'style':
|
|
75
|
-
|
|
76
|
+
// 如果 style 标签有 src 属性,则读取对应的文件内容,否则直接使用 style 标签的内容
|
|
77
|
+
const src = _UxUtil.default.getStyleSrc(childNode, this.options.filePath);
|
|
78
|
+
let cssContent = '';
|
|
79
|
+
const filePath = this.options.filePath;
|
|
80
|
+
if (src) {
|
|
81
|
+
// 如果有 src 属性,且 style 标签内有内容,则提示用户 style 标签内的内容会被 src 文件覆盖
|
|
82
|
+
if (childNode.childNodes && childNode.childNodes.length > 0) {
|
|
83
|
+
this.options.onLog({
|
|
84
|
+
level: _sharedUtils.Loglevel.WARN,
|
|
85
|
+
filePath: this.options.filePath,
|
|
86
|
+
position: {
|
|
87
|
+
startLine: childNode.sourceCodeLocation?.startLine || 0,
|
|
88
|
+
startColumn: 0
|
|
89
|
+
},
|
|
90
|
+
message: [`style tag with src should not have inline content, src file will be used directly`]
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// 读取 src 文件内容,如果文件不存在,则提示用户
|
|
94
|
+
if (!_fsExtra.default.existsSync(src)) {
|
|
95
|
+
this.options.onLog({
|
|
96
|
+
level: _sharedUtils.Loglevel.WARN,
|
|
97
|
+
filePath: this.options.filePath,
|
|
98
|
+
position: {
|
|
99
|
+
startLine: childNode.sourceCodeLocation?.startLine || 0,
|
|
100
|
+
startColumn: 0
|
|
101
|
+
},
|
|
102
|
+
message: [`style src file does not exist: ${src}`]
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
cssContent = _fsExtra.default.readFileSync(src).toString();
|
|
106
|
+
// 解析 css 时需要用到文件路径,所以将options.filePath暂时替换为src,解析完成后再还原
|
|
107
|
+
this.options.filePath = src;
|
|
108
|
+
}
|
|
109
|
+
} else cssContent = parse5.serialize(childNode);
|
|
110
|
+
|
|
76
111
|
// 获取lang值,组合成文件名
|
|
77
112
|
const langType = _UxUtil.default.getLangType(childNode);
|
|
78
|
-
|
|
113
|
+
// 使用 src 时,cssFileName 以 src 的文件名为准,否则以当前解析的文件名为准
|
|
114
|
+
const cssFileName = src ? _path.default.basename(src) : _UxUtil.default.spliceFileName(fileName, langType);
|
|
79
115
|
// 转换全局变量为符合lang类型的字符串
|
|
80
116
|
const globalStyle = _UxUtil.default.convertGlobalJson(this.globalVar, langType);
|
|
81
117
|
// 解析CSS 转为 js格式的内容
|
|
82
118
|
const cssParserResult = await new _StyleParser.default(this.options, this.compilerOption, this.collectImageResource, childNode.sourceCodeLocation?.startLine || 0).parser(`${cssContent}\n${globalStyle}`, cssFileName);
|
|
119
|
+
// 还原 this.options.filePath
|
|
120
|
+
this.options.filePath = filePath;
|
|
83
121
|
// 多Style标签(TODO: 应该不支持多style标签)
|
|
84
122
|
ast.style.styleContent.push(...cssParserResult.ast.styleContent);
|
|
85
123
|
ast.style.content = parse5.serialize(childNode);
|
|
@@ -201,6 +239,7 @@ class UxParser {
|
|
|
201
239
|
* 1. template:
|
|
202
240
|
* a. 最多1个
|
|
203
241
|
* b. 子元素有且仅有1个,不能是 block
|
|
242
|
+
* 2. 必须有闭合标签, 示例: `<script>....</script>`正确, `<script>aaaa`错误
|
|
204
243
|
*/
|
|
205
244
|
validateContent(childNodes) {
|
|
206
245
|
let result = true;
|
|
@@ -249,21 +288,22 @@ class UxParser {
|
|
|
249
288
|
}
|
|
250
289
|
|
|
251
290
|
// 2
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
291
|
+
childNodes.forEach(node => {
|
|
292
|
+
if (_TemplateUtil.default.isElement(node)) {
|
|
293
|
+
const {
|
|
294
|
+
sourceCodeLocation
|
|
295
|
+
} = node;
|
|
296
|
+
if (sourceCodeLocation && !sourceCodeLocation.endTag) {
|
|
297
|
+
onLog({
|
|
298
|
+
level: _sharedUtils.Loglevel.ERROR,
|
|
299
|
+
filePath,
|
|
300
|
+
position: _TemplateUtil.default.parse5LocationToPosition(sourceCodeLocation.startTag),
|
|
301
|
+
message: [`<${node.nodeName}>`, 'must have an end tag']
|
|
302
|
+
});
|
|
303
|
+
result = false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
267
307
|
return result;
|
|
268
308
|
}
|
|
269
309
|
/**
|
|
@@ -12,8 +12,9 @@ declare class ScriptToTypescript implements ITranslate<IScriptAst, SourceFile> {
|
|
|
12
12
|
options: IOptions;
|
|
13
13
|
readonly compilerOption: ITranslateOption;
|
|
14
14
|
readonly context: IFileLaneContext;
|
|
15
|
+
readonly disableCheckCode: boolean;
|
|
15
16
|
private _systemFeatures;
|
|
16
|
-
constructor(options: IOptions, compilerOption: ITranslateOption, context: IFileLaneContext);
|
|
17
|
+
constructor(options: IOptions, compilerOption: ITranslateOption, context: IFileLaneContext, disableCheckCode?: boolean);
|
|
17
18
|
translate(sourceTree: IScriptAst, offsetList: IOffset[]): Promise<{
|
|
18
19
|
targetTree: SourceFile;
|
|
19
20
|
mapList: never[];
|
|
@@ -21,19 +21,23 @@ const BabelPreset = require('@babel/preset-env');
|
|
|
21
21
|
class ScriptToTypescript {
|
|
22
22
|
_systemFeatures = (() => new Set())();
|
|
23
23
|
constructor(options, compilerOption, context) {
|
|
24
|
+
let disableCheckCode = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
24
25
|
this.options = options;
|
|
25
26
|
this.compilerOption = compilerOption;
|
|
26
27
|
this.context = context;
|
|
28
|
+
this.disableCheckCode = disableCheckCode;
|
|
27
29
|
}
|
|
28
30
|
async translate(sourceTree,
|
|
29
31
|
// eslint-disable-next-line
|
|
30
32
|
offsetList) {
|
|
31
33
|
// 检查代码错误
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
logs
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (!this.disableCheckCode) {
|
|
35
|
+
const logs = await this.checkCode(sourceTree);
|
|
36
|
+
if (logs) {
|
|
37
|
+
logs.forEach(log => {
|
|
38
|
+
this.options.onLog(log);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
// 使用babel实现替换,由此实现自动更新source map
|
|
39
43
|
const content = this.babelScript(sourceTree);
|
|
@@ -51,7 +55,10 @@ class ScriptToTypescript {
|
|
|
51
55
|
* @returns
|
|
52
56
|
*/
|
|
53
57
|
babelScript(sourceTree) {
|
|
54
|
-
|
|
58
|
+
if (sourceTree.content === '') {
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
const sourceCode = sourceTree.content;
|
|
55
62
|
const relativePath = _path.default.relative(this.options.projectPath, this.options.filePath);
|
|
56
63
|
const plugins = [
|
|
57
64
|
// 替换所有的require节点
|
|
@@ -96,7 +103,7 @@ class ScriptToTypescript {
|
|
|
96
103
|
let position = undefined;
|
|
97
104
|
let message = babelError.message;
|
|
98
105
|
if (loc) {
|
|
99
|
-
const offsetLine = (sourceTree.sourceCodeLocation?.startLine ||
|
|
106
|
+
const offsetLine = (sourceTree.sourceCodeLocation?.startLine || 1) - 1;
|
|
100
107
|
const startLine = loc.line + offsetLine;
|
|
101
108
|
const startColumn = loc.column;
|
|
102
109
|
// babel 错误信息中包含行列信息,需要替换
|
|
@@ -94,8 +94,14 @@ class StyleToTypescript {
|
|
|
94
94
|
const selector = node[i];
|
|
95
95
|
const {
|
|
96
96
|
type,
|
|
97
|
-
name
|
|
97
|
+
name: orgName
|
|
98
98
|
} = selector;
|
|
99
|
+
|
|
100
|
+
// 去除名称中的转义符,例如 源码是 .w-20\% {}, 希望生成 w-20%
|
|
101
|
+
// 注意:此处的反转义不能用 JSON.parse
|
|
102
|
+
// 原因:js中 % 不需要转义,但css选择器中%需要转义,两者规则不一样,所以不能使用 JSON.parse
|
|
103
|
+
// 示例:js可以写'abc%', 但css选择器中必须写'abc\%'
|
|
104
|
+
const name = orgName.replace(/\\(.{1})/g, '$1');
|
|
99
105
|
// 选择器类型转为数字
|
|
100
106
|
const selectorIndex = (0, _StyleSelectorType.findSelectorIndex)(type);
|
|
101
107
|
if (type === _StyleSelectorType.Selector.COMBINATOR) {
|
|
@@ -131,10 +137,6 @@ class StyleToTypescript {
|
|
|
131
137
|
* @param name
|
|
132
138
|
*/
|
|
133
139
|
addThorwLog(type, name, position, info) {
|
|
134
|
-
const {
|
|
135
|
-
onLog,
|
|
136
|
-
filePath
|
|
137
|
-
} = this.options;
|
|
138
140
|
const logLevel = name === ' ' || name === '>' ? _sharedUtils.Loglevel.WARN : _sharedUtils.Loglevel.THROW;
|
|
139
141
|
const message = info ? [`### StyleToTypescript ### Selector type unsupport`, {
|
|
140
142
|
word: info
|
|
@@ -143,12 +145,7 @@ class StyleToTypescript {
|
|
|
143
145
|
}, ',name:', {
|
|
144
146
|
word: name
|
|
145
147
|
}];
|
|
146
|
-
|
|
147
|
-
filePath,
|
|
148
|
-
position,
|
|
149
|
-
level: logLevel,
|
|
150
|
-
message
|
|
151
|
-
});
|
|
148
|
+
_StyleUtil.default.handleStyleError(logLevel, message, this.options, position);
|
|
152
149
|
}
|
|
153
150
|
translateAtrule(sourceNode) {
|
|
154
151
|
let targetNodes = [];
|