@dimina/compiler 1.0.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/README.md +119 -0
- package/dist/bin/index.cjs +32 -0
- package/dist/bin/index.js +31 -0
- package/dist/core/logic-compiler.cjs +184 -0
- package/dist/core/logic-compiler.js +185 -0
- package/dist/core/style-compiler.cjs +154 -0
- package/dist/core/style-compiler.js +155 -0
- package/dist/core/view-compiler.cjs +651 -0
- package/dist/core/view-compiler.js +634 -0
- package/dist/env-CezfCSQz.js +299 -0
- package/dist/env-Chow6VXH.cjs +298 -0
- package/dist/index.cjs +237 -0
- package/dist/index.js +237 -0
- package/package.json +70 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const node_worker_threads = require("node:worker_threads");
|
|
4
|
+
const babel = require("@babel/core");
|
|
5
|
+
const types = require("@babel/types");
|
|
6
|
+
const _traverse = require("@babel/traverse");
|
|
7
|
+
const compilerSfc = require("@vue/compiler-sfc");
|
|
8
|
+
const cheerio = require("cheerio");
|
|
9
|
+
const htmlparser2 = require("htmlparser2");
|
|
10
|
+
const esbuild = require("esbuild");
|
|
11
|
+
const env = require("../env-Chow6VXH.cjs");
|
|
12
|
+
function _interopNamespaceDefault(e) {
|
|
13
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
14
|
+
if (e) {
|
|
15
|
+
for (const k in e) {
|
|
16
|
+
if (k !== "default") {
|
|
17
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: () => e[k]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
const cheerio__namespace = /* @__PURE__ */ _interopNamespaceDefault(cheerio);
|
|
29
|
+
const htmlparser2__namespace = /* @__PURE__ */ _interopNamespaceDefault(htmlparser2);
|
|
30
|
+
const traverse = _traverse.default ? _traverse.default : _traverse;
|
|
31
|
+
const fileType = [".wxml", ".ddml"];
|
|
32
|
+
const compileResCache = /* @__PURE__ */ new Map();
|
|
33
|
+
const processedModules = /* @__PURE__ */ new Set();
|
|
34
|
+
if (!node_worker_threads.isMainThread) {
|
|
35
|
+
node_worker_threads.parentPort.on("message", async ({ pages, storeInfo }) => {
|
|
36
|
+
try {
|
|
37
|
+
env.resetStoreInfo(storeInfo);
|
|
38
|
+
const progress = {
|
|
39
|
+
_completedTasks: 0,
|
|
40
|
+
get completedTasks() {
|
|
41
|
+
return this._completedTasks;
|
|
42
|
+
},
|
|
43
|
+
set completedTasks(value) {
|
|
44
|
+
this._completedTasks = value;
|
|
45
|
+
node_worker_threads.parentPort.postMessage({ completedTasks: this._completedTasks });
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
await compileML(pages.mainPages, null, progress);
|
|
49
|
+
for (const [root, subPages] of Object.entries(pages.subPages)) {
|
|
50
|
+
await compileML(subPages.info, root, progress);
|
|
51
|
+
}
|
|
52
|
+
node_worker_threads.parentPort.postMessage({ success: true });
|
|
53
|
+
} catch (error) {
|
|
54
|
+
node_worker_threads.parentPort.postMessage({ success: false, error: error.message });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function compileML(pages, root, progress) {
|
|
59
|
+
for (const page of pages) {
|
|
60
|
+
const scriptRes = /* @__PURE__ */ new Map();
|
|
61
|
+
buildCompileView(page, false, scriptRes, []);
|
|
62
|
+
let mergeRender = "";
|
|
63
|
+
for (const [key, value] of scriptRes.entries()) {
|
|
64
|
+
const amdFormat = `modDefine('${key}', function(require, module, exports) {
|
|
65
|
+
${value}
|
|
66
|
+
});`;
|
|
67
|
+
const { code: minifiedCode } = await esbuild.transform(amdFormat, {
|
|
68
|
+
minify: true,
|
|
69
|
+
target: ["es2020"],
|
|
70
|
+
platform: "browser"
|
|
71
|
+
});
|
|
72
|
+
mergeRender += minifiedCode;
|
|
73
|
+
}
|
|
74
|
+
const filename = `${page.path.replace(/\//g, "_")}`;
|
|
75
|
+
if (root) {
|
|
76
|
+
const subDir = `${env.getTargetPath()}/${root}`;
|
|
77
|
+
if (!fs.existsSync(subDir)) {
|
|
78
|
+
fs.mkdirSync(subDir);
|
|
79
|
+
}
|
|
80
|
+
fs.writeFileSync(`${subDir}/${filename}.js`, mergeRender);
|
|
81
|
+
} else {
|
|
82
|
+
const mainDir = `${env.getTargetPath()}/main`;
|
|
83
|
+
if (!fs.existsSync(mainDir)) {
|
|
84
|
+
fs.mkdirSync(mainDir);
|
|
85
|
+
}
|
|
86
|
+
fs.writeFileSync(`${mainDir}/${filename}.js`, mergeRender);
|
|
87
|
+
}
|
|
88
|
+
progress.completedTasks++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function buildCompileView(module2, isComponent = false, scriptRes, depthChain = []) {
|
|
92
|
+
const currentPath = module2.path;
|
|
93
|
+
if (depthChain.includes(currentPath)) {
|
|
94
|
+
console.warn(`检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
|
|
95
|
+
}
|
|
96
|
+
if (depthChain.length > 100) {
|
|
97
|
+
console.warn(`检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
|
|
98
|
+
}
|
|
99
|
+
depthChain = [...depthChain, currentPath];
|
|
100
|
+
compileModule(module2, isComponent, scriptRes);
|
|
101
|
+
if (module2.usingComponents) {
|
|
102
|
+
for (const componentInfo of Object.values(module2.usingComponents)) {
|
|
103
|
+
const componentModule = env.getComponent(componentInfo);
|
|
104
|
+
if (!componentModule) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
buildCompileView(componentModule, true, scriptRes, depthChain);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
processedModules.add(currentPath);
|
|
111
|
+
}
|
|
112
|
+
function compileModule(module2, isComponent, scriptRes) {
|
|
113
|
+
const { tpl, instruction } = toCompileTemplate(isComponent, module2.path, module2.usingComponents, module2.componentPlaceholder);
|
|
114
|
+
if (!tpl) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!scriptRes.has(module2.path) && compileResCache.has(module2.path)) {
|
|
118
|
+
const res = compileResCache.get(module2.path);
|
|
119
|
+
scriptRes.set(module2.path, res);
|
|
120
|
+
for (const sm of instruction.scriptModule) {
|
|
121
|
+
if (!scriptRes.has(sm.path)) {
|
|
122
|
+
scriptRes.set(sm.path, sm.code);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const processedTpl = tpl.replace(/\bthis\./g, "_ctx.");
|
|
128
|
+
const tplCode = compilerSfc.compileTemplate({
|
|
129
|
+
source: processedTpl,
|
|
130
|
+
filename: module2.path,
|
|
131
|
+
// 用于错误提示
|
|
132
|
+
id: `data-v-${module2.id}`,
|
|
133
|
+
scoped: true,
|
|
134
|
+
compilerOptions: {
|
|
135
|
+
// https://template-explorer.vuejs.org/
|
|
136
|
+
prefixIdentifiers: true,
|
|
137
|
+
hoistStatic: false,
|
|
138
|
+
cacheHandlers: true,
|
|
139
|
+
scopeId: `data-v-${module2.id}`,
|
|
140
|
+
mode: "function",
|
|
141
|
+
inline: true
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
let tplComponents = "{";
|
|
145
|
+
for (const tm of instruction.templateModule) {
|
|
146
|
+
tplComponents += `'${tm.path}':${compilerSfc.compileTemplate({
|
|
147
|
+
source: tm.tpl,
|
|
148
|
+
filename: tm.path,
|
|
149
|
+
id: `data-v-${module2.id}`,
|
|
150
|
+
scoped: true,
|
|
151
|
+
compilerOptions: {
|
|
152
|
+
prefixIdentifiers: true,
|
|
153
|
+
hoistStatic: false,
|
|
154
|
+
cacheHandlers: true,
|
|
155
|
+
scopeId: `data-v-${module2.id}`,
|
|
156
|
+
mode: "function",
|
|
157
|
+
inline: true
|
|
158
|
+
}
|
|
159
|
+
}).code},`;
|
|
160
|
+
}
|
|
161
|
+
tplComponents += "}";
|
|
162
|
+
const tplAst = babel.parseSync(tplCode.code);
|
|
163
|
+
for (const sm of instruction.scriptModule) {
|
|
164
|
+
if (!scriptRes.has(sm.path)) {
|
|
165
|
+
scriptRes.set(sm.path, sm.code);
|
|
166
|
+
}
|
|
167
|
+
const assignmentExpression = types.assignmentExpression(
|
|
168
|
+
"=",
|
|
169
|
+
// 创建赋值表达式
|
|
170
|
+
types.memberExpression(
|
|
171
|
+
types.identifier("_ctx"),
|
|
172
|
+
// 对象标识符
|
|
173
|
+
types.identifier(sm.path),
|
|
174
|
+
// 属性标识符
|
|
175
|
+
false
|
|
176
|
+
// 是否是计算属性
|
|
177
|
+
),
|
|
178
|
+
// 创建require调用表达式
|
|
179
|
+
types.callExpression(
|
|
180
|
+
types.identifier("require"),
|
|
181
|
+
// 函数标识符
|
|
182
|
+
[types.stringLiteral(sm.path)]
|
|
183
|
+
// 参数列表,这里传入字符串字面量'foo'
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
const expressionStatement = types.expressionStatement(assignmentExpression);
|
|
187
|
+
tplAst.program.body[0].expression.body.body.splice(0, 0, expressionStatement);
|
|
188
|
+
}
|
|
189
|
+
const { code: transCode } = babel.transformFromAstSync(tplAst, "", {
|
|
190
|
+
comments: false
|
|
191
|
+
});
|
|
192
|
+
const code = `Module({
|
|
193
|
+
path: '${module2.path}',
|
|
194
|
+
id: '${module2.id}',
|
|
195
|
+
render: ${transCode.replace(/;$/, "").replace(/^"use strict";\s*/, "")},
|
|
196
|
+
usingComponents: ${JSON.stringify(module2.usingComponents)},
|
|
197
|
+
tplComponents: ${tplComponents},
|
|
198
|
+
});`;
|
|
199
|
+
compileResCache.set(module2.path, code);
|
|
200
|
+
scriptRes.set(module2.path, code);
|
|
201
|
+
}
|
|
202
|
+
function toCompileTemplate(isComponent, path, components, componentPlaceholder) {
|
|
203
|
+
const workPath = env.getWorkPath();
|
|
204
|
+
const fullPath = getViewPath(workPath, path);
|
|
205
|
+
if (!fullPath) {
|
|
206
|
+
return { tpl: void 0 };
|
|
207
|
+
}
|
|
208
|
+
let content = env.getContentByPath(fullPath).trim();
|
|
209
|
+
if (!content) {
|
|
210
|
+
content = "<block></block>";
|
|
211
|
+
} else {
|
|
212
|
+
if (isComponent) {
|
|
213
|
+
content = `<wrapper>${content}</wrapper>`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const templateModule = [];
|
|
217
|
+
const $ = cheerio__namespace.load(content, {
|
|
218
|
+
xmlMode: true,
|
|
219
|
+
decodeEntities: false
|
|
220
|
+
});
|
|
221
|
+
const includeNodes = $("include");
|
|
222
|
+
includeNodes.each((_, elem) => {
|
|
223
|
+
const src = $(elem).attr("src");
|
|
224
|
+
if (src) {
|
|
225
|
+
const includeContent = env.getContentByPath(env.getAbsolutePath(workPath, path, src)).trim();
|
|
226
|
+
if (includeContent) {
|
|
227
|
+
const $includeContent = cheerio__namespace.load(includeContent, {
|
|
228
|
+
xmlMode: true,
|
|
229
|
+
decodeEntities: false
|
|
230
|
+
});
|
|
231
|
+
$includeContent("template").remove();
|
|
232
|
+
$includeContent("wxs").remove();
|
|
233
|
+
$includeContent("dds").remove();
|
|
234
|
+
$(elem).html($includeContent.html());
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
transTagTemplate($, templateModule, path, components);
|
|
239
|
+
const importNodes = $("import");
|
|
240
|
+
importNodes.each((_, elem) => {
|
|
241
|
+
const src = $(elem).attr("src");
|
|
242
|
+
if (src) {
|
|
243
|
+
const importContent = env.getContentByPath(env.getAbsolutePath(workPath, path, src)).trim();
|
|
244
|
+
if (importContent) {
|
|
245
|
+
transTagTemplate(
|
|
246
|
+
cheerio__namespace.load(importContent, {
|
|
247
|
+
xmlMode: true,
|
|
248
|
+
decodeEntities: false
|
|
249
|
+
}),
|
|
250
|
+
templateModule,
|
|
251
|
+
path,
|
|
252
|
+
components
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
importNodes.remove();
|
|
258
|
+
const scriptModule = [];
|
|
259
|
+
let wxsNodes = $("wxs");
|
|
260
|
+
if (wxsNodes.length === 0) {
|
|
261
|
+
wxsNodes = $("dds");
|
|
262
|
+
}
|
|
263
|
+
wxsNodes.each((_, elem) => {
|
|
264
|
+
const smName = $(elem).attr("module");
|
|
265
|
+
if (smName) {
|
|
266
|
+
let wxsContent;
|
|
267
|
+
if (compileResCache.has(smName)) {
|
|
268
|
+
wxsContent = compileResCache.get(smName);
|
|
269
|
+
} else {
|
|
270
|
+
const src = $(elem).attr("src");
|
|
271
|
+
if (src) {
|
|
272
|
+
wxsContent = env.getContentByPath(env.getAbsolutePath(workPath, path, src)).trim();
|
|
273
|
+
} else {
|
|
274
|
+
wxsContent = $(elem).html();
|
|
275
|
+
}
|
|
276
|
+
const wxsAst = babel.parseSync(wxsContent);
|
|
277
|
+
traverse(wxsAst, {
|
|
278
|
+
CallExpression(path2) {
|
|
279
|
+
if (path2.node.callee.name === "getRegExp" || path2.node.callee.name === "getDate") {
|
|
280
|
+
const args = [];
|
|
281
|
+
for (let i = 0; i < path2.node.arguments.length; i++) {
|
|
282
|
+
args.push(path2.node.arguments[i]);
|
|
283
|
+
}
|
|
284
|
+
const newExpr = types.newExpression(types.identifier(path2.node.callee.name.substring(3)), args);
|
|
285
|
+
path2.replaceWith(newExpr);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
wxsContent = babel.transformFromAstSync(wxsAst, "", {
|
|
290
|
+
comments: false
|
|
291
|
+
}).code;
|
|
292
|
+
compileResCache.set(smName, wxsContent);
|
|
293
|
+
}
|
|
294
|
+
if (wxsContent) {
|
|
295
|
+
scriptModule.push({
|
|
296
|
+
path: smName,
|
|
297
|
+
code: wxsContent
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
wxsNodes.remove();
|
|
303
|
+
transAsses($, $("image"), path);
|
|
304
|
+
const res = [];
|
|
305
|
+
transHtmlTag($.html(), res, components);
|
|
306
|
+
return {
|
|
307
|
+
tpl: res.join(""),
|
|
308
|
+
instruction: {
|
|
309
|
+
templateModule,
|
|
310
|
+
scriptModule
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function transTagTemplate($, templateModule, path, components, componentPlaceholder) {
|
|
315
|
+
const templateNodes = $("template[name]");
|
|
316
|
+
templateNodes.each((_, elem) => {
|
|
317
|
+
const name = $(elem).attr("name");
|
|
318
|
+
const templateContent = $(elem);
|
|
319
|
+
templateContent.find("template").remove();
|
|
320
|
+
templateContent.find("import").remove();
|
|
321
|
+
templateContent.find("include").remove();
|
|
322
|
+
templateContent.find("wxs").remove();
|
|
323
|
+
templateContent.find("dds").remove();
|
|
324
|
+
transAsses($, templateContent.find("image"), path);
|
|
325
|
+
const res = [];
|
|
326
|
+
transHtmlTag(templateContent.html(), res, components);
|
|
327
|
+
templateModule.push({
|
|
328
|
+
path: `tpl-${name}`,
|
|
329
|
+
tpl: res.join("")
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
templateNodes.remove();
|
|
333
|
+
}
|
|
334
|
+
function transAsses($, imageNodes, path) {
|
|
335
|
+
imageNodes.each((_, elem) => {
|
|
336
|
+
const imgSrc = $(elem).attr("src").trim();
|
|
337
|
+
if (!imgSrc.startsWith("{{")) {
|
|
338
|
+
$(elem).attr("src", env.collectAssets(env.getWorkPath(), path, imgSrc, env.getTargetPath(), env.getAppId()));
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
function transHtmlTag(html, res, components, componentPlaceholder) {
|
|
343
|
+
const attrsList = [];
|
|
344
|
+
const parser = new htmlparser2__namespace.Parser(
|
|
345
|
+
{
|
|
346
|
+
onopentag(tag, attrs) {
|
|
347
|
+
attrsList.push(attrs);
|
|
348
|
+
res.push(transTag({ isStart: true, tag, attrs, components }));
|
|
349
|
+
},
|
|
350
|
+
ontext(text) {
|
|
351
|
+
res.push(text);
|
|
352
|
+
},
|
|
353
|
+
onclosetag(tag) {
|
|
354
|
+
res.push(transTag({ tag, attrs: attrsList.pop(), components }));
|
|
355
|
+
},
|
|
356
|
+
onerror(error) {
|
|
357
|
+
console.error(error);
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
{ xmlMode: true }
|
|
361
|
+
);
|
|
362
|
+
parser.write(html);
|
|
363
|
+
parser.end();
|
|
364
|
+
}
|
|
365
|
+
function transTag(opts) {
|
|
366
|
+
const { isStart, tag, attrs, components } = opts;
|
|
367
|
+
let res;
|
|
368
|
+
if (tag === "slot") {
|
|
369
|
+
res = tag;
|
|
370
|
+
} else if (components && components[tag]) {
|
|
371
|
+
res = `dd-${tag}`;
|
|
372
|
+
} else if (tag === "component" || tag === "canvas") {
|
|
373
|
+
res = tag;
|
|
374
|
+
} else if (!env.tagWhiteList.includes(tag)) {
|
|
375
|
+
res = "dd-text";
|
|
376
|
+
} else {
|
|
377
|
+
res = `dd-${tag}`;
|
|
378
|
+
}
|
|
379
|
+
let tagRes;
|
|
380
|
+
const propsAry = getProps(attrs, tag);
|
|
381
|
+
const multipleSlots = attrs?.slot;
|
|
382
|
+
if (attrs?.slot) {
|
|
383
|
+
const withVIf = [];
|
|
384
|
+
const withoutVIf = [];
|
|
385
|
+
for (let i = 0; i < propsAry.length; i++) {
|
|
386
|
+
const prop = propsAry[i];
|
|
387
|
+
if (prop.includes("v-if") || prop.includes("v-else-if") || prop.includes("v-else")) {
|
|
388
|
+
withVIf.push(prop);
|
|
389
|
+
} else {
|
|
390
|
+
withoutVIf.push(prop);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (isStart) {
|
|
394
|
+
tagRes = `<template ${`${withVIf.join(" ")}`} #${multipleSlots}><${res}${` ${withoutVIf.join(" ")}`}>`;
|
|
395
|
+
} else {
|
|
396
|
+
tagRes = `</${res}></template>`;
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
if (isStart) {
|
|
400
|
+
const props = propsAry.join(" ");
|
|
401
|
+
tagRes = props ? `<${res} ${props}>` : `<${res}>`;
|
|
402
|
+
} else {
|
|
403
|
+
tagRes = `</${res}>`;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return tagRes;
|
|
407
|
+
}
|
|
408
|
+
function getProps(attrs, tag) {
|
|
409
|
+
const attrsList = [];
|
|
410
|
+
Object.entries(attrs).forEach(([name, value]) => {
|
|
411
|
+
if (name.endsWith(":if")) {
|
|
412
|
+
attrsList.push({
|
|
413
|
+
name: "v-if",
|
|
414
|
+
value: parseBraceExp(value)
|
|
415
|
+
});
|
|
416
|
+
} else if (name.endsWith(":elif")) {
|
|
417
|
+
attrsList.push({
|
|
418
|
+
name: "v-else-if",
|
|
419
|
+
value: parseBraceExp(value)
|
|
420
|
+
});
|
|
421
|
+
} else if (name.endsWith(":else")) {
|
|
422
|
+
attrsList.push({
|
|
423
|
+
name: "v-else",
|
|
424
|
+
value: ""
|
|
425
|
+
});
|
|
426
|
+
} else if (name.endsWith(":for") || name.endsWith(":for-items")) {
|
|
427
|
+
attrsList.push({
|
|
428
|
+
name: "v-for",
|
|
429
|
+
value: parseForExp(value, attrs)
|
|
430
|
+
});
|
|
431
|
+
} else if (name.endsWith(":for-item") || name.endsWith(":for-index")) ;
|
|
432
|
+
else if (name.endsWith(":key")) {
|
|
433
|
+
let tranValue;
|
|
434
|
+
if (/\*this/.test(value)) {
|
|
435
|
+
tranValue = JSON.stringify("item");
|
|
436
|
+
} else if (/item/.test(value)) {
|
|
437
|
+
tranValue = getForItemName(attrs);
|
|
438
|
+
} else {
|
|
439
|
+
tranValue = parseKeyExpression(value, getForItemName(attrs));
|
|
440
|
+
}
|
|
441
|
+
attrsList.push({
|
|
442
|
+
name: ":key",
|
|
443
|
+
value: tranValue
|
|
444
|
+
});
|
|
445
|
+
} else if (name === "style") {
|
|
446
|
+
attrsList.push({
|
|
447
|
+
name: "v-c-style",
|
|
448
|
+
value: env.transformRpx(parseBraceExp(value))
|
|
449
|
+
});
|
|
450
|
+
} else if (name === "class") {
|
|
451
|
+
if (isWrappedByBraces(value)) {
|
|
452
|
+
attrsList.push({
|
|
453
|
+
name: ":class",
|
|
454
|
+
value: parseClassRules(value)
|
|
455
|
+
});
|
|
456
|
+
} else {
|
|
457
|
+
attrsList.push({
|
|
458
|
+
name: "class",
|
|
459
|
+
value
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
attrsList.push({
|
|
463
|
+
name: "v-c-class",
|
|
464
|
+
value: ""
|
|
465
|
+
});
|
|
466
|
+
} else if (name === "is" && tag === "component") {
|
|
467
|
+
attrsList.push({
|
|
468
|
+
name: ":is",
|
|
469
|
+
value: `'dd-'+${parseBraceExp(value)}`
|
|
470
|
+
});
|
|
471
|
+
} else if (name === "animation" && (tag !== "movable-view" && env.tagWhiteList.includes(tag))) {
|
|
472
|
+
attrsList.push({
|
|
473
|
+
name: "v-c-animation",
|
|
474
|
+
value: parseBraceExp(value)
|
|
475
|
+
});
|
|
476
|
+
} else if (name === "value" && (tag === "input" || tag === "textarea") || (name === "x" || name === "y") && tag === "movable-view") {
|
|
477
|
+
attrsList.push({
|
|
478
|
+
name: `v-model:${name}`,
|
|
479
|
+
value: parseBraceExp(value)
|
|
480
|
+
});
|
|
481
|
+
} else if (name.startsWith("data-")) {
|
|
482
|
+
if (isWrappedByBraces(value)) {
|
|
483
|
+
attrsList.push({
|
|
484
|
+
name: "v-c-data",
|
|
485
|
+
value: ""
|
|
486
|
+
});
|
|
487
|
+
attrsList.push({
|
|
488
|
+
name: `:${name}`,
|
|
489
|
+
value: parseBraceExp(value)
|
|
490
|
+
});
|
|
491
|
+
} else {
|
|
492
|
+
attrsList.push({
|
|
493
|
+
name,
|
|
494
|
+
value
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
} else if (isWrappedByBraces(value)) {
|
|
498
|
+
let pVal = parseBraceExp(value);
|
|
499
|
+
if (tag === "template" && name === "data") {
|
|
500
|
+
pVal = `{${pVal}}`;
|
|
501
|
+
}
|
|
502
|
+
attrsList.push({
|
|
503
|
+
name: `:${name}`,
|
|
504
|
+
value: pVal
|
|
505
|
+
});
|
|
506
|
+
} else if (name !== "slot") {
|
|
507
|
+
attrsList.push({
|
|
508
|
+
name,
|
|
509
|
+
value
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
const propsRes = [];
|
|
514
|
+
attrsList.forEach((attr) => {
|
|
515
|
+
const { name, value } = attr;
|
|
516
|
+
if (value === "") {
|
|
517
|
+
propsRes.push(`${name}`);
|
|
518
|
+
} else if (/\$\{[^}]*\}/.test(value)) {
|
|
519
|
+
propsRes.push(`:${name}="\`${value}\`"`);
|
|
520
|
+
} else {
|
|
521
|
+
propsRes.push(`${name}="${escapeQuotes(value)}"`);
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
return propsRes;
|
|
525
|
+
}
|
|
526
|
+
function parseKeyExpression(exp, itemName = "item") {
|
|
527
|
+
exp = exp.trim();
|
|
528
|
+
if (!exp.includes("{{")) {
|
|
529
|
+
return exp.startsWith(itemName) ? `'${exp}'` : `'${itemName}.${exp}'`;
|
|
530
|
+
}
|
|
531
|
+
if (exp.startsWith("{{") && exp.endsWith("}}")) {
|
|
532
|
+
const content = exp.slice(2, -2).trim();
|
|
533
|
+
return content.startsWith(itemName) ? `'${content}'` : `'${itemName}.${content}'`;
|
|
534
|
+
}
|
|
535
|
+
const parts = exp.split(/(\{\{.*?\}\})/);
|
|
536
|
+
const result = parts.map((part) => {
|
|
537
|
+
if (part.startsWith("{{") && part.endsWith("}}")) {
|
|
538
|
+
const content = part.slice(2, -2).trim();
|
|
539
|
+
return content.startsWith(itemName) ? content : `${itemName}.${content}`;
|
|
540
|
+
}
|
|
541
|
+
return `'${part}'`;
|
|
542
|
+
}).join("+");
|
|
543
|
+
return result.endsWith("+''") ? result.slice(0, -3) : result;
|
|
544
|
+
}
|
|
545
|
+
function getViewPath(workPath, src) {
|
|
546
|
+
const aSrc = src.startsWith("/") ? src : `/${src}`;
|
|
547
|
+
for (const mlType of fileType) {
|
|
548
|
+
const mlFullPath = `${workPath}${aSrc}${mlType}`;
|
|
549
|
+
if (fs.existsSync(mlFullPath)) {
|
|
550
|
+
return mlFullPath;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function escapeQuotes(input) {
|
|
555
|
+
return input.replace(/"/g, "'");
|
|
556
|
+
}
|
|
557
|
+
function isWrappedByBraces(str) {
|
|
558
|
+
return /\{\{.*\}\}/.test(str);
|
|
559
|
+
}
|
|
560
|
+
function splitWithBraces(str) {
|
|
561
|
+
const result = [];
|
|
562
|
+
let temp = "";
|
|
563
|
+
let inBraces = false;
|
|
564
|
+
for (let i = 0; i < str.length; i++) {
|
|
565
|
+
const char = str[i];
|
|
566
|
+
if (char === "{" && i + 1 < str.length && str[i + 1] === "{") {
|
|
567
|
+
inBraces = true;
|
|
568
|
+
temp += "{{";
|
|
569
|
+
i++;
|
|
570
|
+
} else if (char === "}" && i + 1 < str.length && str[i + 1] === "}") {
|
|
571
|
+
inBraces = false;
|
|
572
|
+
temp += "}}";
|
|
573
|
+
i++;
|
|
574
|
+
} else if (!inBraces && char === " ") {
|
|
575
|
+
if (temp) {
|
|
576
|
+
result.push(temp);
|
|
577
|
+
temp = "";
|
|
578
|
+
}
|
|
579
|
+
} else {
|
|
580
|
+
temp += char;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (temp) {
|
|
584
|
+
result.push(temp);
|
|
585
|
+
}
|
|
586
|
+
return result;
|
|
587
|
+
}
|
|
588
|
+
function parseClassRules(cssRule) {
|
|
589
|
+
let list = splitWithBraces(cssRule);
|
|
590
|
+
list = list.map((item) => {
|
|
591
|
+
return parseBraceExp(item);
|
|
592
|
+
});
|
|
593
|
+
if (list.length === 1) {
|
|
594
|
+
return list.pop();
|
|
595
|
+
}
|
|
596
|
+
return `[${list.join(",")}]`;
|
|
597
|
+
}
|
|
598
|
+
function getForItemName(attrs) {
|
|
599
|
+
for (const key in attrs) {
|
|
600
|
+
if (key.endsWith(":for-item")) {
|
|
601
|
+
return attrs[key];
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
return "item";
|
|
605
|
+
}
|
|
606
|
+
function getForIndexName(attrs) {
|
|
607
|
+
for (const key in attrs) {
|
|
608
|
+
if (key.endsWith(":for-index")) {
|
|
609
|
+
return attrs[key];
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return "index";
|
|
613
|
+
}
|
|
614
|
+
function parseForExp(exp, attrs) {
|
|
615
|
+
const item = getForItemName(attrs);
|
|
616
|
+
const index = getForIndexName(attrs);
|
|
617
|
+
const listVariableName = parseBraceExp(exp);
|
|
618
|
+
return `(${item}, ${index}) in ${listVariableName}`;
|
|
619
|
+
}
|
|
620
|
+
const braceRegex = /(\{\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}\})|([^{}]+)/g;
|
|
621
|
+
const noBraceRegex = /\{\{((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\}\}/;
|
|
622
|
+
const ternaryRegex = /[^?]+\?.+:.+/;
|
|
623
|
+
function parseBraceExp(exp) {
|
|
624
|
+
let result;
|
|
625
|
+
const group = [];
|
|
626
|
+
while (result = braceRegex.exec(exp)) {
|
|
627
|
+
if (result[1]) {
|
|
628
|
+
const matchResult = result[1].match(noBraceRegex);
|
|
629
|
+
if (matchResult) {
|
|
630
|
+
const statement = matchResult[1].trim();
|
|
631
|
+
if (ternaryRegex.test(statement)) {
|
|
632
|
+
group.push(`(${statement})`);
|
|
633
|
+
} else {
|
|
634
|
+
group.push(statement);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (result[2]) {
|
|
639
|
+
group.push(`+'${result[2].replace(/'/g, "\\'")}'+`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return group.join("").replace(/^\+|\+$/g, "");
|
|
643
|
+
}
|
|
644
|
+
const viewCompiler = {
|
|
645
|
+
splitWithBraces,
|
|
646
|
+
parseClassRules,
|
|
647
|
+
parseBraceExp,
|
|
648
|
+
parseKeyExpression,
|
|
649
|
+
compileML
|
|
650
|
+
};
|
|
651
|
+
module.exports = viewCompiler;
|