@aiot-toolkit/aiotpack 2.1.0-prender.11 → 2.1.0-prender.13
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/afterCompile/ux/UxAfterCompile.d.ts +10 -0
- package/lib/afterCompile/ux/UxAfterCompile.js +78 -2
- package/lib/compiler/javascript/TemplateCompiler.d.ts +1 -1
- package/lib/compiler/javascript/TemplateCompiler.js +129 -21
- package/lib/compiler/javascript/ViteCompiler.d.ts +2 -0
- package/lib/compiler/javascript/ViteCompiler.js +97 -5
- package/lib/compiler/javascript/vela/utils/Jsc.d.ts +3 -0
- package/lib/compiler/javascript/vela/utils/Jsc.js +43 -1
- package/lib/compiler/javascript/vela/utils/ZipUtil.js +11 -2
- package/lib/config/UxConfig.js +3 -0
- package/package.json +5 -5
|
@@ -22,6 +22,16 @@ declare class UxAfterCompile {
|
|
|
22
22
|
* @param params
|
|
23
23
|
*/
|
|
24
24
|
static compressResource: FollowWork<IJavascriptCompileOption>;
|
|
25
|
+
/**
|
|
26
|
+
* Relocate manifest.icon into build root so debug and release rpks share the
|
|
27
|
+
* same asset layout. Rewrites `manifest.icon` + every string reference to the
|
|
28
|
+
* old icon path inside template.json / css.json / *.js. Files are text-scanned
|
|
29
|
+
* and quoted-substring matched only (no cross-string boundary rewriting).
|
|
30
|
+
*
|
|
31
|
+
* No-op when manifest.icon is already at root, the physical file is missing,
|
|
32
|
+
* or the destination basename already exists at root.
|
|
33
|
+
*/
|
|
34
|
+
static relocateManifestIcon: FollowWork<IJavascriptCompileOption>;
|
|
25
35
|
/**
|
|
26
36
|
* 如果是更新触发,则对比临时项目build文件夹 和 项目build文件夹,生成diff.json
|
|
27
37
|
* @param context
|
|
@@ -99,8 +99,12 @@ class UxAfterCompile {
|
|
|
99
99
|
context,
|
|
100
100
|
compilerOption
|
|
101
101
|
} = params;
|
|
102
|
-
if (compilerOption
|
|
103
|
-
|
|
102
|
+
if (compilerOption) {
|
|
103
|
+
const buildPath = _path.default.join(context.projectPath, context.output, compilerOption.outputPath);
|
|
104
|
+
_Jsc.default.wrapAllJsWithIife(buildPath);
|
|
105
|
+
if (compilerOption.enableJsc === true) {
|
|
106
|
+
return new _Jsc.default(context.projectPath, buildPath).jsc();
|
|
107
|
+
}
|
|
104
108
|
}
|
|
105
109
|
};
|
|
106
110
|
static toRpk = async params => {
|
|
@@ -334,6 +338,78 @@ class UxAfterCompile {
|
|
|
334
338
|
}
|
|
335
339
|
};
|
|
336
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Relocate manifest.icon into build root so debug and release rpks share the
|
|
343
|
+
* same asset layout. Rewrites `manifest.icon` + every string reference to the
|
|
344
|
+
* old icon path inside template.json / css.json / *.js. Files are text-scanned
|
|
345
|
+
* and quoted-substring matched only (no cross-string boundary rewriting).
|
|
346
|
+
*
|
|
347
|
+
* No-op when manifest.icon is already at root, the physical file is missing,
|
|
348
|
+
* or the destination basename already exists at root.
|
|
349
|
+
*/
|
|
350
|
+
static relocateManifestIcon = async params => {
|
|
351
|
+
const {
|
|
352
|
+
compilerOption,
|
|
353
|
+
onLog
|
|
354
|
+
} = params;
|
|
355
|
+
if (!compilerOption) return;
|
|
356
|
+
const {
|
|
357
|
+
projectPath,
|
|
358
|
+
outputPath
|
|
359
|
+
} = compilerOption;
|
|
360
|
+
const buildDir = _path.default.join(projectPath, outputPath);
|
|
361
|
+
const manifestPath = _path.default.join(buildDir, 'manifest.json');
|
|
362
|
+
if (!_fsExtra.default.existsSync(manifestPath)) return;
|
|
363
|
+
const manifest = _fsExtra.default.readJSONSync(manifestPath);
|
|
364
|
+
const oldIcon = manifest.icon;
|
|
365
|
+
if (!oldIcon || typeof oldIcon !== 'string') return;
|
|
366
|
+
const basename = _path.default.basename(oldIcon);
|
|
367
|
+
const newIcon = '/' + basename;
|
|
368
|
+
if (oldIcon === newIcon) return;
|
|
369
|
+
const oldFile = _path.default.join(buildDir, oldIcon.replace(/^\//, ''));
|
|
370
|
+
const newFile = _path.default.join(buildDir, basename);
|
|
371
|
+
if (!_fsExtra.default.existsSync(oldFile)) return;
|
|
372
|
+
if (_fsExtra.default.existsSync(newFile)) {
|
|
373
|
+
onLog?.([{
|
|
374
|
+
level: _sharedUtils.Loglevel.WARN,
|
|
375
|
+
message: [`relocateManifestIcon: skipped — build root already contains ${basename}`]
|
|
376
|
+
}]);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
_fsExtra.default.moveSync(oldFile, newFile);
|
|
380
|
+
manifest.icon = newIcon;
|
|
381
|
+
_fsExtra.default.writeJSONSync(manifestPath, manifest, {
|
|
382
|
+
spaces: 2
|
|
383
|
+
});
|
|
384
|
+
const variants = [oldIcon, oldIcon.replace(/^\//, '')];
|
|
385
|
+
const replacements = [];
|
|
386
|
+
for (const v of variants) {
|
|
387
|
+
const target = v === oldIcon ? newIcon : basename;
|
|
388
|
+
replacements.push([JSON.stringify(v), JSON.stringify(target)]);
|
|
389
|
+
replacements.push([`'${v}'`, `'${target}'`]);
|
|
390
|
+
}
|
|
391
|
+
const rewriteFile = fp => {
|
|
392
|
+
let text;
|
|
393
|
+
try {
|
|
394
|
+
text = _fsExtra.default.readFileSync(fp, 'utf-8');
|
|
395
|
+
} catch {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
let changed = false;
|
|
399
|
+
for (const [from, to] of replacements) {
|
|
400
|
+
if (text.includes(from)) {
|
|
401
|
+
text = text.split(from).join(to);
|
|
402
|
+
changed = true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (changed) _fsExtra.default.writeFileSync(fp, text, 'utf-8');
|
|
406
|
+
};
|
|
407
|
+
for (const fp of _sharedUtils.FileUtil.readAlldirSync(buildDir)) {
|
|
408
|
+
if (fp === manifestPath) continue;
|
|
409
|
+
if (/\.(template\.json|css\.json|js|jsx?)$/.test(fp)) rewriteFile(fp);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
337
413
|
/**
|
|
338
414
|
* 如果是更新触发,则对比临时项目build文件夹 和 项目build文件夹,生成diff.json
|
|
339
415
|
* @param context
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare function uxToTemplateJson(templateNode: any, styleObjectId?: number, styleSheet?: any, importMap?: Record<string, string>, pageDir?: string): any;
|
|
1
|
+
declare function uxToTemplateJson(templateNode: any, styleObjectId?: number, styleSheet?: any, importMap?: Record<string, string>, pageDir?: string, componentsMap?: Record<string, string>): any;
|
|
2
2
|
/**
|
|
3
3
|
* Normalize a media query condition text from CSS Level 4 syntax to Level 3.
|
|
4
4
|
*
|
|
@@ -35,6 +35,81 @@ function hasApplicableMediaRule(styleSheet, tagName, classTokens) {
|
|
|
35
35
|
}
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
|
+
// Parse a simple/compound selector like ".a", ".a.b", "text", "text.a", ".a #id"
|
|
39
|
+
// (id treated as a class token for build-time approximation).
|
|
40
|
+
function parseCompoundSelector(part) {
|
|
41
|
+
const out = {
|
|
42
|
+
classes: []
|
|
43
|
+
};
|
|
44
|
+
const re = /(\.[\w-]+)|(#[\w-]+)|(\*)|([a-zA-Z][\w-]*)/g;
|
|
45
|
+
let m;
|
|
46
|
+
let matched = false;
|
|
47
|
+
while ((m = re.exec(part)) !== null) {
|
|
48
|
+
matched = true;
|
|
49
|
+
if (m[1]) out.classes.push(m[1].slice(1));else if (m[2]) out.classes.push(m[2].slice(1));else if (m[4]) out.tag = m[4];
|
|
50
|
+
}
|
|
51
|
+
return matched ? out : null;
|
|
52
|
+
}
|
|
53
|
+
function matchesCompound(comp, tag, classes) {
|
|
54
|
+
if (comp.tag && comp.tag !== tag) return false;
|
|
55
|
+
for (const c of comp.classes) if (!classes.has(c)) return false;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Match a CSS selector against an element + its ancestor chain (root...parent).
|
|
60
|
+
// Supports descendant, child (>), and compound (.a.b) selectors. Sibling
|
|
61
|
+
// combinators (+, ~) require sibling context and are treated as non-match here.
|
|
62
|
+
function selectorMatchesElement(selector, tag, classes, ancestors) {
|
|
63
|
+
const parts = [];
|
|
64
|
+
const combinators = [];
|
|
65
|
+
let cur = '';
|
|
66
|
+
for (let i = 0; i < selector.length; i++) {
|
|
67
|
+
const ch = selector[i];
|
|
68
|
+
if (ch === '>' || ch === '+' || ch === '~') {
|
|
69
|
+
if (cur.trim()) parts.push(cur.trim());
|
|
70
|
+
combinators.push(ch);
|
|
71
|
+
cur = '';
|
|
72
|
+
} else if (ch === ' ' || ch === '\t') {
|
|
73
|
+
if (cur.trim()) {
|
|
74
|
+
parts.push(cur.trim());
|
|
75
|
+
combinators.push(' ');
|
|
76
|
+
cur = '';
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
cur += ch;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (cur.trim()) parts.push(cur.trim());
|
|
83
|
+
if (parts.length === 0) return false;
|
|
84
|
+
const rightMost = parseCompoundSelector(parts[parts.length - 1]);
|
|
85
|
+
if (!rightMost) return false;
|
|
86
|
+
if (!matchesCompound(rightMost, tag, classes)) return false;
|
|
87
|
+
let idx = ancestors.length - 1;
|
|
88
|
+
for (let i = parts.length - 2; i >= 0; i--) {
|
|
89
|
+
const combinator = combinators[i];
|
|
90
|
+
const simple = parseCompoundSelector(parts[i]);
|
|
91
|
+
if (!simple) return false;
|
|
92
|
+
if (combinator === ' ') {
|
|
93
|
+
let found = false;
|
|
94
|
+
while (idx >= 0) {
|
|
95
|
+
if (matchesCompound(simple, ancestors[idx].tag, ancestors[idx].classes)) {
|
|
96
|
+
idx--;
|
|
97
|
+
found = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
idx--;
|
|
101
|
+
}
|
|
102
|
+
if (!found) return false;
|
|
103
|
+
} else if (combinator === '>') {
|
|
104
|
+
if (idx < 0) return false;
|
|
105
|
+
if (!matchesCompound(simple, ancestors[idx].tag, ancestors[idx].classes)) return false;
|
|
106
|
+
idx--;
|
|
107
|
+
} else {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
38
113
|
|
|
39
114
|
// vivo blueos-pack's aggressive camelCase applied to transition-property values.
|
|
40
115
|
// Every letter that follows a non-letter character (separator or digit) is upper-cased,
|
|
@@ -156,11 +231,17 @@ function normalizeCssTransform(input) {
|
|
|
156
231
|
}
|
|
157
232
|
return matched ? JSON.stringify(out) : null;
|
|
158
233
|
}
|
|
159
|
-
function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pageDir) {
|
|
234
|
+
function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pageDir, componentsMap) {
|
|
160
235
|
const children = templateNode.content?.childNodes || templateNode.childNodes || [];
|
|
161
236
|
const rootEl = children.find(n => n.tagName && n.nodeName !== '#text');
|
|
162
237
|
if (!rootEl) return {};
|
|
163
238
|
const result = elementToJson(rootEl, styleSheet, importMap, undefined, pageDir);
|
|
239
|
+
const componentsForRoot = componentsMap && Object.keys(componentsMap).length ? componentsMap : importMap;
|
|
240
|
+
if (componentsForRoot && Object.keys(componentsForRoot).length) {
|
|
241
|
+
result.components = {
|
|
242
|
+
...componentsForRoot
|
|
243
|
+
};
|
|
244
|
+
}
|
|
164
245
|
// Insert styleObjectId before children (vivo format)
|
|
165
246
|
if (styleObjectId !== undefined) {
|
|
166
247
|
const ordered = {};
|
|
@@ -178,6 +259,16 @@ function uxToTemplateJson(templateNode, styleObjectId, styleSheet, importMap, pa
|
|
|
178
259
|
/** Add this. prefix to variable references in an expression */
|
|
179
260
|
// blueos-pack's pathTestRE: matches simple paths like a.b.c, a['key'], a[0], a[$idx]
|
|
180
261
|
const pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[\w$]+|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/;
|
|
262
|
+
function tryEvalStaticShowLiteral(expr) {
|
|
263
|
+
if (/^'[^']*'$/.test(expr) || /^"[^"]*"$/.test(expr)) {
|
|
264
|
+
const inner = expr.slice(1, -1);
|
|
265
|
+
return inner.length > 0;
|
|
266
|
+
}
|
|
267
|
+
if (expr === 'undefined' || expr === 'null' || expr === 'NaN') return false;
|
|
268
|
+
if (expr === 'Infinity') return true;
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
181
272
|
/**
|
|
182
273
|
* Normalize a media query condition text from CSS Level 4 syntax to Level 3.
|
|
183
274
|
*
|
|
@@ -469,6 +560,7 @@ function emitTextValueAttr(rawText) {
|
|
|
469
560
|
};
|
|
470
561
|
}
|
|
471
562
|
function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
563
|
+
let ancestors = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
|
|
472
564
|
const tagName = el.tagName === 'img' ? 'image' : el.tagName;
|
|
473
565
|
const node = {
|
|
474
566
|
type: tagName
|
|
@@ -493,9 +585,7 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
493
585
|
name = name.slice(1);
|
|
494
586
|
if (!value.includes('{{')) value = `{{${value}}}`;
|
|
495
587
|
}
|
|
496
|
-
if (name === '
|
|
497
|
-
continue; // is attribute handled at runtime
|
|
498
|
-
} else if (name === 'class') {
|
|
588
|
+
if (name === 'class') {
|
|
499
589
|
className = value.replace(/\s+/g, ' ').trim();
|
|
500
590
|
} else if (name.startsWith('@') || name.startsWith('on') && name.length > 2) {
|
|
501
591
|
const rawEvtName = name.startsWith('@') ? name.slice(1) : name.replace(/^on/, '');
|
|
@@ -538,13 +628,20 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
538
628
|
} else if (name === 'show') {
|
|
539
629
|
const showVal = value.replace(/\{\{|\}\}/g, '').trim();
|
|
540
630
|
if (showVal === 'true') attrObj['show'] = true;else if (showVal === 'false') attrObj['show'] = false;else {
|
|
541
|
-
// Try to evaluate as literal
|
|
542
631
|
try {
|
|
543
632
|
const v = JSON.parse(showVal);
|
|
544
633
|
attrObj["show"] = v;
|
|
545
634
|
} catch {
|
|
546
|
-
|
|
547
|
-
|
|
635
|
+
const staticVal = tryEvalStaticShowLiteral(showVal);
|
|
636
|
+
if (staticVal !== undefined) {
|
|
637
|
+
attrObj['show'] = staticVal;
|
|
638
|
+
} else if (pathTestRE.test(showVal)) {
|
|
639
|
+
attrObj['$show'] = showVal;
|
|
640
|
+
hasBind = true;
|
|
641
|
+
} else {
|
|
642
|
+
attrObj['$show'] = `function () { return ${addThisPrefix(showVal)}; }`;
|
|
643
|
+
hasBind = true;
|
|
644
|
+
}
|
|
548
645
|
}
|
|
549
646
|
}
|
|
550
647
|
} else if (name === 'for') {
|
|
@@ -764,15 +861,15 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
764
861
|
// @media rules are applied at runtime by SDK, not inlined here.
|
|
765
862
|
// Class rules apply in stylesheet declaration order (later declarations override earlier),
|
|
766
863
|
// NOT in class-attribute order.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
for (const tok of p.trim().split(/\s+/)) if (tok) staticClassTokens.push(tok);
|
|
774
|
-
}
|
|
864
|
+
const staticClassTokens = [];
|
|
865
|
+
if (className) {
|
|
866
|
+
const parts = className.split(/(\{\{[\s\S]*?\}\})/).filter(Boolean);
|
|
867
|
+
for (const p of parts) {
|
|
868
|
+
if (/^\{\{[\s\S]*?\}\}$/.test(p)) continue;
|
|
869
|
+
for (const tok of p.trim().split(/\s+/)) if (tok) staticClassTokens.push(tok);
|
|
775
870
|
}
|
|
871
|
+
}
|
|
872
|
+
if (styleSheet) {
|
|
776
873
|
const hasMedia = hasApplicableMediaRule(styleSheet, el.tagName, staticClassTokens);
|
|
777
874
|
// Skip class-rule merge when the node has any dynamic binding OR any @media
|
|
778
875
|
// rule that applies to it — runtime must resolve class chain against the
|
|
@@ -794,11 +891,19 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
794
891
|
if (Object.keys(inlined).length) node.style = inlined;
|
|
795
892
|
} else {
|
|
796
893
|
const merged = {};
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
894
|
+
const classSet = new Set(staticClassTokens);
|
|
895
|
+
for (const key of Object.keys(styleSheet)) {
|
|
896
|
+
if (key.startsWith('@')) continue;
|
|
897
|
+
if (key === el.tagName) {
|
|
898
|
+
Object.assign(merged, styleSheet[key]);
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
if (key.length > 1 && key.startsWith('.') && !/[\s>+~.]/.test(key.slice(1))) {
|
|
902
|
+
if (classSet.has(key.slice(1))) Object.assign(merged, styleSheet[key]);
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
if (/[\s>+~]/.test(key) || /\.[\w-]+\./.test(key)) {
|
|
906
|
+
if (selectorMatchesElement(key, el.tagName, classSet, ancestors)) {
|
|
802
907
|
Object.assign(merged, styleSheet[key]);
|
|
803
908
|
}
|
|
804
909
|
}
|
|
@@ -823,7 +928,10 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
823
928
|
const isMixedContent = hasElementChildren && hasTextChildren && (tagName === 'text' || tagName === 'span' || tagName === 'a' || tagName === 'marquee');
|
|
824
929
|
for (const child of el.childNodes || []) {
|
|
825
930
|
if (child.tagName) {
|
|
826
|
-
childNodes.push(elementToJson(child, styleSheet, importMap, scopeVars, pageDir
|
|
931
|
+
childNodes.push(elementToJson(child, styleSheet, importMap, scopeVars, pageDir, [...ancestors, {
|
|
932
|
+
tag: el.tagName,
|
|
933
|
+
classes: new Set(staticClassTokens)
|
|
934
|
+
}]));
|
|
827
935
|
} else if (isMixedContent && child.value?.trim()) {
|
|
828
936
|
const emitted = emitTextValueAttr(child.value);
|
|
829
937
|
const spanNode = {
|
|
@@ -11,7 +11,9 @@ declare class ViteCompiler implements ICompiler {
|
|
|
11
11
|
clean(param: ICompileParam & IJavascriptCompileOption): Promise<void>;
|
|
12
12
|
}
|
|
13
13
|
declare function stripDeadDefProp(code: string): string;
|
|
14
|
+
declare function mergeStyleSheets(app: any, page: any): any;
|
|
14
15
|
export declare const __test: {
|
|
15
16
|
stripDeadDefProp: typeof stripDeadDefProp;
|
|
17
|
+
mergeStyleSheets: typeof mergeStyleSheets;
|
|
16
18
|
};
|
|
17
19
|
export default ViteCompiler;
|
|
@@ -90,12 +90,43 @@ function rewriteSystemImports(code) {
|
|
|
90
90
|
replacement: parts.join(' ')
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
+
// Rewrite CJS require() calls for system modules: require('@system.xxx') → $app_require$("@app-module/system.xxx")
|
|
94
|
+
collectRequireEdits(ast, edits);
|
|
93
95
|
if (edits.length === 0) return code;
|
|
94
96
|
edits.sort((a, b) => b.start - a.start);
|
|
95
97
|
let out = code;
|
|
96
98
|
for (const e of edits) out = out.slice(0, e.start) + e.replacement + out.slice(e.end);
|
|
97
99
|
return out;
|
|
98
100
|
}
|
|
101
|
+
function collectRequireEdits(node, edits) {
|
|
102
|
+
if (!node || typeof node !== 'object') return;
|
|
103
|
+
if (node.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'require' && node.arguments?.length === 1 && node.arguments[0].type === 'Literal' && typeof node.arguments[0].value === 'string') {
|
|
104
|
+
const src = node.arguments[0].value;
|
|
105
|
+
let moduleName = null;
|
|
106
|
+
if (NS_PREFIX.test(src)) {
|
|
107
|
+
moduleName = src.replace(NS_PREFIX, '$1.');
|
|
108
|
+
} else if (src.startsWith(APP_MODULE_PREFIX)) {
|
|
109
|
+
moduleName = src.slice(APP_MODULE_PREFIX.length);
|
|
110
|
+
}
|
|
111
|
+
if (moduleName !== null) {
|
|
112
|
+
edits.push({
|
|
113
|
+
start: node.start,
|
|
114
|
+
end: node.end,
|
|
115
|
+
replacement: `$app_require$("${APP_MODULE_PREFIX}${moduleName}")`
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const key of Object.keys(node)) {
|
|
121
|
+
if (key === 'start' || key === 'end' || key === 'type') continue;
|
|
122
|
+
const val = node[key];
|
|
123
|
+
if (Array.isArray(val)) {
|
|
124
|
+
for (const child of val) collectRequireEdits(child, edits);
|
|
125
|
+
} else if (val && typeof val === 'object' && val.type) {
|
|
126
|
+
collectRequireEdits(val, edits);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
99
130
|
function loadUserViteConfig(projectPath, mode) {
|
|
100
131
|
const configPath = _path.default.join(projectPath, 'quickapp.config.js');
|
|
101
132
|
if (!_fsExtra.default.existsSync(configPath)) return {};
|
|
@@ -246,6 +277,7 @@ class ViteCompiler {
|
|
|
246
277
|
}
|
|
247
278
|
const entryFailures = [];
|
|
248
279
|
let entryAttempted = 0;
|
|
280
|
+
let appStyleSheet = {};
|
|
249
281
|
for (const [entryName, entryValue] of Object.entries(entries)) {
|
|
250
282
|
const entryPath = entryValue.split('?')[0];
|
|
251
283
|
const resolvedEntry = _path.default.resolve(originalProjectPath, entryPath);
|
|
@@ -396,6 +428,7 @@ class ViteCompiler {
|
|
|
396
428
|
});
|
|
397
429
|
let templateNode = null;
|
|
398
430
|
const importMap = {}; // name -> path
|
|
431
|
+
const componentsMap = {}; // originalName -> path
|
|
399
432
|
for (const node of doc.childNodes) {
|
|
400
433
|
if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
|
|
401
434
|
const nameAttr = node.attrs?.find(a => a.name === 'name');
|
|
@@ -404,6 +437,7 @@ class ViteCompiler {
|
|
|
404
437
|
const compAbsPath = _path.default.resolve(_path.default.dirname(resolvedEntry), srcAttr.value).replace(/\.ux$/, '');
|
|
405
438
|
const compPath = _path.default.relative(srcPath, compAbsPath).replace(/\\/g, '/');
|
|
406
439
|
importMap[nameAttr.value.toLowerCase()] = compPath;
|
|
440
|
+
componentsMap[nameAttr.value] = compPath;
|
|
407
441
|
}
|
|
408
442
|
}
|
|
409
443
|
}
|
|
@@ -427,6 +461,9 @@ class ViteCompiler {
|
|
|
427
461
|
if (styleLiteral) {
|
|
428
462
|
styleSheet = (0, _TemplateCompiler.parseStyleArray)(styleLiteral);
|
|
429
463
|
}
|
|
464
|
+
if (isApp) {
|
|
465
|
+
appStyleSheet = styleSheet;
|
|
466
|
+
}
|
|
430
467
|
// Write css.json
|
|
431
468
|
const cssPath = _path.default.join(buildPath, `${isApp ? 'app' : pageName}.css.json`);
|
|
432
469
|
_fsExtra.default.ensureDirSync(_path.default.dirname(cssPath));
|
|
@@ -439,7 +476,8 @@ class ViteCompiler {
|
|
|
439
476
|
if (templateNode && !isApp) {
|
|
440
477
|
const tplPath = _path.default.join(buildPath, `${pageName}.template.json`);
|
|
441
478
|
_fsExtra.default.ensureDirSync(_path.default.dirname(tplPath));
|
|
442
|
-
|
|
479
|
+
const mergedSheet = mergeStyleSheets(appStyleSheet, styleSheet);
|
|
480
|
+
_fsExtra.default.writeJSONSync(tplPath, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergedSheet, importMap, _path.default.dirname(pageName), componentsMap), param.mode === 'production' ? undefined : {
|
|
443
481
|
spaces: 2
|
|
444
482
|
});
|
|
445
483
|
// Worklist BFS over nested <import> chain so transitively imported
|
|
@@ -469,6 +507,7 @@ class ViteCompiler {
|
|
|
469
507
|
});
|
|
470
508
|
let compTpl = null;
|
|
471
509
|
const compImportMap = {};
|
|
510
|
+
const compComponentsMap = {};
|
|
472
511
|
for (const node of compDoc.childNodes) {
|
|
473
512
|
if (node.nodeName === 'template') compTpl = node;else if (node.nodeName === 'import') {
|
|
474
513
|
const n = node.attrs?.find(a => a.name === 'name');
|
|
@@ -477,6 +516,7 @@ class ViteCompiler {
|
|
|
477
516
|
const nestedAbsPath = _path.default.resolve(_path.default.dirname(compUxPath), s.value).replace(/\.ux$/, '');
|
|
478
517
|
const nestedPath = _path.default.relative(srcPath, nestedAbsPath).replace(/\\/g, '/');
|
|
479
518
|
compImportMap[n.value.toLowerCase()] = nestedPath;
|
|
519
|
+
compComponentsMap[n.value] = nestedPath;
|
|
480
520
|
if (!visited.has(nestedPath)) {
|
|
481
521
|
worklist.push({
|
|
482
522
|
compName: n.value.toLowerCase(),
|
|
@@ -504,7 +544,7 @@ class ViteCompiler {
|
|
|
504
544
|
compStyleSheet = (0, _TemplateCompiler.parseStyleArray)(csm);
|
|
505
545
|
}
|
|
506
546
|
const compSid = (0, _TemplateCompiler.getStyleObjectId)(compPath);
|
|
507
|
-
_fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, compStyleSheet, compImportMap, _path.default.dirname(compPath)), param.mode === 'production' ? undefined : {
|
|
547
|
+
_fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, mergeStyleSheets(appStyleSheet, compStyleSheet), compImportMap, _path.default.dirname(compPath), compComponentsMap), param.mode === 'production' ? undefined : {
|
|
508
548
|
spaces: 2
|
|
509
549
|
});
|
|
510
550
|
const compCssPath = _path.default.join(buildPath, `${compPath}.css.json`);
|
|
@@ -594,13 +634,16 @@ class ViteCompiler {
|
|
|
594
634
|
});
|
|
595
635
|
let templateNode = null;
|
|
596
636
|
const importMap = {};
|
|
637
|
+
const componentsMap = {};
|
|
597
638
|
for (const node of doc.childNodes) {
|
|
598
639
|
if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
|
|
599
640
|
const nameAttr = node.attrs?.find(a => a.name === 'name');
|
|
600
641
|
const srcAttr = node.attrs?.find(a => a.name === 'src');
|
|
601
642
|
if (nameAttr && srcAttr) {
|
|
602
643
|
const compPath = _path.default.resolve(_path.default.dirname(uxFile), srcAttr.value).replace(/\.ux$/, '');
|
|
603
|
-
|
|
644
|
+
const rel = _path.default.relative(srcPath, compPath).replace(/\\/g, '/');
|
|
645
|
+
importMap[nameAttr.value.toLowerCase()] = rel;
|
|
646
|
+
componentsMap[nameAttr.value] = rel;
|
|
604
647
|
}
|
|
605
648
|
}
|
|
606
649
|
}
|
|
@@ -630,7 +673,7 @@ class ViteCompiler {
|
|
|
630
673
|
// Generate template.json
|
|
631
674
|
if (templateNode) {
|
|
632
675
|
_fsExtra.default.ensureDirSync(_path.default.dirname(outputTpl));
|
|
633
|
-
_fsExtra.default.writeJSONSync(outputTpl, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, styleSheet, Object.keys(importMap).length ? importMap : undefined, _path.default.dirname(relPath)), param.mode === 'production' ? undefined : {
|
|
676
|
+
_fsExtra.default.writeJSONSync(outputTpl, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, mergeStyleSheets(appStyleSheet, styleSheet), Object.keys(importMap).length ? importMap : undefined, _path.default.dirname(relPath), Object.keys(componentsMap).length ? componentsMap : undefined), param.mode === 'production' ? undefined : {
|
|
634
677
|
spaces: 2
|
|
635
678
|
});
|
|
636
679
|
}
|
|
@@ -708,6 +751,29 @@ function wrapOutput(code, entryName, isApp) {
|
|
|
708
751
|
});
|
|
709
752
|
// Remove Object.defineProperty for Symbol.toStringTag
|
|
710
753
|
code = code.replace(/\s*Object\.defineProperty\(\w+,\s*Symbol\.toStringTag[^;]*;\s*/g, '');
|
|
754
|
+
// Rewrite __require("@system.*") → $app_require$("@app-module/system.*") in rolldown output.
|
|
755
|
+
// Rolldown emits __require when CJS require() survives bundling (aliased require, dynamic
|
|
756
|
+
// concat, or patterns the pre-transform couldn't catch). Also catch _require() which appears
|
|
757
|
+
// when the original code does `var _require = require; _require('@system.xxx')`.
|
|
758
|
+
const sysRequirePattern = /\b_?_?require\(\s*"(@(?:system|service|android|hap)\.[^"]+)"\s*\)/g;
|
|
759
|
+
code = code.replace(sysRequirePattern, (_, mod) => {
|
|
760
|
+
const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
|
|
761
|
+
return `$app_require$("@app-module/${moduleName}")`;
|
|
762
|
+
});
|
|
763
|
+
// Same for @app-module/ prefix
|
|
764
|
+
code = code.replace(/\b_?_?require\(\s*"(@app-module\/[^"]+)"\s*\)/g, (_, mod) => {
|
|
765
|
+
const moduleName = mod.slice('@app-module/'.length);
|
|
766
|
+
return `$app_require$("@app-module/${moduleName}")`;
|
|
767
|
+
});
|
|
768
|
+
// Also handle single-quoted variants
|
|
769
|
+
code = code.replace(/\b_?_?require\(\s*'(@(?:system|service|android|hap)\.[^']+)'\s*\)/g, (_, mod) => {
|
|
770
|
+
const moduleName = mod.replace(/^@(system|service|android|hap)\./, '$1.');
|
|
771
|
+
return `$app_require$("@app-module/${moduleName}")`;
|
|
772
|
+
});
|
|
773
|
+
// Remove the __require polyfill definition if it's no longer referenced anywhere
|
|
774
|
+
if (!/\b__require\b/.test(code)) {
|
|
775
|
+
code = code.replace(/var __require\s*=\s*\/\*[^*]*\*\/\s*\(\(x\)\s*=>[\s\S]*?}\);\n?/g, '');
|
|
776
|
+
}
|
|
711
777
|
// Extract the default export variable
|
|
712
778
|
let exportVar = '_default';
|
|
713
779
|
const m1 = code.match(/export\s*\{\s*(\w+)\s+as\s+default\s*\}/);
|
|
@@ -738,7 +804,33 @@ $app_define$("${defineId}", [], function($app_require$, $app_exports$, $app_modu
|
|
|
738
804
|
$app_bootstrap$("${bootstrapId}");
|
|
739
805
|
`;
|
|
740
806
|
}
|
|
807
|
+
function mergeStyleSheets(app, page) {
|
|
808
|
+
if (!app || !Object.keys(app).length) return page;
|
|
809
|
+
if (!page || !Object.keys(page).length) return app;
|
|
810
|
+
const merged = {
|
|
811
|
+
...app
|
|
812
|
+
};
|
|
813
|
+
for (const [k, v] of Object.entries(page)) {
|
|
814
|
+
if (k === '@KEYFRAMES' || k === '@FONT-FACE') {
|
|
815
|
+
merged[k] = {
|
|
816
|
+
...(merged[k] || {}),
|
|
817
|
+
...v
|
|
818
|
+
};
|
|
819
|
+
} else if (k === '@MEDIA') {
|
|
820
|
+
merged[k] = [...(merged[k] || []), ...v];
|
|
821
|
+
} else if (typeof v === 'object' && v !== null && typeof merged[k] === 'object' && merged[k] !== null) {
|
|
822
|
+
merged[k] = {
|
|
823
|
+
...merged[k],
|
|
824
|
+
...v
|
|
825
|
+
};
|
|
826
|
+
} else {
|
|
827
|
+
merged[k] = v;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
return merged;
|
|
831
|
+
}
|
|
741
832
|
const __test = exports.__test = {
|
|
742
|
-
stripDeadDefProp
|
|
833
|
+
stripDeadDefProp,
|
|
834
|
+
mergeStyleSheets
|
|
743
835
|
};
|
|
744
836
|
var _default = exports.default = ViteCompiler;
|
|
@@ -9,6 +9,9 @@ var path = _interopRequireWildcard(require("path"));
|
|
|
9
9
|
var _sharedUtils = require("@aiot-toolkit/shared-utils");
|
|
10
10
|
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); }
|
|
11
11
|
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; }
|
|
12
|
+
const REQUIRED_JSC_VERSION = '1.0.9';
|
|
13
|
+
const IIFE_WRAP_PREFIX = 'export default (function (__ctx) {\n' + ' let { requireModule, unRequireModule, $app_define$, $app_bootstrap$, $app_require$,\n' + ' console = global.console } = __ctx;\n' + ' let { setTimeout, clearTimeout, setInterval, clearInterval } = __ctx;\n\n';
|
|
14
|
+
const IIFE_WRAP_SUFFIX = '\n});\n';
|
|
12
15
|
class Jsc {
|
|
13
16
|
constructor(projectPath, buildPath) {
|
|
14
17
|
this.projectPath = projectPath;
|
|
@@ -23,8 +26,10 @@ class Jsc {
|
|
|
23
26
|
const beforeJsCount = Jsc.listFiles(buildPath, '.js').length;
|
|
24
27
|
return _sharedUtils.CommonUtil.requireNodeModule(projectPath, `@aiot-toolkit/jsc`).then(async module => {
|
|
25
28
|
this.logBeforeInvoke();
|
|
29
|
+
this.assertJscVersion();
|
|
30
|
+
Jsc.wrapAllJsWithIife(buildPath);
|
|
26
31
|
const start = Date.now();
|
|
27
|
-
const msg = await module.default(buildPath);
|
|
32
|
+
const msg = await module.default(buildPath, []);
|
|
28
33
|
const elapsed = Date.now() - start;
|
|
29
34
|
if (msg) {
|
|
30
35
|
_sharedUtils.ColorConsole.success({
|
|
@@ -119,5 +124,42 @@ class Jsc {
|
|
|
119
124
|
walk(dir);
|
|
120
125
|
return out;
|
|
121
126
|
}
|
|
127
|
+
assertJscVersion() {
|
|
128
|
+
const {
|
|
129
|
+
projectPath
|
|
130
|
+
} = this;
|
|
131
|
+
const jscName = '@aiot-toolkit/jsc';
|
|
132
|
+
try {
|
|
133
|
+
const pkgJsonPath = require.resolve(`${jscName}/package.json`, {
|
|
134
|
+
paths: [projectPath]
|
|
135
|
+
});
|
|
136
|
+
const pkg = require(pkgJsonPath);
|
|
137
|
+
const version = pkg.version || '0.0.0';
|
|
138
|
+
if (Jsc.compareSemver(version, REQUIRED_JSC_VERSION) < 0) {
|
|
139
|
+
_sharedUtils.ColorConsole.throw(`[jsc] ${jscName}@${version} is too old — need >= ${REQUIRED_JSC_VERSION}. ` + `Run: npm i ${jscName}@^${REQUIRED_JSC_VERSION}`);
|
|
140
|
+
throw new Error(`[jsc] ${jscName} must be >= ${REQUIRED_JSC_VERSION}, got ${version}`);
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (e?.message?.includes(`must be >= ${REQUIRED_JSC_VERSION}`)) throw e;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
static wrapAllJsWithIife(buildPath) {
|
|
147
|
+
for (const {
|
|
148
|
+
rel
|
|
149
|
+
} of Jsc.listFiles(buildPath, '.js')) {
|
|
150
|
+
const abs = path.join(buildPath, rel);
|
|
151
|
+
const body = fs.readFileSync(abs, 'utf-8');
|
|
152
|
+
if (body.startsWith('export default (function (__ctx)')) continue;
|
|
153
|
+
fs.writeFileSync(abs, IIFE_WRAP_PREFIX + body + IIFE_WRAP_SUFFIX, 'utf-8');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
static compareSemver(a, b) {
|
|
157
|
+
const parse = v => v.replace(/^[\^~=v]/, '').split(/[.-]/).slice(0, 3).map(p => parseInt(p, 10) || 0);
|
|
158
|
+
const [a1, a2, a3] = parse(a);
|
|
159
|
+
const [b1, b2, b3] = parse(b);
|
|
160
|
+
if (a1 !== b1) return a1 - b1;
|
|
161
|
+
if (a2 !== b2) return a2 - b2;
|
|
162
|
+
return a3 - b3;
|
|
163
|
+
}
|
|
122
164
|
}
|
|
123
165
|
var _default = exports.default = Jsc;
|
|
@@ -153,8 +153,17 @@ class ZipUtil {
|
|
|
153
153
|
// basename from manifest.icon (e.g. `/resources/base/media/icon_small.png`
|
|
154
154
|
// → `icon_small.vug` at rpk root) so runtime + IDE previews can look it up
|
|
155
155
|
// by the manifest-declared name.
|
|
156
|
-
|
|
157
|
-
const
|
|
156
|
+
const runtimeIconPath = (() => {
|
|
157
|
+
const buildManifest = _path.default.join(buildDir, 'manifest.json');
|
|
158
|
+
if (_fsExtra.default.existsSync(buildManifest)) {
|
|
159
|
+
try {
|
|
160
|
+
return _fsExtra.default.readJSONSync(buildManifest).icon;
|
|
161
|
+
} catch {/* fall through */}
|
|
162
|
+
}
|
|
163
|
+
return config.icon;
|
|
164
|
+
})();
|
|
165
|
+
if (runtimeIconPath) {
|
|
166
|
+
const iconPath = _path.default.join(buildDir, runtimeIconPath.replace(/^\//, ''));
|
|
158
167
|
if (_fsExtra.default.existsSync(iconPath)) {
|
|
159
168
|
const iconBuf = _fsExtra.default.readFileSync(iconPath);
|
|
160
169
|
outerPackage.addResource({
|
package/lib/config/UxConfig.js
CHANGED
|
@@ -86,6 +86,9 @@ class UxConfig {
|
|
|
86
86
|
}, {
|
|
87
87
|
worker: _UxAfterCompile.default.copyResource,
|
|
88
88
|
workerDescribe: 'Copy resource files'
|
|
89
|
+
}, {
|
|
90
|
+
worker: _UxAfterCompile.default.relocateManifestIcon,
|
|
91
|
+
workerDescribe: 'Move manifest.icon to build root + rewrite refs'
|
|
89
92
|
}, {
|
|
90
93
|
worker: _UxAfterCompile.default.compressResource,
|
|
91
94
|
workerDescribe: 'Compress resource files'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiot-toolkit/aiotpack",
|
|
3
|
-
"version": "2.1.0-prender.
|
|
3
|
+
"version": "2.1.0-prender.13",
|
|
4
4
|
"description": "The process tool for packaging aiot projects.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aiotpack"
|
|
@@ -19,16 +19,16 @@
|
|
|
19
19
|
"test": "node ./__tests__/aiotpack.test.js"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@aiot-toolkit/generator": "2.1.0-prender.
|
|
23
|
-
"@aiot-toolkit/parser": "2.1.0-prender.
|
|
24
|
-
"@aiot-toolkit/shared-utils": "2.1.0-prender.
|
|
22
|
+
"@aiot-toolkit/generator": "2.1.0-prender.13",
|
|
23
|
+
"@aiot-toolkit/parser": "2.1.0-prender.13",
|
|
24
|
+
"@aiot-toolkit/shared-utils": "2.1.0-prender.13",
|
|
25
25
|
"@hap-toolkit/aaptjs": "^2.0.0",
|
|
26
26
|
"@rspack/core": "^1.3.9",
|
|
27
27
|
"acorn": "^8.16.0",
|
|
28
28
|
"aiot-parse5": "^1.0.2",
|
|
29
29
|
"astring": "^1.9.0",
|
|
30
30
|
"babel-loader": "^9.1.3",
|
|
31
|
-
"file-lane": "2.1.0-prender.
|
|
31
|
+
"file-lane": "2.1.0-prender.13",
|
|
32
32
|
"file-loader": "^6.2.0",
|
|
33
33
|
"fs-extra": "^11.2.0",
|
|
34
34
|
"jsrsasign": "^11.1.0",
|