chocola 2.0.0-next.1 → 2.0.0-next.10
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 +34 -36
- package/compiler/chalk.js +34 -0
- package/compiler/component-processor.js +526 -398
- package/compiler/config.js +3 -56
- package/compiler/dom-processor.js +12 -75
- package/compiler/fs.js +0 -11
- package/compiler/index.js +74 -225
- package/compiler/module-graph.js +210 -0
- package/compiler/pipeline.js +54 -196
- package/compiler/render.js +181 -0
- package/compiler/runtime-generator.js +20 -15
- package/compiler/utils.js +79 -126
- package/dev/index.js +5 -11
- package/package.json +9 -12
- package/parser/component.js +268 -0
- package/parser/context.js +59 -0
- package/parser/css.js +96 -0
- package/parser/index.js +5 -0
- package/parser/template.js +120 -0
- package/parser/utils.js +32 -0
- package/runtime/index.js +312 -0
- package/server/index.js +402 -0
- package/utils.js +41 -6
|
@@ -1,510 +1,638 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { parseHTML } from "linkedom";
|
|
3
|
+
import { protectCurlyBraces } from "../utils.js";
|
|
4
|
+
import { genRandomId, runtimeFunctionId, throwError, deterministicHash, warnConstantCondition, warnUnusedDeclaration, findElementLine } from "./utils.js";
|
|
5
|
+
import {
|
|
6
|
+
extractPropsDefaults, extractRuntime, extractTopLevelFunctions, extractTopLevelVariables,
|
|
7
|
+
extractCtxFromEl, hasMountIf, getMountIf,
|
|
8
|
+
reservedAttrs, validateChainStructure, applyConditionalToElement, interpolateNode,
|
|
9
|
+
scopeCss, compileExpr, evaluateConstant,
|
|
10
|
+
} from "../parser/index.js";
|
|
11
|
+
import chalk from "./chalk.js";
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ProcessContext {
|
|
16
|
+
constructor(loadedComponents, runtimeChunks, compIdColl, runtimeMap, cssScopes, cssScopesMap, scopedStyles, staticCtxRegistry, csrClasses) {
|
|
17
|
+
this.loadedComponents = loadedComponents;
|
|
18
|
+
this.runtimeChunks = runtimeChunks;
|
|
19
|
+
this.compIdColl = compIdColl;
|
|
20
|
+
this.runtimeMap = runtimeMap;
|
|
21
|
+
this.cssScopes = cssScopes;
|
|
22
|
+
this.cssScopesMap = cssScopesMap;
|
|
23
|
+
this.scopedStyles = scopedStyles;
|
|
24
|
+
this.staticCtxRegistry = staticCtxRegistry;
|
|
25
|
+
this.csrClasses = csrClasses;
|
|
26
|
+
this.unusedWarned = new Set();
|
|
13
27
|
}
|
|
14
|
-
return false;
|
|
15
28
|
}
|
|
16
29
|
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
if (s.startsWith("." + cssId)) return s;
|
|
20
|
-
if (hasCombinator(s)) return `.${cssId} ${s}`;
|
|
21
|
-
return `.${cssId}${s}, .${cssId} ${s}`;
|
|
30
|
+
function escapeForTemplateLiteral(str) {
|
|
31
|
+
return str.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\${/g, "\\${");
|
|
22
32
|
}
|
|
23
33
|
|
|
24
|
-
function
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
function parseFragment(html, doc) {
|
|
35
|
+
const fragment = doc.createDocumentFragment();
|
|
36
|
+
const temp = doc.createElement("div");
|
|
37
|
+
temp.innerHTML = html;
|
|
38
|
+
const children = [...temp.childNodes];
|
|
39
|
+
for (const child of children) {
|
|
40
|
+
fragment.appendChild(child);
|
|
30
41
|
}
|
|
42
|
+
return fragment;
|
|
43
|
+
}
|
|
31
44
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
function generateCSRClass(compName, cx, explicitClassName) {
|
|
46
|
+
if (cx.csrClasses.has(compName)) return;
|
|
47
|
+
|
|
48
|
+
let instance = cx.loadedComponents.get(compName);
|
|
49
|
+
if (!instance) return;
|
|
50
|
+
|
|
51
|
+
instance = protectCurlyBraces(instance);
|
|
52
|
+
const dom = parseHTML(instance);
|
|
53
|
+
const doc = dom.document;
|
|
54
|
+
const script = doc.querySelector("script")?.innerHTML;
|
|
55
|
+
const template = doc.querySelector("template")?.innerHTML;
|
|
56
|
+
const styles = doc.querySelector("style")?.innerHTML;
|
|
57
|
+
|
|
58
|
+
if (!template) return;
|
|
59
|
+
|
|
60
|
+
const compProps = extractPropsDefaults(script);
|
|
61
|
+
const topFuncSrc = extractTopLevelFunctions(script || "", RUNTIME_KW);
|
|
62
|
+
const topVars = extractTopLevelVariables(script || "");
|
|
63
|
+
let runtime = extractRuntime(script || "", compName);
|
|
64
|
+
|
|
65
|
+
if (!cx.cssScopesMap.has(compName)) {
|
|
66
|
+
cx.cssScopesMap.set(compName, deterministicHash(compName, 8));
|
|
67
|
+
}
|
|
68
|
+
const cssId = cx.cssScopesMap.get(compName);
|
|
69
|
+
|
|
70
|
+
if (styles) {
|
|
71
|
+
cx.scopedStyles.push(scopeCss(styles, cssId));
|
|
45
72
|
}
|
|
46
73
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
74
|
+
const childMappings = [];
|
|
75
|
+
const bindVarNames = new Set();
|
|
76
|
+
const templateDoc = parseFragment(template, doc);
|
|
77
|
+
const seenTags = new Set();
|
|
78
|
+
for (const el of templateDoc.querySelectorAll("*")) {
|
|
79
|
+
const tag = el.tagName.toLowerCase();
|
|
80
|
+
if (!seenTags.has(tag)) {
|
|
81
|
+
seenTags.add(tag);
|
|
82
|
+
const childCompName = tag + ".html";
|
|
83
|
+
if (cx.loadedComponents.has(childCompName)) {
|
|
84
|
+
generateCSRClass(childCompName, cx);
|
|
85
|
+
const childClassName = childCompName.replace(".html", "").replace(/^\w/, c => c.toUpperCase());
|
|
86
|
+
childMappings.push({ tag, compClass: childClassName });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const attr of el.attributes) {
|
|
90
|
+
if (attr.name.startsWith("bind:")) {
|
|
91
|
+
bindVarNames.add(attr.value);
|
|
55
92
|
}
|
|
56
93
|
}
|
|
57
|
-
return s.length - 1;
|
|
58
94
|
}
|
|
59
95
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
break;
|
|
96
|
+
let csrRuntimeSource = null;
|
|
97
|
+
const injectedNames = new Set(compProps.map(p => p.name));
|
|
98
|
+
for (const varName of bindVarNames) injectedNames.add(varName);
|
|
99
|
+
const topVarsToInject = topVars.filter(v => !injectedNames.has(v.name));
|
|
100
|
+
if (runtime) {
|
|
101
|
+
let injectCode = "";
|
|
102
|
+
for (const { name, defaultValue } of compProps) {
|
|
103
|
+
if (defaultValue !== undefined) {
|
|
104
|
+
injectCode += `let ${name} = ctx.${name}??(${defaultValue});\n`;
|
|
105
|
+
} else {
|
|
106
|
+
injectCode += `let ${name} = ctx.${name};\n`;
|
|
72
107
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (header.trim().startsWith("@")) {
|
|
78
|
-
const atKeyword = header.trim().split(/\s+/)[0].toLowerCase();
|
|
79
|
-
if (scopeInnerAtRules.has(atKeyword)) {
|
|
80
|
-
out += header + "{" + processBlock(inner) + "}";
|
|
81
|
-
} else {
|
|
82
|
-
out += header + "{" + inner + "}";
|
|
83
|
-
}
|
|
108
|
+
}
|
|
109
|
+
for (const { keyword, name, value } of topVarsToInject) {
|
|
110
|
+
if (value !== undefined) {
|
|
111
|
+
injectCode += `${keyword} ${name} = ctx.${name}??(${value});\n`;
|
|
84
112
|
} else {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
? selectors.map(sel => scopeSelector(sel, cssId)).join(", ")
|
|
92
|
-
: header;
|
|
93
|
-
out += scopedHeader + "{" + innerScoped + "}";
|
|
113
|
+
injectCode += `${keyword} ${name};\n`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const varName of bindVarNames) {
|
|
117
|
+
if (varName !== "self") {
|
|
118
|
+
injectCode += `let ${varName} = ctx.${varName};\n`;
|
|
94
119
|
}
|
|
120
|
+
}
|
|
121
|
+
if (topFuncSrc.length > 0) {
|
|
122
|
+
injectCode += "\n" + topFuncSrc.join("\n\n") + "\n";
|
|
123
|
+
}
|
|
124
|
+
runtime = runtime.replace(/\$runtime\([^)]*\)\s*\{/, match => match + "\n" + injectCode);
|
|
125
|
+
runtime = runtime.replace(`${RUNTIME_KW}()`, `function(self, ctx)`);
|
|
126
|
+
csrRuntimeSource = runtime.replace(/^(async\s+)?function\s+\w+/, "$1function");
|
|
127
|
+
}
|
|
95
128
|
|
|
96
|
-
|
|
129
|
+
const className = explicitClassName || compName.replace(".html", "").replace(/^\w/, c => c.toUpperCase());
|
|
130
|
+
const propsParts = [];
|
|
131
|
+
for (const { name, defaultValue } of compProps) {
|
|
132
|
+
propsParts.push(`${JSON.stringify(name)}: ${defaultValue !== undefined ? defaultValue : "null"}`);
|
|
133
|
+
}
|
|
134
|
+
for (const { name, value } of topVarsToInject) {
|
|
135
|
+
if (value !== undefined) {
|
|
136
|
+
propsParts.push(`${JSON.stringify(name)}: ${value}`);
|
|
97
137
|
}
|
|
98
|
-
return out;
|
|
99
138
|
}
|
|
100
139
|
|
|
101
|
-
|
|
140
|
+
const childrenPart = childMappings.length > 0
|
|
141
|
+
? ",\n children: [" + childMappings.map(m => `{tag:"${m.tag}",compClass:${m.compClass}}`).join(",") + "]"
|
|
142
|
+
: "";
|
|
143
|
+
const runtimePart = csrRuntimeSource ? `,\n runtime: ${csrRuntimeSource}` : "";
|
|
144
|
+
const propsPart = propsParts.length > 0 ? `{ ${propsParts.join(", ")} }` : "{}";
|
|
145
|
+
const classDef = `class ${className} extends ChocolaComponent {\n constructor() {\n super({\n template: \`${escapeForTemplateLiteral(template)}\`,\n hash: "${cssId}",\n props: ${propsPart}${runtimePart}${childrenPart}\n });\n }\n}`;
|
|
146
|
+
cx.csrClasses.set(compName, classDef);
|
|
102
147
|
}
|
|
103
148
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
149
|
+
const BARE_IDENTIFIER_RE = /(?<![.\w$])[a-zA-Z_$][0-9a-zA-Z_$]*/g;
|
|
150
|
+
const PROPERTY_IDENTIFIER_RE = /\.([a-zA-Z_$][0-9a-zA-Z_$]*)/g;
|
|
151
|
+
|
|
152
|
+
function countIdentifiers(text, counts) {
|
|
153
|
+
for (const re of [BARE_IDENTIFIER_RE, PROPERTY_IDENTIFIER_RE]) {
|
|
154
|
+
re.lastIndex = 0;
|
|
155
|
+
for (const m of text.matchAll(re)) counts.set(m[1] ?? m[0], (counts.get(m[1] ?? m[0]) || 0) + 1);
|
|
110
156
|
}
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
function getDelIfAttr(el) {
|
|
114
|
-
return el.getAttribute("del:if") ?? el.getAttribute("del-if");
|
|
157
|
+
return counts;
|
|
115
158
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
159
|
+
|
|
160
|
+
function escapeNameForRegex(name) {
|
|
161
|
+
return name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
119
162
|
}
|
|
120
163
|
|
|
121
|
-
function
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return Function("ctx", `with(ctx) { return (${expr}); }`)(ctxProxy);
|
|
126
|
-
} catch {
|
|
127
|
-
return "";
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
} else {
|
|
131
|
-
node.childNodes.forEach(child => interpolateNode(child, ctxProxy));
|
|
132
|
-
}
|
|
164
|
+
function findLineInSource(source, regex) {
|
|
165
|
+
const match = regex.exec(source);
|
|
166
|
+
if (!match) return null;
|
|
167
|
+
return source.substring(0, match.index).split("\n").length;
|
|
133
168
|
}
|
|
134
169
|
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
170
|
+
function warnUnusedDeclarations(cx, compName, instance, script, fragment) {
|
|
171
|
+
if (!script && !fragment.querySelector("[bind\\:]")) return;
|
|
172
|
+
if (cx.unusedWarned.has(compName)) return;
|
|
173
|
+
cx.unusedWarned.add(compName);
|
|
174
|
+
|
|
175
|
+
const props = extractPropsDefaults(script).map(p => p.name);
|
|
176
|
+
const topVars = extractTopLevelVariables(script).map(v => v.name);
|
|
177
|
+
const topFuncs = extractTopLevelFunctions(script, RUNTIME_KW)
|
|
178
|
+
.map(src => src.match(/^(?:async\s+)?function\s+([a-zA-Z_$][0-9a-zA-Z_$]*)/)?.[1])
|
|
179
|
+
.filter(Boolean);
|
|
180
|
+
|
|
181
|
+
const bindings = [];
|
|
182
|
+
for (const el of fragment.querySelectorAll("*")) {
|
|
183
|
+
for (const attr of el.attributes) {
|
|
184
|
+
if (attr.name.startsWith("bind:")) bindings.push({ name: attr.value, element: el });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
139
187
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const hasDelIf = hasDelIfAttr(child, sourceFile);
|
|
143
|
-
const hasElif = child.hasAttribute("elif");
|
|
144
|
-
const hasElse = child.hasAttribute("else");
|
|
188
|
+
const counts = new Map();
|
|
189
|
+
if (script) countIdentifiers(script, counts);
|
|
145
190
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
hits++;
|
|
158
|
-
if (hits === outerCounts[outer]) {
|
|
159
|
-
let line = parentContent.substring(0, searchIdx).split("\n").length;
|
|
160
|
-
if (sourceContent !== parentContent) {
|
|
161
|
-
const anchor = parentContent.trim().slice(0, 80);
|
|
162
|
-
const vars = [
|
|
163
|
-
anchor,
|
|
164
|
-
anchor.replace(/=""/g, ' '),
|
|
165
|
-
anchor.replace(/=""/g, ''),
|
|
166
|
-
anchor.replace(/="/g, "='").replace(/"/g, "'"),
|
|
167
|
-
];
|
|
168
|
-
let anchorIdx = -1;
|
|
169
|
-
for (const v of vars) {
|
|
170
|
-
anchorIdx = sourceContent.indexOf(v);
|
|
171
|
-
if (anchorIdx !== -1) break;
|
|
172
|
-
}
|
|
173
|
-
if (anchorIdx !== -1) {
|
|
174
|
-
const offset = sourceContent.substring(0, anchorIdx).split("\n").length;
|
|
175
|
-
line = offset + line - 1;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
loc = `${sourceFile}:${line}`;
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
searchIdx += outer.length;
|
|
182
|
-
}
|
|
191
|
+
const walk = (node) => {
|
|
192
|
+
if (node.nodeType === 3) {
|
|
193
|
+
for (const m of node.textContent.matchAll(/\{([^}]+)\}/g)) countIdentifiers(m[1], counts);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (node.attributes) {
|
|
197
|
+
for (const attr of node.attributes) {
|
|
198
|
+
if (attr.name.startsWith("bind:")) {
|
|
199
|
+
countIdentifiers(attr.value, counts);
|
|
200
|
+
} else {
|
|
201
|
+
for (const m of attr.value.matchAll(/\{([^}]+)\}/g)) countIdentifiers(m[1], counts);
|
|
183
202
|
}
|
|
184
|
-
throwError(`${loc}\n <${tag}> has ${attr} without a preceding if/del-if sibling`);
|
|
185
|
-
}
|
|
186
|
-
if (hasElse) {
|
|
187
|
-
chainActive = false;
|
|
188
203
|
}
|
|
189
204
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
205
|
+
for (const child of node.childNodes) walk(child);
|
|
206
|
+
};
|
|
207
|
+
walk(fragment);
|
|
208
|
+
|
|
209
|
+
const isUnused = (name) => (counts.get(name) || 0) <= 1;
|
|
210
|
+
const warn = (kind, name, declRegex) => {
|
|
211
|
+
const lineNum = findLineInSource(instance, declRegex);
|
|
212
|
+
warnUnusedDeclaration(lineNum !== null ? `${compName}:${lineNum}` : compName, kind, name);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
for (const name of props) {
|
|
216
|
+
if (isUnused(name)) warn("prop", name, new RegExp("export\\s+let\\s+" + escapeNameForRegex(name) + "\\b"));
|
|
217
|
+
}
|
|
218
|
+
for (const name of topVars) {
|
|
219
|
+
if (isUnused(name)) warn("variable", name, new RegExp("(?:^|[^\\w])(?:let|const)\\s+" + escapeNameForRegex(name) + "\\b"));
|
|
220
|
+
}
|
|
221
|
+
for (const name of topFuncs) {
|
|
222
|
+
if (isUnused(name)) warn("function", name, new RegExp("(?:async\\s+)?function\\s+" + escapeNameForRegex(name) + "\\b"));
|
|
223
|
+
}
|
|
224
|
+
const seenBindings = new Set();
|
|
225
|
+
for (const { name, element } of bindings) {
|
|
226
|
+
if (seenBindings.has(name)) continue;
|
|
227
|
+
seenBindings.add(name);
|
|
228
|
+
if (isUnused(name)) {
|
|
229
|
+
const lineNum = findElementLine(instance, element.outerHTML);
|
|
230
|
+
warnUnusedDeclaration(lineNum !== null ? `${compName}:${lineNum}` : compName, "binding", name);
|
|
195
231
|
}
|
|
196
|
-
|
|
197
|
-
validateChainStructure(child, sourceFile, sourceContent, parentContent);
|
|
198
232
|
}
|
|
199
233
|
}
|
|
200
234
|
|
|
201
|
-
/**
|
|
202
|
-
* Processes a single component element and inserts it into the DOM
|
|
203
|
-
* @param {Element} element
|
|
204
|
-
* @param {Map} loadedComponents
|
|
205
|
-
* @param {Array} runtimeChunks
|
|
206
|
-
* @param {Array} compIdColl
|
|
207
|
-
* @param {object} letterState - { value: string }
|
|
208
|
-
* @returns {boolean} - true if component was processed, false if not found
|
|
209
|
-
*/
|
|
210
235
|
export function processComponentElement(
|
|
211
236
|
element,
|
|
212
|
-
|
|
213
|
-
runtimeChunks,
|
|
214
|
-
compIdColl,
|
|
215
|
-
letterState,
|
|
216
|
-
runtimeMap,
|
|
217
|
-
cssScopes,
|
|
218
|
-
cssScopesMap,
|
|
219
|
-
scopedStyles,
|
|
237
|
+
cx,
|
|
220
238
|
renderChain = [],
|
|
221
|
-
staticCtxRegistry,
|
|
222
239
|
sourceFile,
|
|
223
|
-
sourceContent
|
|
240
|
+
sourceContent,
|
|
241
|
+
globalCtx = {}
|
|
224
242
|
) {
|
|
225
243
|
const tagName = element.tagName.toLowerCase();
|
|
226
|
-
const compName = tagName + ".
|
|
227
|
-
|
|
244
|
+
const compName = tagName + ".html";
|
|
245
|
+
let instance = cx.loadedComponents.get(compName);
|
|
228
246
|
|
|
229
247
|
if (!instance || instance === undefined) return false;
|
|
230
248
|
if (renderChain && renderChain.includes(compName)) return false;
|
|
231
249
|
|
|
250
|
+
instance = protectCurlyBraces(instance);
|
|
251
|
+
const dom = parseHTML(instance);
|
|
252
|
+
const doc = dom.document;
|
|
253
|
+
let script = doc.querySelector("script")?.innerHTML;
|
|
254
|
+
let template = doc.querySelector("template")?.innerHTML;
|
|
255
|
+
let styles = doc.querySelector("style")?.innerHTML;
|
|
256
|
+
|
|
257
|
+
if (!template) {
|
|
258
|
+
console.warn(chalk.yellow(`${compName} — component is missing a <template>`));
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (script) {
|
|
263
|
+
const importRegex = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?\s*/g;
|
|
264
|
+
script = script.replace(importRegex, (_, importedName, importPath) => {
|
|
265
|
+
const importedCompName = path.basename(importPath).toLowerCase();
|
|
266
|
+
if (cx.loadedComponents.has(importedCompName)) {
|
|
267
|
+
generateCSRClass(importedCompName, cx, importedName);
|
|
268
|
+
}
|
|
269
|
+
return "";
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const compProps = extractPropsDefaults(script);
|
|
274
|
+
|
|
232
275
|
let ctx;
|
|
233
|
-
if (staticCtxRegistry && staticCtxRegistry.has(element)) {
|
|
234
|
-
ctx = staticCtxRegistry.get(element);
|
|
276
|
+
if (cx.staticCtxRegistry && cx.staticCtxRegistry.has(element)) {
|
|
277
|
+
ctx = cx.staticCtxRegistry.get(element);
|
|
235
278
|
} else {
|
|
236
|
-
ctx =
|
|
237
|
-
|
|
279
|
+
ctx = extractCtxFromEl(element, globalCtx);
|
|
280
|
+
if (globalCtx && typeof globalCtx === "object") {
|
|
281
|
+
for (const [k, v] of Object.entries(globalCtx)) {
|
|
282
|
+
if (!(k in ctx)) ctx[k] = v;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
cx.staticCtxRegistry && cx.staticCtxRegistry.set(element, ctx);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (compProps.length > 0) {
|
|
289
|
+
compProps.forEach(({ name, defaultValue }) => {
|
|
290
|
+
if (defaultValue !== undefined && !(name in ctx)) {
|
|
291
|
+
try {
|
|
292
|
+
ctx[name] = compileExpr(defaultValue, false)();
|
|
293
|
+
} catch {
|
|
294
|
+
ctx[name] = defaultValue;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
238
298
|
}
|
|
239
|
-
|
|
299
|
+
|
|
300
|
+
const topFuncSrc = extractTopLevelFunctions(script || "", RUNTIME_KW);
|
|
301
|
+
const topVars = extractTopLevelVariables(script || "");
|
|
302
|
+
for (const { name, value } of topVars) {
|
|
303
|
+
if (name in ctx) continue;
|
|
304
|
+
if (value !== undefined) {
|
|
305
|
+
try {
|
|
306
|
+
ctx[name] = compileExpr(value, false)();
|
|
307
|
+
} catch {}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
for (const src of topFuncSrc) {
|
|
311
|
+
try {
|
|
312
|
+
const fn = (0, eval)("(" + src + ")");
|
|
313
|
+
const name = fn.name;
|
|
314
|
+
if (name && !(name in ctx)) ctx[name] = fn;
|
|
315
|
+
} catch {}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const elInnerHtml = element.innerHTML;
|
|
240
319
|
|
|
241
320
|
const ctxProxy = new Proxy(ctx, {
|
|
242
321
|
has() { return true; },
|
|
243
322
|
get(target, key) { return target[key]; }
|
|
244
323
|
});
|
|
245
324
|
|
|
246
|
-
|
|
247
|
-
|
|
325
|
+
const fragment = parseFragment(template, doc);
|
|
326
|
+
|
|
327
|
+
warnUnusedDeclarations(cx, compName, instance, script, fragment);
|
|
248
328
|
|
|
249
|
-
|
|
329
|
+
const slotFragment = parseFragment(elInnerHtml, doc);
|
|
330
|
+
if (sourceFile) {
|
|
331
|
+
validateChainStructure(slotFragment, sourceFile, sourceContent, elInnerHtml);
|
|
332
|
+
}
|
|
333
|
+
validateChainStructure(fragment, instance.__sourceFile || compName, instance, template);
|
|
334
|
+
Array.from(fragment.querySelectorAll("slot")).forEach(slot => {
|
|
335
|
+
slot.replaceWith(slotFragment);
|
|
336
|
+
});
|
|
250
337
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
338
|
+
const childEntries = Array.from(fragment.querySelectorAll("*")).map(el => ({
|
|
339
|
+
el,
|
|
340
|
+
parent: el.parentNode
|
|
341
|
+
}));
|
|
342
|
+
const condChains = new Map();
|
|
343
|
+
const bindings = [];
|
|
344
|
+
const elBindIds = new Map();
|
|
345
|
+
let bindCounter = 0;
|
|
346
|
+
|
|
347
|
+
const conditionalLocations = new Map();
|
|
348
|
+
for (const { el } of childEntries) {
|
|
349
|
+
if (!el.hasAttribute("if") && !hasMountIf(el) && !el.hasAttribute("elif")) continue;
|
|
350
|
+
let location = sourceFile;
|
|
351
|
+
if (instance) {
|
|
352
|
+
const lineNum = findElementLine(instance, el.outerHTML);
|
|
353
|
+
if (lineNum !== null) location = `${compName}:${lineNum}`;
|
|
254
354
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
355
|
+
if (location === sourceFile && sourceContent) {
|
|
356
|
+
const lineNum = findElementLine(sourceContent, el.outerHTML);
|
|
357
|
+
if (lineNum !== null) location = `${sourceFile}:${lineNum}`;
|
|
358
|
+
}
|
|
359
|
+
conditionalLocations.set(el, location);
|
|
360
|
+
}
|
|
259
361
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
parent:
|
|
263
|
-
}
|
|
264
|
-
const
|
|
362
|
+
childEntries.forEach(({ el: child, parent }) => {
|
|
363
|
+
if (!condChains.has(parent)) {
|
|
364
|
+
condChains.set(parent, { active: false, rendered: false });
|
|
365
|
+
}
|
|
366
|
+
const condChain = condChains.get(parent);
|
|
265
367
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const condChain = condChains.get(parent);
|
|
368
|
+
const hasIf = child.hasAttribute("if");
|
|
369
|
+
const hasDelIf = hasMountIf(child);
|
|
370
|
+
const hasElif = child.hasAttribute("elif");
|
|
371
|
+
const hasElse = child.hasAttribute("else");
|
|
271
372
|
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
const
|
|
275
|
-
const
|
|
373
|
+
if (hasIf || hasDelIf || hasElif) {
|
|
374
|
+
const location = conditionalLocations.get(child) || sourceFile;
|
|
375
|
+
const stripBraces = (raw) => raw.startsWith("{") ? raw.slice(1, -1) : raw;
|
|
376
|
+
const tag = child.tagName.toLowerCase();
|
|
377
|
+
const warnIfConstant = (expr, attr) => {
|
|
378
|
+
const { constant, value } = evaluateConstant(expr);
|
|
379
|
+
if (constant) warnConstantCondition(location, tag, attr, expr, Boolean(value));
|
|
380
|
+
};
|
|
381
|
+
if (hasIf) warnIfConstant(stripBraces(child.getAttribute("if")), "if");
|
|
382
|
+
if (hasDelIf) warnIfConstant(stripBraces(getMountIf(child)), "mount:if");
|
|
383
|
+
if (hasElif) warnIfConstant(stripBraces(child.getAttribute("elif")), "elif");
|
|
384
|
+
}
|
|
276
385
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
386
|
+
if (hasElif || hasElse) {
|
|
387
|
+
if (!condChain.active) {
|
|
388
|
+
throwError(`${instance.__sourceFile || compName}: <${child.tagName.toLowerCase()}> has ${hasElif ? "elif" : "else"} without a preceding if/mount:if sibling`);
|
|
389
|
+
}
|
|
390
|
+
if (condChain.rendered) {
|
|
391
|
+
child.remove();
|
|
392
|
+
if (hasElse) {
|
|
393
|
+
condChain.active = false;
|
|
287
394
|
}
|
|
395
|
+
return;
|
|
288
396
|
}
|
|
397
|
+
}
|
|
289
398
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
399
|
+
if (child.tagName.toLowerCase() === "void") {
|
|
400
|
+
if (hasElif || hasElse) {
|
|
401
|
+
if (hasElif) {
|
|
402
|
+
const expr = child.getAttribute("elif").slice(1, -1);
|
|
403
|
+
const fn = compileExpr(expr, true);
|
|
404
|
+
if (!fn(ctxProxy)) {
|
|
405
|
+
child.remove();
|
|
406
|
+
return;
|
|
299
407
|
}
|
|
408
|
+
}
|
|
409
|
+
child.replaceWith(...child.children);
|
|
410
|
+
condChain.rendered = true;
|
|
411
|
+
if (hasElse) {
|
|
412
|
+
condChain.active = false;
|
|
413
|
+
}
|
|
414
|
+
} else if (hasIf || hasDelIf) {
|
|
415
|
+
const raw = hasIf ? child.getAttribute("if") : getMountIf(child);
|
|
416
|
+
const expr = raw.slice(1, -1);
|
|
417
|
+
const fn = compileExpr(expr, true);
|
|
418
|
+
condChain.active = true;
|
|
419
|
+
if (fn(ctxProxy)) {
|
|
300
420
|
child.replaceWith(...child.children);
|
|
301
421
|
condChain.rendered = true;
|
|
302
|
-
if (hasElse) {
|
|
303
|
-
condChain.active = false;
|
|
304
|
-
}
|
|
305
|
-
} else if (hasIf || hasDelIf) {
|
|
306
|
-
const raw = hasIf ? child.getAttribute("if") : getDelIfAttr(child);
|
|
307
|
-
const expr = raw.slice(1, -1);
|
|
308
|
-
const fn = new Function("ctx", `with(ctx) { return (${expr}); }`);
|
|
309
|
-
condChain.active = true;
|
|
310
|
-
if (fn(ctxProxy)) {
|
|
311
|
-
child.replaceWith(...child.children);
|
|
312
|
-
condChain.rendered = true;
|
|
313
|
-
} else {
|
|
314
|
-
child.remove();
|
|
315
|
-
condChain.rendered = false;
|
|
316
|
-
}
|
|
317
422
|
} else {
|
|
318
|
-
child.
|
|
319
|
-
condChain.active = false;
|
|
423
|
+
child.remove();
|
|
320
424
|
condChain.rendered = false;
|
|
321
425
|
}
|
|
322
|
-
|
|
426
|
+
} else {
|
|
427
|
+
child.replaceWith(...child.children);
|
|
428
|
+
condChain.active = false;
|
|
429
|
+
condChain.rendered = false;
|
|
323
430
|
}
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
324
433
|
|
|
325
|
-
|
|
434
|
+
Array.from(child.attributes).forEach(attribute => {
|
|
435
|
+
if (!attribute || attribute === undefined) return;
|
|
436
|
+
if (reservedAttrs.includes(attribute.name)) return;
|
|
437
|
+
|
|
438
|
+
if (attribute.name.startsWith("bind:")) {
|
|
439
|
+
const prop = attribute.name.slice(5);
|
|
440
|
+
const varName = attribute.value;
|
|
441
|
+
let bindId = elBindIds.get(child);
|
|
442
|
+
if (!bindId) {
|
|
443
|
+
bindId = "b" + (bindCounter++);
|
|
444
|
+
elBindIds.set(child, bindId);
|
|
445
|
+
child.setAttribute("data-chbind-" + bindId, "");
|
|
446
|
+
}
|
|
447
|
+
bindings.push({ prop, varName, bindId });
|
|
448
|
+
child.removeAttribute(attribute.name);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
326
451
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
attribute.value = attribute.value.replace(
|
|
452
|
+
child.setAttribute(
|
|
453
|
+
attribute.name,
|
|
454
|
+
attribute.value.replace(
|
|
331
455
|
/\{([^}]+)\}/g,
|
|
332
456
|
(_, expr) => {
|
|
333
457
|
try {
|
|
334
|
-
return
|
|
458
|
+
return compileExpr(expr, true)(ctxProxy);
|
|
335
459
|
} catch {
|
|
336
460
|
return "";
|
|
337
461
|
}
|
|
338
462
|
}
|
|
339
|
-
)
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
processComponentElement(
|
|
343
|
-
child,
|
|
344
|
-
loadedComponents,
|
|
345
|
-
runtimeChunks,
|
|
346
|
-
compIdColl,
|
|
347
|
-
letterState,
|
|
348
|
-
runtimeMap,
|
|
349
|
-
cssScopes,
|
|
350
|
-
cssScopesMap,
|
|
351
|
-
scopedStyles,
|
|
352
|
-
renderChain.concat(compName),
|
|
353
|
-
staticCtxRegistry,
|
|
354
|
-
instance.__sourceFile || compName,
|
|
355
|
-
body
|
|
463
|
+
)
|
|
356
464
|
);
|
|
465
|
+
});
|
|
357
466
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
467
|
+
const condAttrs = {};
|
|
468
|
+
if (hasIf) condAttrs["if"] = child.getAttribute("if");
|
|
469
|
+
if (hasDelIf) condAttrs["mount:if"] = getMountIf(child);
|
|
470
|
+
if (hasElif) condAttrs["elif"] = child.getAttribute("elif");
|
|
471
|
+
if (hasElse) condAttrs["else"] = "";
|
|
472
|
+
|
|
473
|
+
const processed = processComponentElement(
|
|
474
|
+
child,
|
|
475
|
+
cx,
|
|
476
|
+
renderChain.concat(compName),
|
|
477
|
+
compName,
|
|
478
|
+
template,
|
|
479
|
+
globalCtx
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
let condTarget = child;
|
|
483
|
+
if (processed && processed.nodeType === 1) {
|
|
484
|
+
condTarget = processed;
|
|
485
|
+
for (const [name, value] of Object.entries(condAttrs)) {
|
|
486
|
+
condTarget.setAttribute(name, value);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
applyConditionalToElement(condTarget, ctxProxy, condChain, hasIf, hasDelIf, hasElif, hasElse);
|
|
491
|
+
|
|
492
|
+
interpolateNode(condTarget, ctxProxy)
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
let csrRuntimeSource = null;
|
|
496
|
+
const firstChild = fragment.children[0];
|
|
497
|
+
|
|
498
|
+
if (firstChild && firstChild.nodeType === 1) {
|
|
499
|
+
if (script) {
|
|
500
|
+
const compId = "chid-" + deterministicHash(compName + ":" + cx.compIdColl.length, 8);
|
|
501
|
+
cx.compIdColl.push(compId);
|
|
502
|
+
firstChild.setAttribute("chid", compId);
|
|
503
|
+
|
|
504
|
+
const ctxRegex = /ctx\s*=\s*({.*?})/;
|
|
505
|
+
const ctxMatch = script.match(ctxRegex);
|
|
506
|
+
let runtimeCtx = {};
|
|
507
|
+
if (ctxMatch) {
|
|
508
|
+
try {
|
|
509
|
+
runtimeCtx = JSON.parse(ctxMatch[1].replace(/(\w+):/g, '"$1":'));
|
|
510
|
+
} catch (e) {
|
|
511
|
+
runtimeCtx = {};
|
|
378
512
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
513
|
+
}
|
|
514
|
+
const ctxDefParts = [];
|
|
515
|
+
const declared = new Set();
|
|
516
|
+
for (const [key, value] of Object.entries(runtimeCtx)) {
|
|
517
|
+
ctxDefParts.push(`let ${key} = ctx.${key}??${JSON.stringify(value)};\n`);
|
|
518
|
+
declared.add(key);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
for (const { name, defaultValue } of compProps) {
|
|
522
|
+
if (declared.has(name)) continue;
|
|
523
|
+
if (defaultValue !== undefined) {
|
|
524
|
+
ctxDefParts.push(`let ${name} = ctx.${name}??(${defaultValue});\n`);
|
|
385
525
|
} else {
|
|
386
|
-
|
|
526
|
+
ctxDefParts.push(`let ${name} = ctx.${name};\n`);
|
|
387
527
|
}
|
|
388
|
-
child.removeAttribute("elif");
|
|
389
|
-
} else if (hasElse) {
|
|
390
|
-
condChain.rendered = true;
|
|
391
|
-
condChain.active = false;
|
|
392
|
-
child.removeAttribute("else");
|
|
393
|
-
} else {
|
|
394
|
-
condChain.active = false;
|
|
395
|
-
condChain.rendered = false;
|
|
396
528
|
}
|
|
397
529
|
|
|
398
|
-
|
|
399
|
-
});
|
|
530
|
+
const ctxDef = ctxDefParts.join("");
|
|
400
531
|
|
|
401
|
-
|
|
532
|
+
script = script.replace(ctxRegex, "ctx");
|
|
402
533
|
|
|
403
|
-
|
|
404
|
-
if (instance.script || instance.effects) {
|
|
405
|
-
const compId = "chid-" + genRandomId(compIdColl);
|
|
406
|
-
firstChild.setAttribute("chid", compId);
|
|
534
|
+
let runtime = extractRuntime(script, compName);
|
|
407
535
|
|
|
408
|
-
|
|
536
|
+
if (runtime) {
|
|
537
|
+
let fnEntry = cx.runtimeMap && cx.runtimeMap.get(compName);
|
|
538
|
+
let fnId;
|
|
539
|
+
if (!fnEntry) {
|
|
540
|
+
fnId = runtimeFunctionId(compName);
|
|
541
|
+
const topFuncs = topFuncSrc;
|
|
409
542
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
543
|
+
let injectCode = ctxDef;
|
|
544
|
+
for (const b of bindings) declared.add(b.varName);
|
|
545
|
+
const undeclaredTopVars = topVars.filter(v => !declared.has(v.name));
|
|
546
|
+
if (undeclaredTopVars.length > 0) {
|
|
547
|
+
injectCode += "\n" + undeclaredTopVars.map(v => v.value !== undefined
|
|
548
|
+
? `${v.keyword} ${v.name} = ctx.${v.name}??(${v.value});`
|
|
549
|
+
: `${v.keyword} ${v.name};`
|
|
550
|
+
).join("\n") + "\n";
|
|
418
551
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
runtimeChunks.push(
|
|
433
|
-
runtimeMap && runtimeMap.set(compName, {
|
|
552
|
+
if (bindings.length > 0) {
|
|
553
|
+
injectCode += "\n" + bindings.map(b => {
|
|
554
|
+
const accessor = b.prop === "self" ? "" : "." + b.prop;
|
|
555
|
+
return "let " + b.varName + " = self.querySelector('[data-chbind-" + b.bindId + "]')" + accessor + ";";
|
|
556
|
+
}).join("\n") + "\n";
|
|
557
|
+
}
|
|
558
|
+
if (topFuncs.length > 0) {
|
|
559
|
+
injectCode += "\n" + topFuncs.join("\n\n") + "\n";
|
|
560
|
+
}
|
|
561
|
+
runtime = runtime.replace(/\$runtime\([^)]*\)\s*\{/, match => match + "\n" + injectCode);
|
|
562
|
+
|
|
563
|
+
runtime = runtime.replace(`${RUNTIME_KW}()`, `${fnId}(self, ctx)`);
|
|
564
|
+
csrRuntimeSource = runtime.replace(/^function\s+\w+/, "function");
|
|
565
|
+
cx.runtimeChunks.push(runtime);
|
|
566
|
+
cx.runtimeMap && cx.runtimeMap.set(compName, { fnId });
|
|
434
567
|
} else {
|
|
435
|
-
|
|
568
|
+
fnId = fnEntry.fnId;
|
|
436
569
|
}
|
|
437
570
|
|
|
438
|
-
runtimeChunks.push(`${
|
|
571
|
+
cx.runtimeChunks.push(`${fnId}(document.querySelector('[chid="${compId}"]'), ${JSON.stringify(ctx)});`);
|
|
439
572
|
}
|
|
440
573
|
}
|
|
574
|
+
}
|
|
441
575
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
576
|
+
let cssId = cx.cssScopesMap && cx.cssScopesMap.get(compName);
|
|
577
|
+
if (!cssId) {
|
|
578
|
+
cssId = deterministicHash(compName, 8);
|
|
579
|
+
cx.cssScopesMap.set(compName, cssId);
|
|
580
|
+
}
|
|
581
|
+
if (fragment.children.length === 1 && firstChild.nodeType === 1) {
|
|
582
|
+
firstChild.classList.add(cssId);
|
|
583
|
+
}
|
|
584
|
+
if (styles) {
|
|
585
|
+
styles = scopeCss(styles, cssId);
|
|
586
|
+
cx.scopedStyles.push(styles);
|
|
587
|
+
}
|
|
455
588
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
589
|
+
if (csrRuntimeSource && !cx.csrClasses.has(compName)) {
|
|
590
|
+
generateCSRClass(compName, cx);
|
|
591
|
+
}
|
|
459
592
|
|
|
460
|
-
|
|
461
|
-
|
|
593
|
+
if (element.style.display === "none" && firstChild && firstChild.nodeType === 1) {
|
|
594
|
+
firstChild.style.display = "none";
|
|
462
595
|
}
|
|
463
596
|
|
|
464
|
-
|
|
465
|
-
return
|
|
597
|
+
element.replaceWith(fragment);
|
|
598
|
+
return firstChild && firstChild.nodeType === 1 ? firstChild : true;
|
|
466
599
|
}
|
|
467
600
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
601
|
+
export function processAllComponents(appElements, loadedComponents, pageSourceFile, pageSourceContent, globalCtx = {}) {
|
|
602
|
+
const cx = new ProcessContext(
|
|
603
|
+
loadedComponents, [], [], new Map(), [], new Map(), [], new Map(), new Map()
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
for (const [compName, instance] of cx.loadedComponents) {
|
|
607
|
+
const script = instance.match(/<script>([\s\S]*?)<\/script>/i);
|
|
608
|
+
if (script) {
|
|
609
|
+
const importRegex = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?\s*/g;
|
|
610
|
+
let match;
|
|
611
|
+
while ((match = importRegex.exec(script[1])) !== null) {
|
|
612
|
+
const importedName = match[1];
|
|
613
|
+
const importedCompName = path.basename(match[2]).toLowerCase();
|
|
614
|
+
if (cx.loadedComponents.has(importedCompName)) {
|
|
615
|
+
generateCSRClass(importedCompName, cx, importedName);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
487
620
|
|
|
488
621
|
appElements.forEach(el => {
|
|
489
|
-
|
|
622
|
+
if (!el.isConnected) return;
|
|
623
|
+
processComponentElement(el, cx, [], pageSourceFile, pageSourceContent, globalCtx);
|
|
490
624
|
});
|
|
491
|
-
const runtimeScript = runtimeChunks.join("\n");
|
|
492
|
-
const hasComponents = runtimeChunks.length > 0;
|
|
493
|
-
const scopesCss =
|
|
625
|
+
const runtimeScript = cx.runtimeChunks.join("\n");
|
|
626
|
+
const hasComponents = cx.runtimeChunks.length > 0;
|
|
627
|
+
const scopesCss = cx.scopedStyles.join("\n");
|
|
628
|
+
const csrClasses = [...cx.csrClasses.values()].join("\n\n");
|
|
629
|
+
|
|
630
|
+
const hashMap = {};
|
|
631
|
+
for (const [compName, hash] of cx.cssScopesMap) {
|
|
632
|
+
hashMap[compName] = hash;
|
|
633
|
+
}
|
|
494
634
|
|
|
495
|
-
return { runtimeScript, hasComponents, scopesCss };
|
|
635
|
+
return { runtimeScript, hasComponents, scopesCss, hashMap, csrClasses };
|
|
496
636
|
}
|
|
497
637
|
|
|
498
|
-
|
|
499
|
-
* Gets the next letter in sequence or starts with 'a'
|
|
500
|
-
* @param {object} letterState - { value: string }
|
|
501
|
-
* @returns {string}
|
|
502
|
-
*/
|
|
503
|
-
function getNextLetter(letterState) {
|
|
504
|
-
if (!letterState.value) {
|
|
505
|
-
letterState.value = "a";
|
|
506
|
-
} else {
|
|
507
|
-
letterState.value = incrementAlfabet(letterState.value);
|
|
508
|
-
}
|
|
509
|
-
return letterState.value;
|
|
510
|
-
}
|
|
638
|
+
const RUNTIME_KW = "$runtime";
|