@aiot-toolkit/aiotpack 2.1.0-prender.6 → 2.1.0-prender.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.
|
@@ -281,6 +281,50 @@ function addThisPrefix(expr, extraReserved) {
|
|
|
281
281
|
}).join('');
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
|
+
function emitTextValueAttr(rawText) {
|
|
285
|
+
const text = rawText.trim();
|
|
286
|
+
if (!/\{\{[\s\S]*?\}\}/.test(text)) {
|
|
287
|
+
return {
|
|
288
|
+
attr: {
|
|
289
|
+
value: text.replace(/\s*\n\s*/g, ' ')
|
|
290
|
+
},
|
|
291
|
+
needsBind: false
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
const parts = text.split(/(\{\{[\s\S]*?\}\})/);
|
|
295
|
+
const exprs = parts.filter(Boolean).map(p => {
|
|
296
|
+
const m = p.match(/^\{\{([\s\S]*?)\}\}$/);
|
|
297
|
+
if (m) return addThisPrefix(m[1].trim());
|
|
298
|
+
return `'${p.replace(/'/g, "\\'")}'`;
|
|
299
|
+
});
|
|
300
|
+
if (exprs.length === 1 && pathTestRE.test(exprs[0].replace(/^this\./, ''))) {
|
|
301
|
+
return {
|
|
302
|
+
attr: {
|
|
303
|
+
$value: exprs[0].replace(/^this\./, '')
|
|
304
|
+
},
|
|
305
|
+
needsBind: true
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
if (exprs.length === 1) {
|
|
309
|
+
return {
|
|
310
|
+
attr: {
|
|
311
|
+
$value: `function () { return ${exprs[0]}; }`
|
|
312
|
+
},
|
|
313
|
+
needsBind: true
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const wrapped = exprs.map(e => {
|
|
317
|
+
if (e.startsWith("'") || e.startsWith('"')) return e;
|
|
318
|
+
if (/(\|\||&&|\?\s|\+)/.test(e) && !e.startsWith('(')) return `(${e})`;
|
|
319
|
+
return e;
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
attr: {
|
|
323
|
+
$value: `function () { return '' + ${wrapped.join(' + ')}; }`
|
|
324
|
+
},
|
|
325
|
+
needsBind: true
|
|
326
|
+
};
|
|
327
|
+
}
|
|
284
328
|
function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
285
329
|
const tagName = el.tagName === 'img' ? 'image' : el.tagName;
|
|
286
330
|
const node = {
|
|
@@ -491,8 +535,11 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
491
535
|
hasBind = true;
|
|
492
536
|
} else {
|
|
493
537
|
let staticVal = value ? value.replace(/ {2,}/g, ' ') : '';
|
|
494
|
-
// Normalize relative path attrs (src, href) to absolute paths from src root
|
|
495
|
-
|
|
538
|
+
// Normalize relative path attrs (src, href, alt) to absolute paths from src root.
|
|
539
|
+
// alt can also carry prose (e.g. "blank") — only rewrite when the value starts with
|
|
540
|
+
// ./ or ../ so image alt-text prose passes through untouched.
|
|
541
|
+
const isRelPath = staticVal.startsWith('./') || staticVal.startsWith('../');
|
|
542
|
+
if (staticVal && isRelPath && (name === 'src' || name === 'href' || name === 'alt') && pageDir) {
|
|
496
543
|
// Resolve relative to pageDir, then make absolute from src root
|
|
497
544
|
const segments = pageDir.split('/').filter(Boolean).concat(staticVal.split('/'));
|
|
498
545
|
const stack = [];
|
|
@@ -509,34 +556,9 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
509
556
|
for (const child of el.childNodes || []) {
|
|
510
557
|
const textElements = new Set(['text', 'span', 'a', 'input', 'qrcode', 'barcode', 'marquee', 'arc-text', 'option', 'button', 'label', 'textarea', 'richtext']);
|
|
511
558
|
if (child.value?.trim() && !child.tagName && !(el.childNodes || []).some(c => c.tagName) && textElements.has(tagName)) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
if (
|
|
515
|
-
// Build function expression from template literal
|
|
516
|
-
// Trim surrounding whitespace before splitting (vivo ignores indentation whitespace)
|
|
517
|
-
const trimmedText = text.trim();
|
|
518
|
-
const parts = trimmedText.split(/(\{\{[\s\S]*?\}\})/);
|
|
519
|
-
const exprs = parts.filter(Boolean).map(p => {
|
|
520
|
-
const m = p.match(/^\{\{([\s\S]*?)\}\}$/);
|
|
521
|
-
if (m) return addThisPrefix(m[1].trim());
|
|
522
|
-
return `'${p.replace(/'/g, "\\'")}'`;
|
|
523
|
-
});
|
|
524
|
-
if (exprs.length === 1 && pathTestRE.test(exprs[0].replace(/^this\./, ''))) {
|
|
525
|
-
attrObj['$value'] = exprs[0].replace(/^this\./, '');
|
|
526
|
-
} else if (exprs.length === 1) {
|
|
527
|
-
attrObj['$value'] = `function () { return ${exprs[0]}; }`;
|
|
528
|
-
} else {
|
|
529
|
-
const wrappedExprs = exprs.map(e => {
|
|
530
|
-
if (e.startsWith("'") || e.startsWith('"')) return e;
|
|
531
|
-
if (/(\|\||&&|\?\s|\+)/.test(e) && !e.startsWith('(')) return `(${e})`;
|
|
532
|
-
return e;
|
|
533
|
-
});
|
|
534
|
-
attrObj['$value'] = `function () { return '' + ${wrappedExprs.join(' + ')}; }`;
|
|
535
|
-
}
|
|
536
|
-
hasBind = true;
|
|
537
|
-
} else {
|
|
538
|
-
attrObj['value'] = text.replace(/\s*\n\s*/g, ' ');
|
|
539
|
-
}
|
|
559
|
+
const emitted = emitTextValueAttr(child.value);
|
|
560
|
+
Object.assign(attrObj, emitted.attr);
|
|
561
|
+
if (emitted.needsBind) hasBind = true;
|
|
540
562
|
}
|
|
541
563
|
}
|
|
542
564
|
// Output in vivo order: attr → bind → class → events → import → style → children
|
|
@@ -572,13 +594,19 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
572
594
|
}
|
|
573
595
|
if (Object.keys(events).length) node.events = events;
|
|
574
596
|
// Inline style from styleSheet (class selector + tag selector) + static portion of style="..."
|
|
597
|
+
// Inline style from styleSheet (class selector + tag selector) + static portion of style="...".
|
|
575
598
|
// Only base (non-@media) selectors are inlined; @media rules are applied at runtime by SDK.
|
|
599
|
+
// Class rules apply in stylesheet declaration order (later declarations override earlier),
|
|
600
|
+
// NOT in class-attribute order.
|
|
576
601
|
if (styleSheet) {
|
|
577
602
|
const merged = {};
|
|
578
603
|
if (styleSheet[el.tagName]) Object.assign(merged, styleSheet[el.tagName]);
|
|
579
604
|
if (className && !hasDynClass) {
|
|
580
|
-
|
|
581
|
-
|
|
605
|
+
const classSet = new Set(className.split(/\s+/).filter(Boolean));
|
|
606
|
+
for (const key of Object.keys(styleSheet)) {
|
|
607
|
+
if (key.length > 1 && key.startsWith('.') && classSet.has(key.slice(1))) {
|
|
608
|
+
Object.assign(merged, styleSheet[key]);
|
|
609
|
+
}
|
|
582
610
|
}
|
|
583
611
|
}
|
|
584
612
|
Object.assign(merged, staticInlineStyle);
|
|
@@ -597,14 +625,12 @@ function elementToJson(el, styleSheet, importMap, scopeVars, pageDir) {
|
|
|
597
625
|
if (child.tagName) {
|
|
598
626
|
childNodes.push(elementToJson(child, styleSheet, importMap, scopeVars, pageDir));
|
|
599
627
|
} else if (isMixedContent && child.value?.trim()) {
|
|
600
|
-
|
|
601
|
-
const text = child.value.replace(/[ \t]*\n[ \t]*/g, ' ').replace(/ {2,}/g, ' ');
|
|
628
|
+
const emitted = emitTextValueAttr(child.value);
|
|
602
629
|
const spanNode = {
|
|
603
630
|
type: 'span',
|
|
604
|
-
attr:
|
|
605
|
-
value: text
|
|
606
|
-
}
|
|
631
|
+
attr: emitted.attr
|
|
607
632
|
};
|
|
633
|
+
if (emitted.needsBind) spanNode.bind = 1;
|
|
608
634
|
childNodes.push(spanNode);
|
|
609
635
|
}
|
|
610
636
|
}
|
|
@@ -10,4 +10,8 @@ declare class ViteCompiler implements ICompiler {
|
|
|
10
10
|
compile(param: IJavascriptCompileOption): Promise<void>;
|
|
11
11
|
clean(param: ICompileParam & IJavascriptCompileOption): Promise<void>;
|
|
12
12
|
}
|
|
13
|
+
declare function stripDeadDefProp(code: string): string;
|
|
14
|
+
export declare const __test: {
|
|
15
|
+
stripDeadDefProp: typeof stripDeadDefProp;
|
|
16
|
+
};
|
|
13
17
|
export default ViteCompiler;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = void 0;
|
|
6
|
+
exports.default = exports.__test = void 0;
|
|
7
7
|
var _TemplateCompiler = require("./TemplateCompiler");
|
|
8
8
|
var _path = _interopRequireDefault(require("path"));
|
|
9
9
|
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
@@ -208,6 +208,16 @@ class ViteCompiler {
|
|
|
208
208
|
external: id => id.startsWith('@app-module/') || /^@(system|service|android|hap)\./.test(id),
|
|
209
209
|
output: {
|
|
210
210
|
globals: id => `$app_require$("@app-module/${id.replace(/^@(system|service|android|hap|app-module)\./, '')}")`
|
|
211
|
+
},
|
|
212
|
+
onwarn(warning, defaultHandler) {
|
|
213
|
+
// Rolldown silently emits `(void 0)()` for namespace-member accesses whose
|
|
214
|
+
// name is not exported by the target module — leaves runtime with an opaque
|
|
215
|
+
// TypeError instead of the source identifier. Escalate to a build error so
|
|
216
|
+
// the source location surfaces before ship.
|
|
217
|
+
if (warning.code === 'IMPORT_IS_UNDEFINED') {
|
|
218
|
+
throw new Error(`[toolkit] ${warning.message ?? 'IMPORT_IS_UNDEFINED'} — this would silently emit (void 0)() at the call site.`);
|
|
219
|
+
}
|
|
220
|
+
defaultHandler(warning);
|
|
211
221
|
}
|
|
212
222
|
},
|
|
213
223
|
commonjsOptions: {
|
|
@@ -249,6 +259,26 @@ class ViteCompiler {
|
|
|
249
259
|
map: null
|
|
250
260
|
} : null;
|
|
251
261
|
}
|
|
262
|
+
}, {
|
|
263
|
+
name: 'namespace-preserve',
|
|
264
|
+
enforce: 'pre',
|
|
265
|
+
transform(code, id) {
|
|
266
|
+
if (!/import\s*\*\s*as\s+\w+\s+from/.test(code)) return null;
|
|
267
|
+
// Rolldown resolves `import * as L from './x'; L.foo()` at compile time —
|
|
268
|
+
// if `foo` isn't exported by `./x` the call collapses to `(void 0)()` and
|
|
269
|
+
// the source identifier is lost. Rewriting the alias to a runtime variable
|
|
270
|
+
// (with webpack-style default-interop) preserves the identifier so runtime
|
|
271
|
+
// errors point at the actual source name.
|
|
272
|
+
const out = code.replace(/import\s*\*\s*as\s+(\w+)\s+from\s+(['"][^'"]+['"])/g, (_m, local, src) => {
|
|
273
|
+
const ns = `__${local}_ns`,
|
|
274
|
+
key = `__${local}_key`;
|
|
275
|
+
return `import * as ${ns} from ${src}; const ${key} = 'default'; const ${local} = ${ns}[${key}] != null ? ${ns}[${key}] : ${ns};`;
|
|
276
|
+
});
|
|
277
|
+
return out !== code ? {
|
|
278
|
+
code: out,
|
|
279
|
+
map: null
|
|
280
|
+
} : null;
|
|
281
|
+
}
|
|
252
282
|
}, {
|
|
253
283
|
name: 'ux-loader',
|
|
254
284
|
resolveId(source, importer) {
|
|
@@ -432,10 +462,13 @@ class ViteCompiler {
|
|
|
432
462
|
});
|
|
433
463
|
}
|
|
434
464
|
}
|
|
435
|
-
if (
|
|
465
|
+
if (entryFailures.length > 0) {
|
|
466
|
+
// Any per-entry failure fails the whole build — silently shipping an rpk with
|
|
467
|
+
// one page missing is exactly the class of bug that lets `(void 0)()` /
|
|
468
|
+
// empty jsc / dropped app.js leak to users.
|
|
436
469
|
const sample = entryFailures.slice(0, 3).map(f => ` ${f.entry}: ${f.error}`).join('\n');
|
|
437
470
|
const more = entryFailures.length > 3 ? `\n ...and ${entryFailures.length - 3} more` : '';
|
|
438
|
-
throw new Error(`vite build failed for
|
|
471
|
+
throw new Error(`vite build failed for ${entryFailures.length}/${entryAttempted} entry page(s).\n` + `Failures:\n${sample}${more}`);
|
|
439
472
|
}
|
|
440
473
|
// Second pass: compile ALL .ux files that weren't entry pages
|
|
441
474
|
// Each .ux file gets its own template.json + css.json + js
|
|
@@ -531,6 +564,10 @@ class ViteCompiler {
|
|
|
531
564
|
_UxCompileUtil.default.clean([outputPath, releasePath].map(item => _path.default.resolve(projectPath, item)));
|
|
532
565
|
}
|
|
533
566
|
}
|
|
567
|
+
function stripDeadDefProp(code) {
|
|
568
|
+
const withoutDefine = code.replace(/var __defProp = Object\.defineProperty;\n?/g, '');
|
|
569
|
+
return /\b__defProp\s*\(/.test(withoutDefine) ? code : withoutDefine;
|
|
570
|
+
}
|
|
534
571
|
function wrapOutput(code, entryName, isApp) {
|
|
535
572
|
const componentName = _path.default.parse(entryName).name;
|
|
536
573
|
const defineId = isApp ? '@app-component/app' : `@app-component/${componentName}`;
|
|
@@ -561,8 +598,10 @@ function wrapOutput(code, entryName, isApp) {
|
|
|
561
598
|
// Remove rolldown region comments
|
|
562
599
|
code = code.replace(/\/\/#region[^\n]*\n/g, '');
|
|
563
600
|
code = code.replace(/\/\/#endregion[^\n]*/g, '');
|
|
564
|
-
// Remove rolldown runtime helpers
|
|
565
|
-
|
|
601
|
+
// Remove rolldown runtime helpers. __defProp is only dead when nothing else calls it;
|
|
602
|
+
// when the CJS→ESM interop chain (__toCommonJS / __copyProps / __publicField) survives
|
|
603
|
+
// tree-shaking, __defProp is referenced by those helpers and must stay.
|
|
604
|
+
code = stripDeadDefProp(code);
|
|
566
605
|
code = code.replace(/var __exportAll = [\s\S]*?return target;\s*\};\n?/g, '');
|
|
567
606
|
// Inline __exportAll calls: __exportAll({key: () => value, ...}) -> {key: value, ...}
|
|
568
607
|
// Match __exportAll(...) or /* @__PURE__ */ __exportAll(...)
|
|
@@ -603,4 +642,7 @@ $app_define$("${defineId}", [], function($app_require$, $app_exports$, $app_modu
|
|
|
603
642
|
$app_bootstrap$("${bootstrapId}");
|
|
604
643
|
`;
|
|
605
644
|
}
|
|
645
|
+
const __test = exports.__test = {
|
|
646
|
+
stripDeadDefProp
|
|
647
|
+
};
|
|
606
648
|
var _default = exports.default = ViteCompiler;
|
|
@@ -20,6 +20,7 @@ class Jsc {
|
|
|
20
20
|
projectPath,
|
|
21
21
|
buildPath
|
|
22
22
|
} = this;
|
|
23
|
+
const beforeJsCount = Jsc.listFiles(buildPath, '.js').length;
|
|
23
24
|
return _sharedUtils.CommonUtil.requireNodeModule(projectPath, `@aiot-toolkit/jsc`).then(async module => {
|
|
24
25
|
this.logBeforeInvoke();
|
|
25
26
|
const start = Date.now();
|
|
@@ -32,6 +33,15 @@ class Jsc {
|
|
|
32
33
|
}
|
|
33
34
|
this.logAfterInvoke(elapsed);
|
|
34
35
|
}).then(() => {
|
|
36
|
+
// aiotjsc silently exits 0 on Windows when the buildPath contains CJK chars
|
|
37
|
+
// (win32_aiotjsc.exe uses ANSI POSIX APIs) — leaves 0 .jsc while the delete step
|
|
38
|
+
// below removes all .js, shipping an empty VRU. Fail loud before the deletion
|
|
39
|
+
// runs so the source path issue surfaces at build time.
|
|
40
|
+
const afterJscCount = Jsc.listFiles(buildPath, '.jsc').length;
|
|
41
|
+
if (beforeJsCount > 0 && afterJscCount < beforeJsCount) {
|
|
42
|
+
_sharedUtils.ColorConsole.throw(`[jsc] silent failure: expected at least ${beforeJsCount} .jsc file(s) but got ${afterJscCount}. ` + `Most common cause on Windows: buildPath contains non-ASCII characters ` + `(rename the project directory to ASCII-only and rebuild).`);
|
|
43
|
+
return Promise.reject(new Error(`[jsc] produced ${afterJscCount} of ${beforeJsCount} expected .jsc files`));
|
|
44
|
+
}
|
|
35
45
|
if (deleteJs) {
|
|
36
46
|
return _sharedUtils.FileUtil.del(`${buildPath}/**/*.js`);
|
|
37
47
|
}
|
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.7",
|
|
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.7",
|
|
23
|
+
"@aiot-toolkit/parser": "2.1.0-prender.7",
|
|
24
|
+
"@aiot-toolkit/shared-utils": "2.1.0-prender.7",
|
|
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.7",
|
|
32
32
|
"file-loader": "^6.2.0",
|
|
33
33
|
"fs-extra": "^11.2.0",
|
|
34
34
|
"jsrsasign": "^11.1.0",
|