@aiot-toolkit/aiotpack 2.0.6-beta.8 → 2.1.0-prender.1
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 +4 -0
- package/lib/afterCompile/ux/UxAfterCompile.js +90 -2
- package/lib/compiler/javascript/JavascriptCompiler.js +11 -4
- package/lib/compiler/javascript/TemplateCompiler.d.ts +29 -0
- package/lib/compiler/javascript/TemplateCompiler.js +564 -0
- package/lib/compiler/javascript/ViteCompiler.d.ts +13 -0
- package/lib/compiler/javascript/ViteCompiler.js +414 -0
- package/lib/compiler/javascript/interface/IJavascriptCompileOption.d.ts +26 -0
- package/lib/compiler/javascript/vela/VelaWebpackConfigurator.d.ts +3 -1
- package/lib/compiler/javascript/vela/VelaWebpackConfigurator.js +16 -1
- package/lib/compiler/javascript/vela/interface/IManifest.d.ts +12 -0
- package/lib/compiler/javascript/vela/plugin/WrapPlugin.d.ts +10 -1
- package/lib/compiler/javascript/vela/plugin/WrapPlugin.js +241 -57
- package/lib/compiler/javascript/vela/utils/UxCompileUtil.d.ts +3 -2
- package/lib/compiler/javascript/vela/utils/UxCompileUtil.js +12 -4
- package/lib/compiler/javascript/vela/utils/VruUtil.d.ts +50 -0
- package/lib/compiler/javascript/vela/utils/VruUtil.js +128 -0
- package/lib/compiler/javascript/vela/utils/ZipUtil.d.ts +9 -0
- package/lib/compiler/javascript/vela/utils/ZipUtil.js +112 -6
- package/lib/compiler/javascript/vela/utils/webpackLoader/WebpackJsLoader.js +1 -1
- package/lib/config/UxConfig.d.ts +12 -5
- package/lib/config/UxConfig.js +7 -6
- package/lib/loader/ux/JsLoader.d.ts +9 -0
- package/lib/loader/ux/JsLoader.js +47 -8
- package/lib/loader/ux/vela/HmlLoader.d.ts +6 -6
- package/lib/loader/ux/vela/HmlLoader.js +30 -13
- package/lib/prerender/PrerenderVM.d.ts +86 -0
- package/lib/prerender/PrerenderVM.js +677 -0
- package/lib/prerender/StyleSerializer.d.ts +18 -0
- package/lib/prerender/StyleSerializer.js +92 -0
- package/lib/prerender/TemplateSerializer.d.ts +26 -0
- package/lib/prerender/TemplateSerializer.js +122 -0
- package/lib/prerender/index.d.ts +20 -0
- package/lib/prerender/index.js +519 -0
- package/lib/prerender/interface/IPrerenderOption.d.ts +15 -0
- package/lib/prerender/interface/IPrerenderOption.js +1 -0
- package/lib/utils/BeforeCompileUtils.d.ts +1 -1
- package/lib/utils/BeforeCompileUtils.js +52 -9
- package/lib/utils/ux/ManifestSchema.js +0 -1
- package/lib/utils/ux/UxFileUtils.js +1 -1
- package/lib/utils/ux/UxLoaderUtils.d.ts +6 -0
- package/lib/utils/ux/UxLoaderUtils.js +22 -10
- package/package.json +9 -6
|
@@ -14,6 +14,7 @@ var _BuildNameFormatType = _interopRequireDefault(require("../enum/BuildNameForm
|
|
|
14
14
|
var _Package = _interopRequireDefault(require("../model/Package"));
|
|
15
15
|
var _UxCompileUtil = _interopRequireDefault(require("./UxCompileUtil"));
|
|
16
16
|
var _SignUtil = _interopRequireDefault(require("./signature/SignUtil"));
|
|
17
|
+
var _VruUtil = require("./VruUtil");
|
|
17
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
19
|
/**
|
|
19
20
|
* Zip 用于将打包成功的 build 目录按特定规则压缩成 rpk
|
|
@@ -66,17 +67,122 @@ class ZipUtil {
|
|
|
66
67
|
_sharedUtils.ColorConsole.error(`The build file is missing, stop generating the application package, please check carefully`);
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
70
|
+
const signConfig = await _SignUtil.default.getProjectSignConfig(param);
|
|
71
|
+
const rpkFileName = this.getFileName(param, config, 'rpk');
|
|
72
|
+
|
|
73
|
+
// VRU mode: produce wrapped RPK (manifest + logo + CERT + inner-vru)
|
|
74
|
+
if (param.enableVru) {
|
|
75
|
+
const wrappedRpkBuffer = await this.createWrappedReleaseRpk(param, config, files, signConfig);
|
|
76
|
+
return await this.generateDistFile(wrappedRpkBuffer, param, rpkFileName);
|
|
77
|
+
}
|
|
69
78
|
|
|
70
|
-
//
|
|
79
|
+
// Flat mode (default): all build files directly in RPK
|
|
71
80
|
const {
|
|
72
81
|
fullPackage
|
|
73
82
|
} = await this.createPackagesDefinition(param, config, files);
|
|
74
|
-
|
|
75
|
-
// 生产出带签名的rpk文件buffer
|
|
76
|
-
const signConfig = await _SignUtil.default.getProjectSignConfig(param);
|
|
77
83
|
const rpkBuffer = await ZipUtil.buildProjectAndOutput(fullPackage, signConfig);
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
return await this.generateDistFile(rpkBuffer, param, rpkFileName);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Build the blueos-pack compatible "wrapped release" RPK.
|
|
89
|
+
* Outer RPK (zip) contains:
|
|
90
|
+
* - manifest.json (top-level metadata)
|
|
91
|
+
* - logo.<ext> (icon - kept as png since VUG conversion is out of scope)
|
|
92
|
+
* - META-INF/CERT (signature)
|
|
93
|
+
* - <package>.vru (multi-file VRU containing all build artifacts)
|
|
94
|
+
*/
|
|
95
|
+
static async createWrappedReleaseRpk(param, config, files, signConfig) {
|
|
96
|
+
const {
|
|
97
|
+
projectPath,
|
|
98
|
+
outputPath
|
|
99
|
+
} = param;
|
|
100
|
+
const buildDir = _path.default.join(projectPath, outputPath);
|
|
101
|
+
|
|
102
|
+
// 1. Pack all build files into VRU
|
|
103
|
+
const vruEntries = [];
|
|
104
|
+
for (const f of files) {
|
|
105
|
+
// Skip top-level manifest.json and CERT — those go in outer rpk
|
|
106
|
+
if (f === 'manifest.json' || f === ZipUtil.CERT_PATH) continue;
|
|
107
|
+
const absPath = _path.default.join(buildDir, f);
|
|
108
|
+
vruEntries.push({
|
|
109
|
+
name: f,
|
|
110
|
+
data: _fsExtra.default.readFileSync(absPath)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Add packageInfo.json for build metadata
|
|
114
|
+
const packageInfo = {
|
|
115
|
+
originType: 'native',
|
|
116
|
+
toolkit: 'aiot-toolkit',
|
|
117
|
+
buildTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
|
118
|
+
node: process.version,
|
|
119
|
+
platform: process.platform,
|
|
120
|
+
arch: process.arch
|
|
121
|
+
};
|
|
122
|
+
vruEntries.push({
|
|
123
|
+
name: 'packageInfo.json',
|
|
124
|
+
data: Buffer.from(JSON.stringify(packageInfo, null, 2), 'utf-8')
|
|
125
|
+
});
|
|
126
|
+
// Sort entries alphabetically (matches blueos-pack ordering)
|
|
127
|
+
vruEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
128
|
+
const vruBuffer = _VruUtil.VruUtil.pack(vruEntries, config.package);
|
|
129
|
+
|
|
130
|
+
// 2. Build the outer RPK
|
|
131
|
+
const outerPackage = new _Package.default({
|
|
132
|
+
filePrefix: config.package,
|
|
133
|
+
fileSuffix: 'rpk',
|
|
134
|
+
standalone: true,
|
|
135
|
+
comment: JSON.stringify(this.createComment(param))
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Add manifest.json
|
|
139
|
+
const manifestPath = _path.default.join(buildDir, 'manifest.json');
|
|
140
|
+
if (_fsExtra.default.existsSync(manifestPath)) {
|
|
141
|
+
const manifestBuf = _fsExtra.default.readFileSync(manifestPath);
|
|
142
|
+
outerPackage.addResource({
|
|
143
|
+
fileBuildPath: 'manifest.json',
|
|
144
|
+
fileContentBuffer: manifestBuf,
|
|
145
|
+
fileContentDigest: _sharedUtils.CommonUtil.calcDataDigest(manifestBuf)
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Add icon (as-is, no VUG conversion)
|
|
150
|
+
if (config.icon) {
|
|
151
|
+
const iconPath = _path.default.join(buildDir, config.icon.replace(/^\//, ''));
|
|
152
|
+
if (_fsExtra.default.existsSync(iconPath)) {
|
|
153
|
+
const iconBuf = _fsExtra.default.readFileSync(iconPath);
|
|
154
|
+
const iconExt = _path.default.extname(iconPath) || '.png';
|
|
155
|
+
outerPackage.addResource({
|
|
156
|
+
fileBuildPath: `logo${iconExt}`,
|
|
157
|
+
fileContentBuffer: iconBuf,
|
|
158
|
+
fileContentDigest: _sharedUtils.CommonUtil.calcDataDigest(iconBuf)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Add inner VRU
|
|
164
|
+
outerPackage.addResource({
|
|
165
|
+
fileBuildPath: _VruUtil.VruUtil.getVruName(config.package),
|
|
166
|
+
fileContentBuffer: vruBuffer,
|
|
167
|
+
fileContentDigest: _sharedUtils.CommonUtil.calcDataDigest(vruBuffer)
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Add CERT if present
|
|
171
|
+
const certAbsPath = _path.default.join(buildDir, ZipUtil.CERT_PATH);
|
|
172
|
+
if (_fsExtra.default.existsSync(certAbsPath)) {
|
|
173
|
+
let certBuf = _fsExtra.default.readFileSync(certAbsPath);
|
|
174
|
+
const metaZip = await _jszip.default.loadAsync(certBuf);
|
|
175
|
+
certBuf = await metaZip.generateAsync({
|
|
176
|
+
...ZipUtil.ZIP_OPTION,
|
|
177
|
+
comment: null
|
|
178
|
+
});
|
|
179
|
+
outerPackage.addResource({
|
|
180
|
+
fileBuildPath: ZipUtil.CERT_PATH,
|
|
181
|
+
fileContentBuffer: certBuf,
|
|
182
|
+
fileContentDigest: _sharedUtils.CommonUtil.calcDataDigest(certBuf)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return await ZipUtil.buildProjectAndOutput(outerPackage, signConfig);
|
|
80
186
|
}
|
|
81
187
|
static getFileName(param, config, ext) {
|
|
82
188
|
const {
|
|
@@ -20,7 +20,7 @@ async function _default(source) {
|
|
|
20
20
|
projectPath: this.rootContext,
|
|
21
21
|
onLog: log => onLog?.([log]),
|
|
22
22
|
projectType: _sharedUtils.ProjectType.VELA_UX
|
|
23
|
-
}, compileParam, context).translate({
|
|
23
|
+
}, compileParam, context, true).translate({
|
|
24
24
|
content: source
|
|
25
25
|
}, []);
|
|
26
26
|
callback(null, result.targetTree.getFullText());
|
package/lib/config/UxConfig.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import PngLoader from '../loader/ux/PngLoader';
|
|
|
5
5
|
import AppUxLoader from '../loader/ux/vela/AppUxLoader';
|
|
6
6
|
import HmlLoader from '../loader/ux/vela/HmlLoader';
|
|
7
7
|
import UxLoader from '../loader/ux/vela/UxLoader';
|
|
8
|
+
import AndroidUxLoader from '../loader/ux/android/UxLoader';
|
|
8
9
|
import UxBeforeWorks from '../beforeWorks/ux/UxBeforeWorks';
|
|
9
10
|
import UxAfterWorks from '../afterWorks/ux/UxAfterWorks';
|
|
10
11
|
import { IChangedFile } from 'file-lane/lib/interface/IChangedFile';
|
|
@@ -28,13 +29,15 @@ declare class UxConfig implements IFileLaneConfig<IJavascriptCompileOption> {
|
|
|
28
29
|
beforeCompile: import("file-lane").PreWork<IJavascriptCompileOption>[];
|
|
29
30
|
afterCompile: ({
|
|
30
31
|
worker: import("file-lane").FollowWork<IJavascriptCompileOption>;
|
|
32
|
+
workDescribe: string;
|
|
31
33
|
workerDescribe?: undefined;
|
|
32
34
|
} | {
|
|
33
35
|
worker: import("file-lane").FollowWork<IJavascriptCompileOption>;
|
|
34
36
|
workerDescribe: string;
|
|
37
|
+
workDescribe?: undefined;
|
|
35
38
|
})[];
|
|
36
39
|
afterWorks: (typeof UxAfterWorks.cleanOutput)[];
|
|
37
|
-
watchIgnores:
|
|
40
|
+
watchIgnores: string[];
|
|
38
41
|
/**
|
|
39
42
|
* 通过项目类型,返回模块配置
|
|
40
43
|
*/
|
|
@@ -46,11 +49,7 @@ declare class UxConfig implements IFileLaneConfig<IJavascriptCompileOption> {
|
|
|
46
49
|
} | {
|
|
47
50
|
test: RegExp[];
|
|
48
51
|
exclude: RegExp[];
|
|
49
|
-
loader: (typeof UxLoader)[];
|
|
50
|
-
} | {
|
|
51
|
-
test: RegExp[];
|
|
52
52
|
loader: (typeof HmlLoader | typeof UxLoader)[];
|
|
53
|
-
exclude?: undefined;
|
|
54
53
|
} | {
|
|
55
54
|
test: RegExp[];
|
|
56
55
|
loader: (typeof JsLoader)[];
|
|
@@ -60,6 +59,14 @@ declare class UxConfig implements IFileLaneConfig<IJavascriptCompileOption> {
|
|
|
60
59
|
loader: (typeof PngLoader)[];
|
|
61
60
|
exclude?: undefined;
|
|
62
61
|
})[];
|
|
62
|
+
} | {
|
|
63
|
+
rules: ({
|
|
64
|
+
test: RegExp[];
|
|
65
|
+
loader: (typeof AndroidUxLoader)[];
|
|
66
|
+
} | {
|
|
67
|
+
test: RegExp[];
|
|
68
|
+
loader: (typeof PngLoader)[];
|
|
69
|
+
})[];
|
|
63
70
|
};
|
|
64
71
|
/**
|
|
65
72
|
* 判断项目类型
|
package/lib/config/UxConfig.js
CHANGED
|
@@ -75,13 +75,17 @@ class UxConfig {
|
|
|
75
75
|
beforeWorks = (() => [_UxBeforeWorks.default.cleanOutput])();
|
|
76
76
|
beforeCompile = (() => [_UxBeforeCompile.default.validateManifest, _UxBeforeCompile.default.validateSitemap, _BeforeCompileUtils.default.clean, _BeforeCompileUtils.default.getEntries, _BeforeCompileUtils.default.getGlobalVar])();
|
|
77
77
|
afterCompile = (() => [{
|
|
78
|
-
worker: _UxAfterCompile.default.writeGitIgnore
|
|
78
|
+
worker: _UxAfterCompile.default.writeGitIgnore,
|
|
79
|
+
workDescribe: 'Write .gitignore'
|
|
79
80
|
}, {
|
|
80
81
|
worker: _UxAfterCompile.default.symlinkNodeModule,
|
|
81
82
|
workerDescribe: 'Create a soft link to the node_modules folder'
|
|
82
83
|
}, {
|
|
83
84
|
worker: _UxAfterCompile.default.compileJavascript,
|
|
84
85
|
workerDescribe: 'Compile javascript project'
|
|
86
|
+
}, {
|
|
87
|
+
worker: _UxAfterCompile.default.prerender,
|
|
88
|
+
workerDescribe: 'Prerender pages to template.json + css.json'
|
|
85
89
|
}, {
|
|
86
90
|
worker: _UxAfterCompile.default.copyResource,
|
|
87
91
|
workerDescribe: 'Copy resource files'
|
|
@@ -111,7 +115,7 @@ class UxConfig {
|
|
|
111
115
|
workerDescribe: 'Check resource'
|
|
112
116
|
}])();
|
|
113
117
|
afterWorks = (() => [_UxAfterWorks.default.cleanOutput])();
|
|
114
|
-
watchIgnores = [
|
|
118
|
+
watchIgnores = ['**/node_modules/**', '**/build/**', '**/dist/**'];
|
|
115
119
|
|
|
116
120
|
/**
|
|
117
121
|
* 通过项目类型,返回模块配置
|
|
@@ -123,11 +127,8 @@ class UxConfig {
|
|
|
123
127
|
test: ['app.ux'],
|
|
124
128
|
loader: [_AppUxLoader.default]
|
|
125
129
|
}, {
|
|
126
|
-
test: [/.+\.ux$/],
|
|
130
|
+
test: [/.+\.(ux|hml)$/],
|
|
127
131
|
exclude: [/app\.ux/],
|
|
128
|
-
loader: [_UxLoader.default]
|
|
129
|
-
}, {
|
|
130
|
-
test: [/.+\.hml$/],
|
|
131
132
|
loader: [_HmlLoader.default, _UxLoader.default]
|
|
132
133
|
}, {
|
|
133
134
|
test: [/.+\.js$/],
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { IFileLaneContext, IFileParam, ILoader } from 'file-lane';
|
|
2
2
|
import IJavascriptCompileOption from '../../compiler/javascript/interface/IJavascriptCompileOption';
|
|
3
|
+
import { ILog } from '@aiot-toolkit/shared-utils';
|
|
4
|
+
import FileLaneCompilation from 'file-lane/lib/FileLaneCompilation';
|
|
3
5
|
/**
|
|
4
6
|
* JsLoader
|
|
5
7
|
*/
|
|
6
8
|
declare class JsLoader implements ILoader {
|
|
7
9
|
context: IFileLaneContext;
|
|
8
10
|
compilerOption: IJavascriptCompileOption;
|
|
11
|
+
compilation: FileLaneCompilation;
|
|
12
|
+
logs: ILog[];
|
|
13
|
+
/**
|
|
14
|
+
* 解析文件内容
|
|
15
|
+
* @param files files 待处理的文件数组
|
|
16
|
+
* @returns 处理后的文件数组
|
|
17
|
+
*/
|
|
9
18
|
parser(files: IFileParam<any>[]): Promise<IFileParam<any>[]>;
|
|
10
19
|
}
|
|
11
20
|
export default JsLoader;
|
|
@@ -6,13 +6,28 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _parser = require("@aiot-toolkit/parser");
|
|
8
8
|
var _sharedUtils = require("@aiot-toolkit/shared-utils");
|
|
9
|
+
var _UxLoaderUtils = _interopRequireDefault(require("../../utils/ux/UxLoaderUtils"));
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
12
|
/**
|
|
10
13
|
* JsLoader
|
|
11
14
|
*/
|
|
12
15
|
class JsLoader {
|
|
16
|
+
logs = [];
|
|
17
|
+
/**
|
|
18
|
+
* 解析文件内容
|
|
19
|
+
* @param files files 待处理的文件数组
|
|
20
|
+
* @returns 处理后的文件数组
|
|
21
|
+
*/
|
|
13
22
|
async parser(files) {
|
|
14
|
-
const onLog = () => {};
|
|
15
23
|
const result = [];
|
|
24
|
+
const {
|
|
25
|
+
projectPath,
|
|
26
|
+
widgetProvider
|
|
27
|
+
} = this.context;
|
|
28
|
+
const {
|
|
29
|
+
sourceRoot
|
|
30
|
+
} = this.compilerOption;
|
|
16
31
|
for (const item of files) {
|
|
17
32
|
if (!item.content) {
|
|
18
33
|
result.push({
|
|
@@ -22,17 +37,41 @@ class JsLoader {
|
|
|
22
37
|
} else {
|
|
23
38
|
const options = {
|
|
24
39
|
filePath: item.path,
|
|
25
|
-
projectPath
|
|
40
|
+
projectPath,
|
|
26
41
|
content: item.content.toString(),
|
|
27
42
|
projectType: _sharedUtils.ProjectType.getProjectType(this.context.projectPath),
|
|
28
|
-
onLog
|
|
43
|
+
onLog: log => {
|
|
44
|
+
this.logs.push(log);
|
|
45
|
+
}
|
|
29
46
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
const scriptTree = await new _parser.ScriptToTypescript(options, this.compilerOption, this.context).translate({
|
|
48
|
+
content: new _parser.ScriptParser(options).parser(item.content.toString()).ast.content
|
|
49
|
+
}, []);
|
|
50
|
+
const isService = _UxLoaderUtils.default.isServiceFile(item.path, {
|
|
51
|
+
compilation: this.compilation,
|
|
52
|
+
compilerOption: this.compilerOption,
|
|
53
|
+
context: this.context
|
|
35
54
|
});
|
|
55
|
+
if (isService) {
|
|
56
|
+
result.push({
|
|
57
|
+
path: item.path,
|
|
58
|
+
content: _UxLoaderUtils.default.createServiceWrapper(scriptTree.targetTree).filter(Boolean).join('\n')
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
const isWidgetProvider = widgetProvider?.includes(_path.default.relative(_path.default.join(projectPath, sourceRoot), item.path).replace(/\\/g, '/'));
|
|
62
|
+
let content = scriptTree.targetTree.getFullText();
|
|
63
|
+
if (isWidgetProvider) {
|
|
64
|
+
const {
|
|
65
|
+
newScriptTree,
|
|
66
|
+
scriptSourceMap
|
|
67
|
+
} = _parser.SourceMapUtil.splitSourceMap(scriptTree.targetTree);
|
|
68
|
+
content = _parser.SourceMapUtil.concatSourceMap(`${newScriptTree.getFullText()}\n$app_exports$.default = exports["default"]\n`, scriptSourceMap);
|
|
69
|
+
}
|
|
70
|
+
result.push({
|
|
71
|
+
path: item.path,
|
|
72
|
+
content: content
|
|
73
|
+
});
|
|
74
|
+
}
|
|
36
75
|
}
|
|
37
76
|
}
|
|
38
77
|
return result;
|
|
@@ -9,16 +9,16 @@ declare class HmlLoader implements ILoader {
|
|
|
9
9
|
/**
|
|
10
10
|
* 包裹 hml 文件
|
|
11
11
|
*
|
|
12
|
-
* # 路径
|
|
13
|
-
* 如果存在同路径的 ux 后缀,报错;否则转换为同路径的 ux 后缀
|
|
14
|
-
*
|
|
15
12
|
* # 内容
|
|
16
|
-
* 1.
|
|
17
|
-
* 2.
|
|
18
|
-
*
|
|
13
|
+
* 1. 全文模式(存在template、script、style任一节点),保留原内容不变
|
|
14
|
+
* 2. 否则,则进行如下包装
|
|
15
|
+
* 1. hml的内容: import放到最前,其它内容使用<template></template>包裹
|
|
16
|
+
* 2. 如果存在同路径同名的 script文件,则加到<script></script>中
|
|
17
|
+
* 3. 如果存在同路径同名的 style文件,则加到<style></style>中
|
|
19
18
|
*
|
|
20
19
|
* @param file
|
|
21
20
|
*/
|
|
22
21
|
private wrapHml;
|
|
22
|
+
private nodesToString;
|
|
23
23
|
}
|
|
24
24
|
export default HmlLoader;
|
|
@@ -7,6 +7,9 @@ exports.default = void 0;
|
|
|
7
7
|
var _path = _interopRequireDefault(require("path"));
|
|
8
8
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
9
|
var _parser = require("@aiot-toolkit/parser");
|
|
10
|
+
var parse5 = _interopRequireWildcard(require("aiot-parse5"));
|
|
11
|
+
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); }
|
|
12
|
+
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; }
|
|
10
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
14
|
/**
|
|
12
15
|
* HmlLoader
|
|
@@ -21,13 +24,12 @@ class HmlLoader {
|
|
|
21
24
|
/**
|
|
22
25
|
* 包裹 hml 文件
|
|
23
26
|
*
|
|
24
|
-
* # 路径
|
|
25
|
-
* 如果存在同路径的 ux 后缀,报错;否则转换为同路径的 ux 后缀
|
|
26
|
-
*
|
|
27
27
|
* # 内容
|
|
28
|
-
* 1.
|
|
29
|
-
* 2.
|
|
30
|
-
*
|
|
28
|
+
* 1. 全文模式(存在template、script、style任一节点),保留原内容不变
|
|
29
|
+
* 2. 否则,则进行如下包装
|
|
30
|
+
* 1. hml的内容: import放到最前,其它内容使用<template></template>包裹
|
|
31
|
+
* 2. 如果存在同路径同名的 script文件,则加到<script></script>中
|
|
32
|
+
* 3. 如果存在同路径同名的 style文件,则加到<style></style>中
|
|
31
33
|
*
|
|
32
34
|
* @param file
|
|
33
35
|
*/
|
|
@@ -36,32 +38,47 @@ class HmlLoader {
|
|
|
36
38
|
path,
|
|
37
39
|
content
|
|
38
40
|
} = file;
|
|
39
|
-
const
|
|
41
|
+
const uxAst = parse5.parseFragment(content?.toString() || '', {
|
|
42
|
+
scriptingEnabled: false,
|
|
43
|
+
sourceCodeLocationInfo: true
|
|
44
|
+
});
|
|
45
|
+
const fullMode = uxAst.childNodes.some(node => {
|
|
46
|
+
return ['template', 'script', 'style'].includes(node.nodeName);
|
|
47
|
+
});
|
|
48
|
+
if (fullMode) {
|
|
49
|
+
return file;
|
|
50
|
+
}
|
|
40
51
|
const getFilePath = ext => {
|
|
41
52
|
const pathParsed = _path.default.parse(path);
|
|
42
53
|
pathParsed.ext = ext;
|
|
43
54
|
pathParsed.base = pathParsed.name + ext;
|
|
44
55
|
return _path.default.format(pathParsed);
|
|
45
56
|
};
|
|
46
|
-
const uxPath = getFilePath(uxExt);
|
|
47
|
-
if (_fs.default.existsSync(uxPath)) {
|
|
48
|
-
throw new Error(`${uxPath} already exists`);
|
|
49
|
-
}
|
|
50
57
|
const scriptExts = _parser.ExtensionConfig.SCRIPTS;
|
|
51
58
|
const styleExts = _parser.ExtensionConfig.STYLES;
|
|
52
59
|
const scriptPath = scriptExts.map(item => getFilePath(item)).find(item => _fs.default.existsSync(item));
|
|
53
60
|
const stylePath = styleExts.map(item => getFilePath(item)).find(item => _fs.default.existsSync(item));
|
|
54
|
-
|
|
61
|
+
const importNodes = uxAst.childNodes.filter(node => node.nodeName === 'import');
|
|
62
|
+
const otherNodes = uxAst.childNodes.filter(node => node.nodeName !== 'import');
|
|
63
|
+
let uxContent = this.nodesToString(importNodes);
|
|
64
|
+
uxContent += ['<template>', this.nodesToString(otherNodes), '</template>'].join('\n');
|
|
55
65
|
if (scriptPath) {
|
|
56
66
|
uxContent += ['<script>', _fs.default.readFileSync(scriptPath, 'utf-8'), '</script>'].join('\n');
|
|
57
67
|
}
|
|
58
68
|
if (stylePath) {
|
|
59
|
-
|
|
69
|
+
const styleExt = _path.default.extname(stylePath).toLowerCase();
|
|
70
|
+
uxContent += [`<style lang="${styleExt.slice(1)}">`, _fs.default.readFileSync(stylePath, 'utf-8'), '</style>'].join('\n');
|
|
60
71
|
}
|
|
61
72
|
return {
|
|
62
73
|
path,
|
|
63
74
|
content: uxContent
|
|
64
75
|
};
|
|
65
76
|
}
|
|
77
|
+
nodesToString(nodes) {
|
|
78
|
+
return parse5.serialize({
|
|
79
|
+
nodeName: '#document-fragment',
|
|
80
|
+
childNodes: nodes
|
|
81
|
+
});
|
|
82
|
+
}
|
|
66
83
|
}
|
|
67
84
|
var _default = exports.default = HmlLoader;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ILog } from '@aiot-toolkit/shared-utils';
|
|
2
|
+
/** 预渲染 DOM 节点 */
|
|
3
|
+
export interface PrerenderNode {
|
|
4
|
+
type: string;
|
|
5
|
+
attr?: Record<string, any>;
|
|
6
|
+
class?: string;
|
|
7
|
+
style?: Record<string, string>;
|
|
8
|
+
styleObjectId?: number;
|
|
9
|
+
children?: PrerenderNode[];
|
|
10
|
+
events?: Record<string, string>;
|
|
11
|
+
bind?: number;
|
|
12
|
+
$repeat?: string;
|
|
13
|
+
repeat?: any[];
|
|
14
|
+
repeat_items?: PrerenderNode[];
|
|
15
|
+
import?: string;
|
|
16
|
+
}
|
|
17
|
+
/** 绑定标记:文本/属性绑定 */
|
|
18
|
+
export interface BindingMarker {
|
|
19
|
+
$value: string;
|
|
20
|
+
bind: 1;
|
|
21
|
+
_staticValue?: any;
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}
|
|
24
|
+
/** 循环标记 */
|
|
25
|
+
export interface RepeatMarker {
|
|
26
|
+
$repeat: string;
|
|
27
|
+
repeat: any[];
|
|
28
|
+
}
|
|
29
|
+
/** 事件标记 */
|
|
30
|
+
export interface EventMarker {
|
|
31
|
+
[key: `$${string}`]: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* PrerenderVM - 在 Node.js VM 沙箱中执行编译后的模板函数,收集 DOM 树
|
|
35
|
+
*/
|
|
36
|
+
export default class PrerenderVM {
|
|
37
|
+
private components;
|
|
38
|
+
private styleMap;
|
|
39
|
+
private bindCounter;
|
|
40
|
+
private styleSerializer;
|
|
41
|
+
private accessedKeys;
|
|
42
|
+
/** 创建 data Proxy,拦截访问并返回绑定标记(支持嵌套和数组) */
|
|
43
|
+
createDataProxy(data: Record<string, any>, parentPath?: string): Record<string, any>;
|
|
44
|
+
/** 获取已访问的 key 列表 */
|
|
45
|
+
getAccessedKeys(): string[];
|
|
46
|
+
/** Track binding markers accessed during a function call */
|
|
47
|
+
private _bindingAccess;
|
|
48
|
+
/** Create a binding marker with toString for string concatenation */
|
|
49
|
+
private createBindingMarker;
|
|
50
|
+
/** 文本绑定标记 */
|
|
51
|
+
static createTextBinding(key: string): BindingMarker;
|
|
52
|
+
/** 属性绑定标记 */
|
|
53
|
+
static createAttrBinding(attr: string, key: string): Record<string, any>;
|
|
54
|
+
/** 循环标记 */
|
|
55
|
+
static createRepeatMarker(listName: string): RepeatMarker;
|
|
56
|
+
/** 事件标记 */
|
|
57
|
+
static createEventMarker(event: string, handler: string): EventMarker;
|
|
58
|
+
/**
|
|
59
|
+
* 执行编译后的 JS,收集组件定义
|
|
60
|
+
*/
|
|
61
|
+
execute(jsCode: string, onLog?: (logs: ILog[]) => void): {
|
|
62
|
+
tree: PrerenderNode | null;
|
|
63
|
+
styles: Record<number, any>;
|
|
64
|
+
};
|
|
65
|
+
private unwrapCode;
|
|
66
|
+
private createSandbox;
|
|
67
|
+
private collectStyles;
|
|
68
|
+
private normalizeStyleSheet;
|
|
69
|
+
private createMockVM;
|
|
70
|
+
private createNode;
|
|
71
|
+
private createConditionalNode;
|
|
72
|
+
private createForNode;
|
|
73
|
+
private createBlockNode;
|
|
74
|
+
private executeTemplate;
|
|
75
|
+
private parseInlineStyle;
|
|
76
|
+
private extractBindingExpression;
|
|
77
|
+
/** Replace $item.xxx references in event handler strings with actual values */
|
|
78
|
+
private bakeItemRefsInEvents;
|
|
79
|
+
/**
|
|
80
|
+
* Get all registered sub-component templates (excluding the bootstrapped main component)
|
|
81
|
+
*/
|
|
82
|
+
getSubComponentTemplates(mainName?: string): Map<string, {
|
|
83
|
+
tree: PrerenderNode | null;
|
|
84
|
+
styles: Record<number, any>;
|
|
85
|
+
}>;
|
|
86
|
+
}
|