@zeus-js/output-wc 0.1.1-beta.13 → 0.1.1-beta.15
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/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/capabilities.prod.cjs +2 -2
- package/dist/capabilities.prod.js +1 -1
- package/dist/output-wc.cjs +272 -107
- package/dist/output-wc.esm-bundler.js +321 -103
- package/dist/output-wc.prod.cjs +272 -107
- package/package.json +6 -6
package/dist/capabilities.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.1-beta.
|
|
2
|
+
* output-wc v0.1.1-beta.15
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -9,7 +9,7 @@ Object.defineProperties(exports, {
|
|
|
9
9
|
});
|
|
10
10
|
const ZEUS_OUTPUT_WC_CAPABILITIES = {
|
|
11
11
|
packageName: "@zeus-js/output-wc",
|
|
12
|
-
version: "0.1.1-beta.
|
|
12
|
+
version: "0.1.1-beta.15",
|
|
13
13
|
output: {
|
|
14
14
|
webComponent: true,
|
|
15
15
|
customElements: true,
|
package/dist/capabilities.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.1-beta.
|
|
2
|
+
* output-wc v0.1.1-beta.15
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -9,7 +9,7 @@ Object.defineProperties(exports, {
|
|
|
9
9
|
});
|
|
10
10
|
const ZEUS_OUTPUT_WC_CAPABILITIES = {
|
|
11
11
|
packageName: "@zeus-js/output-wc",
|
|
12
|
-
version: "0.1.1-beta.
|
|
12
|
+
version: "0.1.1-beta.15",
|
|
13
13
|
output: {
|
|
14
14
|
webComponent: true,
|
|
15
15
|
customElements: true,
|
package/dist/output-wc.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* output-wc v0.1.1-beta.
|
|
2
|
+
* output-wc v0.1.1-beta.15
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -31,11 +31,87 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
//#endregion
|
|
32
32
|
let node_path = require("node:path");
|
|
33
33
|
node_path = __toESM(node_path, 1);
|
|
34
|
+
let node_url = require("node:url");
|
|
34
35
|
let _zeus_js_bundler_plugin = require("@zeus-js/bundler-plugin");
|
|
35
36
|
let _zeus_js_component_dts = require("@zeus-js/component-dts");
|
|
37
|
+
//#region packages/web-c/output-wc/src/generateManifest.ts
|
|
38
|
+
function generateZeusComponentsManifest(manifest) {
|
|
39
|
+
validateComponentManifest(manifest);
|
|
40
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
41
|
+
}
|
|
42
|
+
function validateComponentManifest(manifest) {
|
|
43
|
+
if ((manifest === null || manifest === void 0 ? void 0 : manifest.schemaVersion) !== 1) throw new Error("[ZEUS_WC_ABI_VERSION] Component manifest schemaVersion must be 1.");
|
|
44
|
+
if (!Array.isArray(manifest.components)) throw new Error("[ZEUS_WC_INVALID_MANIFEST] Component manifest components must be an array.");
|
|
45
|
+
const tags = /* @__PURE__ */ new Set();
|
|
46
|
+
for (const [componentIndex, component] of manifest.components.entries()) {
|
|
47
|
+
if (!component || typeof component.tag !== "string") throw new Error(`[ZEUS_WC_INVALID_MANIFEST] components[${componentIndex}].tag must be a string.`);
|
|
48
|
+
if (tags.has(component.tag)) throw new Error(`[ZEUS_WC_DUPLICATE_TAG] Component tag "${component.tag}" is declared more than once.`);
|
|
49
|
+
tags.add(component.tag);
|
|
50
|
+
}
|
|
51
|
+
for (const [componentIndex, component] of manifest.components.entries()) {
|
|
52
|
+
var _component$props, _component$events, _component$props2;
|
|
53
|
+
const componentPath = `components[${componentIndex}]`;
|
|
54
|
+
if (!component || typeof component.tag !== "string" || typeof component.exportName !== "string") throw new Error(`[ZEUS_WC_INVALID_MANIFEST] ${componentPath} requires tag and exportName strings.`);
|
|
55
|
+
const attributes = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const [propName, prop] of Object.entries((_component$props = component.props) !== null && _component$props !== void 0 ? _component$props : {})) {
|
|
57
|
+
const attrName = prop.attr === false ? false : typeof prop.attr === "string" ? prop.attr : [
|
|
58
|
+
"string",
|
|
59
|
+
"number",
|
|
60
|
+
"boolean"
|
|
61
|
+
].includes(prop.type) ? propName.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`) : false;
|
|
62
|
+
if (attrName !== false) {
|
|
63
|
+
const previous = attributes.get(attrName);
|
|
64
|
+
if (previous && previous !== propName) throw new Error(`[ZEUS_WC_ATTR_COLLISION] ${componentPath}.props.${propName} and ${previous} both use attribute "${attrName}".`);
|
|
65
|
+
attributes.set(attrName, propName);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const [eventKey, event] of Object.entries((_component$events = component.events) !== null && _component$events !== void 0 ? _component$events : {})) if (event.name !== void 0 && typeof event.name !== "string" || event.reactName !== void 0 && typeof event.reactName !== "string" || event.bubbles !== void 0 && typeof event.bubbles !== "boolean" || event.composed !== void 0 && typeof event.composed !== "boolean" || event.cancelable !== void 0 && typeof event.cancelable !== "boolean") throw new Error(`[ZEUS_WC_EVENT_ABI] ${componentPath}.events.${eventKey} contains invalid names or bubbles/composed/cancelable flags.`);
|
|
69
|
+
for (const [propName, prop] of Object.entries((_component$props2 = component.props) !== null && _component$props2 !== void 0 ? _component$props2 : {})) {
|
|
70
|
+
if (prop.hasDefault !== void 0 && typeof prop.hasDefault !== "boolean") throw new Error(`[ZEUS_WC_INVALID_DEFAULT_META] ${componentPath}.props.${propName}.hasDefault must be boolean.`);
|
|
71
|
+
if (prop.defaultStrategy !== void 0 && prop.defaultStrategy !== "static" && prop.defaultStrategy !== "factory") throw new Error(`[ZEUS_WC_INVALID_DEFAULT_META] ${componentPath}.props.${propName}.defaultStrategy is invalid.`);
|
|
72
|
+
if (prop.defaultStrategy === "factory" && prop.default !== void 0) throw new Error(`[ZEUS_WC_INVALID_DEFAULT_META] ${componentPath}.props.${propName} factory defaults cannot be serialized as values.`);
|
|
73
|
+
if (prop.defaultStrategy === "static" && !Object.prototype.hasOwnProperty.call(prop, "default")) throw new Error(`[ZEUS_WC_INVALID_DEFAULT_META] ${componentPath}.props.${propName} static defaults require a value.`);
|
|
74
|
+
if (Object.prototype.hasOwnProperty.call(prop, "default")) {
|
|
75
|
+
if (prop.default === void 0) throw new Error(`[ZEUS_WC_INVALID_DEFAULT_META] ${componentPath}.props.${propName}.default cannot be undefined.`);
|
|
76
|
+
assertJsonSafe(prop.default, `${componentPath}.props.${propName}.default`, /* @__PURE__ */ new Set(), "ZEUS_WC_INVALID_DEFAULT_META", true);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
assertJsonSafe(manifest, "manifest");
|
|
81
|
+
}
|
|
82
|
+
function assertJsonSafe(value, path, parents = /* @__PURE__ */ new Set(), code = "ZEUS_WC_INVALID_MANIFEST", rejectUndefined = false) {
|
|
83
|
+
if (value === void 0) {
|
|
84
|
+
if (rejectUndefined) throw invalidManifest(path, "undefined values are not supported", code);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (value === null) return;
|
|
88
|
+
if (typeof value === "string" || typeof value === "boolean") return;
|
|
89
|
+
if (typeof value === "number") {
|
|
90
|
+
if (!Number.isFinite(value) || Object.is(value, -0)) throw invalidManifest(path, "numbers must be finite and cannot be -0", code);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") throw invalidManifest(path, "functions, symbols, and bigint values are not supported", code);
|
|
94
|
+
if (typeof value !== "object") throw invalidManifest(path, "value is not JSON-safe", code);
|
|
95
|
+
if (parents.has(value)) throw invalidManifest(path, "cyclic values are not supported", code);
|
|
96
|
+
const prototype = Object.getPrototypeOf(value);
|
|
97
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) throw invalidManifest(path, "only plain objects and arrays are supported", code);
|
|
98
|
+
if (Object.getOwnPropertySymbols(value).length > 0) throw invalidManifest(path, "symbol keys are not supported", code);
|
|
99
|
+
parents.add(value);
|
|
100
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
|
|
101
|
+
if ("get" in descriptor || "set" in descriptor) throw invalidManifest(`${path}.${key}`, "accessor properties are not supported", code);
|
|
102
|
+
if (descriptor.value === void 0 && !rejectUndefined) continue;
|
|
103
|
+
assertJsonSafe(descriptor.value, Array.isArray(value) ? `${path}[${key}]` : `${path}.${key}`, parents, code, rejectUndefined);
|
|
104
|
+
}
|
|
105
|
+
parents.delete(value);
|
|
106
|
+
}
|
|
107
|
+
function invalidManifest(path, reason, code) {
|
|
108
|
+
return /* @__PURE__ */ new Error(`[${code}] ${path}: ${reason}.`);
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
36
111
|
//#region packages/web-c/output-wc/src/generateCustomElementsJson.ts
|
|
37
112
|
function generateCustomElementsJson(options) {
|
|
38
113
|
const { manifest, getModulePath } = options;
|
|
114
|
+
validateComponentManifest(manifest);
|
|
39
115
|
const result = {
|
|
40
116
|
schemaVersion: "1.0.0",
|
|
41
117
|
modules: manifest.components.map((component) => {
|
|
@@ -97,14 +173,24 @@ function generateMembers(component) {
|
|
|
97
173
|
default: prop.default === void 0 ? void 0 : JSON.stringify(prop.default)
|
|
98
174
|
};
|
|
99
175
|
});
|
|
100
|
-
const methods = Object.
|
|
101
|
-
return {
|
|
102
|
-
kind: "method",
|
|
103
|
-
name
|
|
104
|
-
};
|
|
105
|
-
});
|
|
176
|
+
const methods = Object.entries((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {}).map(([name, method]) => generateMethodMember(name, method));
|
|
106
177
|
return [...fields, ...methods];
|
|
107
178
|
}
|
|
179
|
+
function generateMethodMember(name, method) {
|
|
180
|
+
var _method$returns, _method$returns2;
|
|
181
|
+
const member = {
|
|
182
|
+
kind: "method",
|
|
183
|
+
name,
|
|
184
|
+
return: { type: { text: method.async ? `Promise<${(_method$returns = method.returns) !== null && _method$returns !== void 0 ? _method$returns : "unknown"}>` : (_method$returns2 = method.returns) !== null && _method$returns2 !== void 0 ? _method$returns2 : "unknown" } }
|
|
185
|
+
};
|
|
186
|
+
if (method.parameters) member.parameters = method.parameters.map((parameter) => ({
|
|
187
|
+
name: parameter.name,
|
|
188
|
+
type: { text: parameter.type },
|
|
189
|
+
optional: parameter.optional,
|
|
190
|
+
rest: parameter.rest
|
|
191
|
+
}));
|
|
192
|
+
return member;
|
|
193
|
+
}
|
|
108
194
|
function generateEvents(component) {
|
|
109
195
|
return Object.entries(component.events).map(([key, event]) => {
|
|
110
196
|
var _event$name, _event$key;
|
|
@@ -179,6 +265,15 @@ function generateWCEntry(options) {
|
|
|
179
265
|
`import { ${component.exportName} } from ${JSON.stringify(source)};`,
|
|
180
266
|
"",
|
|
181
267
|
`export { ${component.exportName} };`,
|
|
268
|
+
"",
|
|
269
|
+
`export function defineCustomElement(options = {}) {`,
|
|
270
|
+
` const registry = options.registry ?? (typeof customElements === 'undefined' ? undefined : customElements);`,
|
|
271
|
+
` if (!registry) return;`,
|
|
272
|
+
` const existing = registry.get(${JSON.stringify(component.tag)});`,
|
|
273
|
+
` if (existing === ${component.exportName}) return;`,
|
|
274
|
+
` if (existing) throw new Error(${JSON.stringify(`[ZEUS_WC_DUPLICATE_TAG] <${component.tag}> is already registered with a different definition.`)});`,
|
|
275
|
+
` registry.define(${JSON.stringify(component.tag)}, ${component.exportName});`,
|
|
276
|
+
`}`,
|
|
182
277
|
""
|
|
183
278
|
].join("\n");
|
|
184
279
|
}
|
|
@@ -204,16 +299,19 @@ function getVirtualIndexId() {
|
|
|
204
299
|
//#region packages/web-c/output-wc/src/generateLazyEntry.ts
|
|
205
300
|
function generateLazyEntry(options) {
|
|
206
301
|
const { component, outPath, sourceImport } = options;
|
|
207
|
-
const source = sourceImport !== null && sourceImport !== void 0 ? sourceImport : toRelativeImport(component.source, outPath)
|
|
302
|
+
const source = `${sourceImport !== null && sourceImport !== void 0 ? sourceImport : toRelativeImport(component.source, outPath)}?zeus-lazy-component=${component.exportName}`;
|
|
208
303
|
return [
|
|
209
|
-
`import { createCustomElementMountLifecycle, mountElementDefinition } from "@zeus-js/runtime-dom";`,
|
|
304
|
+
`import { createCustomElementMountLifecycle, getElementDefinition, mountElementDefinition } from "@zeus-js/runtime-dom";`,
|
|
305
|
+
`import { resolveHostProperties } from "@zeus-js/web-c-runtime";`,
|
|
210
306
|
`import { ${component.exportName} } from ${JSON.stringify(source)};`,
|
|
211
307
|
"",
|
|
212
308
|
`export function createComponent(hostRef) {`,
|
|
309
|
+
` resolveHostProperties(hostRef, getElementDefinition(${component.exportName}).propDefs);`,
|
|
213
310
|
` const mountState = {`,
|
|
214
311
|
` attributeProps: hostRef.attributeProps,`,
|
|
215
312
|
` internals: hostRef.internals,`,
|
|
216
313
|
` reflectingAttrs: hostRef.reflectingAttrs,`,
|
|
314
|
+
` exposedMethods: hostRef.exposedMethods,`,
|
|
217
315
|
` };`,
|
|
218
316
|
` const lifecycle = createCustomElementMountLifecycle(() =>`,
|
|
219
317
|
` mountElementDefinition(`,
|
|
@@ -233,8 +331,8 @@ function generateLazyEntry(options) {
|
|
|
233
331
|
` lifecycle.disconnect();`,
|
|
234
332
|
` },`,
|
|
235
333
|
"",
|
|
236
|
-
` propertyChanged(
|
|
237
|
-
` lifecycle.current()?.propertyChanged(
|
|
334
|
+
` propertyChanged(change) {`,
|
|
335
|
+
` lifecycle.current()?.propertyChanged(change);`,
|
|
238
336
|
` },`,
|
|
239
337
|
"",
|
|
240
338
|
` formAssociated(form) {`,
|
|
@@ -268,54 +366,6 @@ function toRelativeImport(source, outPath) {
|
|
|
268
366
|
return [...outParts.slice(common).map(() => ".."), ...sourceParts.slice(common)].join("/");
|
|
269
367
|
}
|
|
270
368
|
//#endregion
|
|
271
|
-
//#region packages/web-c/output-wc/src/generateLazyManifest.ts
|
|
272
|
-
function generateLazyManifest(options) {
|
|
273
|
-
const { components, getEntryFileName } = options;
|
|
274
|
-
return `export const components = [
|
|
275
|
-
${components.map((component) => {
|
|
276
|
-
var _component$runtimePro, _component$methods, _component$meta$shado, _component$meta, _component$meta$formA, _component$meta2;
|
|
277
|
-
const entryFile = getEntryFileName(component.tag).replace(/\\/g, "/");
|
|
278
|
-
const props = generatePropsArray((_component$runtimePro = component.runtimeProps) !== null && _component$runtimePro !== void 0 ? _component$runtimePro : component.props);
|
|
279
|
-
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {});
|
|
280
|
-
const importPath = entryFile.startsWith(".") ? JSON.stringify(entryFile) : JSON.stringify(`./${entryFile}`);
|
|
281
|
-
const methodLine = methods.length ? ` methods: ${JSON.stringify(methods)},\n` : "";
|
|
282
|
-
return ` {
|
|
283
|
-
tagName: ${JSON.stringify(component.tag)},
|
|
284
|
-
shadow: ${(_component$meta$shado = (_component$meta = component.meta) === null || _component$meta === void 0 ? void 0 : _component$meta.shadow) !== null && _component$meta$shado !== void 0 ? _component$meta$shado : false},
|
|
285
|
-
formAssociated: ${(_component$meta$formA = (_component$meta2 = component.meta) === null || _component$meta2 === void 0 ? void 0 : _component$meta2.formAssociated) !== null && _component$meta$formA !== void 0 ? _component$meta$formA : false},
|
|
286
|
-
load: () => import(${importPath}),
|
|
287
|
-
props: ${props},
|
|
288
|
-
${methodLine}
|
|
289
|
-
}`;
|
|
290
|
-
}).join(",\n")}
|
|
291
|
-
];
|
|
292
|
-
`;
|
|
293
|
-
}
|
|
294
|
-
function generatePropsArray(props) {
|
|
295
|
-
const entries = Object.entries(props);
|
|
296
|
-
if (entries.length === 0) return "[]";
|
|
297
|
-
return `[\n${entries.map(([name, prop]) => {
|
|
298
|
-
const parts = [`name: ${JSON.stringify(name)}`];
|
|
299
|
-
if (!isAttributeBackedType(prop.type) && !prop.deserialize || prop.attr === false) parts.push("attrName: false");
|
|
300
|
-
else {
|
|
301
|
-
var _prop$attr;
|
|
302
|
-
const attrName = (_prop$attr = prop.attr) !== null && _prop$attr !== void 0 ? _prop$attr : toKebabCase(name);
|
|
303
|
-
if (attrName !== toKebabCase(name)) parts.push(`attrName: ${JSON.stringify(attrName)}`);
|
|
304
|
-
}
|
|
305
|
-
parts.push(`type: ${JSON.stringify(prop.type)}`);
|
|
306
|
-
if (prop.reflect && (isAttributeBackedType(prop.type) || Boolean(prop.serialize))) parts.push("reflect: true");
|
|
307
|
-
if (prop.serialize) parts.push("serialize: true");
|
|
308
|
-
if (prop.deserialize) parts.push("deserialize: true");
|
|
309
|
-
return ` { ${parts.join(", ")} }`;
|
|
310
|
-
}).join(",\n")}\n ]`;
|
|
311
|
-
}
|
|
312
|
-
function isAttributeBackedType(type) {
|
|
313
|
-
return type === "string" || type === "number" || type === "boolean";
|
|
314
|
-
}
|
|
315
|
-
function toKebabCase(value) {
|
|
316
|
-
return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
317
|
-
}
|
|
318
|
-
//#endregion
|
|
319
369
|
//#region packages/web-c/output-wc/src/generateLoader.ts
|
|
320
370
|
function generateLoader() {
|
|
321
371
|
return `import { bootstrapLazy } from "@zeus-js/web-c-runtime";
|
|
@@ -325,24 +375,11 @@ const componentsByTagName = new Map(
|
|
|
325
375
|
components.map(component => [component.tagName, component]),
|
|
326
376
|
);
|
|
327
377
|
|
|
328
|
-
const definedTagsByRegistry = new WeakMap();
|
|
329
|
-
|
|
330
378
|
function resolveRegistry(options) {
|
|
331
379
|
return options.registry ??
|
|
332
380
|
(typeof customElements === "undefined" ? undefined : customElements);
|
|
333
381
|
}
|
|
334
382
|
|
|
335
|
-
function getDefinedTags(registry) {
|
|
336
|
-
let definedTags = definedTagsByRegistry.get(registry);
|
|
337
|
-
|
|
338
|
-
if (!definedTags) {
|
|
339
|
-
definedTags = new Set();
|
|
340
|
-
definedTagsByRegistry.set(registry, definedTags);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return definedTags;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
383
|
export function defineCustomElement(tagName, options = {}) {
|
|
347
384
|
const registry = resolveRegistry(options);
|
|
348
385
|
|
|
@@ -356,16 +393,7 @@ export function defineCustomElement(tagName, options = {}) {
|
|
|
356
393
|
throw new Error(\`[zeus:web-c] Unknown custom element: <\${tagName}>.\`);
|
|
357
394
|
}
|
|
358
395
|
|
|
359
|
-
const definedTags = getDefinedTags(registry);
|
|
360
|
-
|
|
361
|
-
if (definedTags.has(tagName) || registry.get(tagName)) {
|
|
362
|
-
definedTags.add(tagName);
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
396
|
bootstrapLazy([component], { registry });
|
|
367
|
-
|
|
368
|
-
definedTags.add(tagName);
|
|
369
397
|
}
|
|
370
398
|
|
|
371
399
|
export function defineCustomElements(options = {}) {
|
|
@@ -374,8 +402,6 @@ export function defineCustomElements(options = {}) {
|
|
|
374
402
|
}
|
|
375
403
|
}
|
|
376
404
|
|
|
377
|
-
export const defineLazyElement = defineCustomElement;
|
|
378
|
-
export const defineLazyElements = defineCustomElements;
|
|
379
405
|
`;
|
|
380
406
|
}
|
|
381
407
|
function generateAutoEntry() {
|
|
@@ -390,18 +416,149 @@ function generateLazyIndex() {
|
|
|
390
416
|
return `export {
|
|
391
417
|
defineCustomElement,
|
|
392
418
|
defineCustomElements,
|
|
393
|
-
defineLazyElement,
|
|
394
|
-
defineLazyElements,
|
|
395
419
|
} from "./loader.js";
|
|
396
420
|
`;
|
|
397
421
|
}
|
|
398
422
|
//#endregion
|
|
399
|
-
//#region packages/web-c/output-wc/src/
|
|
400
|
-
function
|
|
401
|
-
|
|
423
|
+
//#region packages/web-c/output-wc/src/generateLazyManifest.ts
|
|
424
|
+
function generateLazyManifest(options) {
|
|
425
|
+
const { components, getEntryFileName } = options;
|
|
426
|
+
return `export const components = [
|
|
427
|
+
${components.map((component) => {
|
|
428
|
+
var _component$runtimePro, _component$methods, _component$meta$shado, _component$meta, _component$meta$formA, _component$meta2;
|
|
429
|
+
const entryFile = getEntryFileName(component.tag).replace(/\\/g, "/");
|
|
430
|
+
const props = generatePropsArray((_component$runtimePro = component.runtimeProps) !== null && _component$runtimePro !== void 0 ? _component$runtimePro : component.props);
|
|
431
|
+
const methods = Object.keys((_component$methods = component.methods) !== null && _component$methods !== void 0 ? _component$methods : {});
|
|
432
|
+
const importPath = entryFile.startsWith(".") ? JSON.stringify(entryFile) : JSON.stringify(`./${entryFile}`);
|
|
433
|
+
const methodLine = methods.length ? ` methods: ${JSON.stringify(methods)},\n` : "";
|
|
434
|
+
return ` {
|
|
435
|
+
tagName: ${JSON.stringify(component.tag)},
|
|
436
|
+
shadow: ${(_component$meta$shado = (_component$meta = component.meta) === null || _component$meta === void 0 ? void 0 : _component$meta.shadow) !== null && _component$meta$shado !== void 0 ? _component$meta$shado : false},
|
|
437
|
+
formAssociated: ${(_component$meta$formA = (_component$meta2 = component.meta) === null || _component$meta2 === void 0 ? void 0 : _component$meta2.formAssociated) !== null && _component$meta$formA !== void 0 ? _component$meta$formA : false},
|
|
438
|
+
load: () => import(${importPath}),
|
|
439
|
+
props: ${props},
|
|
440
|
+
${methodLine}
|
|
441
|
+
}`;
|
|
442
|
+
}).join(",\n")}
|
|
443
|
+
];
|
|
444
|
+
`;
|
|
445
|
+
}
|
|
446
|
+
function generatePropsArray(props) {
|
|
447
|
+
const entries = Object.entries(props);
|
|
448
|
+
if (entries.length === 0) return "[]";
|
|
449
|
+
return `[\n${entries.map(([name, prop]) => {
|
|
450
|
+
const parts = [`name: ${JSON.stringify(name)}`];
|
|
451
|
+
if (!isAttributeBackedType(prop.type) && !prop.deserialize || prop.attr === false) parts.push("attrName: false");
|
|
452
|
+
else {
|
|
453
|
+
var _prop$attr;
|
|
454
|
+
const attrName = (_prop$attr = prop.attr) !== null && _prop$attr !== void 0 ? _prop$attr : toKebabCase(name);
|
|
455
|
+
if (attrName !== toKebabCase(name)) parts.push(`attrName: ${JSON.stringify(attrName)}`);
|
|
456
|
+
}
|
|
457
|
+
parts.push(`type: ${JSON.stringify(prop.type)}`);
|
|
458
|
+
if (isJsonSafeDefault(prop.default)) {
|
|
459
|
+
const encoded = JSON.stringify(prop.default);
|
|
460
|
+
parts.push(`default: ${typeof prop.default === "object" && prop.default !== null ? `JSON.parse(${JSON.stringify(encoded)})` : encoded}`);
|
|
461
|
+
}
|
|
462
|
+
if (prop.reflect && (isAttributeBackedType(prop.type) || Boolean(prop.serialize))) parts.push("reflect: true");
|
|
463
|
+
if (prop.serialize) parts.push("serialize: true");
|
|
464
|
+
if (prop.deserialize) parts.push("deserialize: true");
|
|
465
|
+
return ` { ${parts.join(", ")} }`;
|
|
466
|
+
}).join(",\n")}\n ]`;
|
|
467
|
+
}
|
|
468
|
+
function isJsonSafeDefault(value, parents = /* @__PURE__ */ new Set()) {
|
|
469
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
470
|
+
if (typeof value === "number") return Number.isFinite(value) && !Object.is(value, -0);
|
|
471
|
+
if (typeof value !== "object" || parents.has(value)) return false;
|
|
472
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) return false;
|
|
473
|
+
if (Object.getOwnPropertySymbols(value).length) return false;
|
|
474
|
+
parents.add(value);
|
|
475
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
476
|
+
const valid = Array.isArray(value) ? Array.from({ length: value.length }, (_, index) => descriptors[index]).every((descriptor) => descriptor && "value" in descriptor && isJsonSafeDefault(descriptor.value, parents)) : Object.values(descriptors).every((descriptor) => "value" in descriptor && isJsonSafeDefault(descriptor.value, parents));
|
|
477
|
+
parents.delete(value);
|
|
478
|
+
return valid;
|
|
479
|
+
}
|
|
480
|
+
function isAttributeBackedType(type) {
|
|
481
|
+
return type === "string" || type === "number" || type === "boolean";
|
|
482
|
+
}
|
|
483
|
+
function toKebabCase(value) {
|
|
484
|
+
return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region packages/web-c/output-wc/src/generateRegistration.ts
|
|
488
|
+
function generateLazyRegistration(component, entryFileName) {
|
|
489
|
+
return `import { bootstrapLazy } from "@zeus-js/web-c-runtime";
|
|
490
|
+
${generateLazyManifest({
|
|
491
|
+
components: [component],
|
|
492
|
+
getEntryFileName: () => entryFileName
|
|
493
|
+
})}
|
|
494
|
+
export const component = components[0];
|
|
495
|
+
|
|
496
|
+
export function defineCustomElement(options = {}) {
|
|
497
|
+
bootstrapLazy([component], options);
|
|
498
|
+
}
|
|
499
|
+
`;
|
|
500
|
+
}
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region packages/web-c/output-wc/src/generateVSCodeCustomData.ts
|
|
503
|
+
function generateVSCodeCustomData(customElementsJson) {
|
|
504
|
+
let manifest;
|
|
505
|
+
try {
|
|
506
|
+
manifest = JSON.parse(customElementsJson);
|
|
507
|
+
} catch {
|
|
508
|
+
throw new Error("[ZEUS_VSCODE_CUSTOM_DATA_INVALID] CEM input is not valid JSON.");
|
|
509
|
+
}
|
|
510
|
+
if ((manifest === null || manifest === void 0 ? void 0 : manifest.schemaVersion) !== "1.0.0" || !Array.isArray(manifest.modules)) throw new Error("[ZEUS_VSCODE_CUSTOM_DATA_INVALID] CEM input must use schemaVersion 1.0.0 and contain modules.");
|
|
511
|
+
const tags = manifest.modules.flatMap((module) => {
|
|
512
|
+
var _module$declarations;
|
|
513
|
+
return ((_module$declarations = module.declarations) !== null && _module$declarations !== void 0 ? _module$declarations : []).filter((declaration) => declaration.kind === "class" && declaration.customElement === true && typeof declaration.tagName === "string").map((declaration) => {
|
|
514
|
+
var _declaration$attribut;
|
|
515
|
+
const tagName = declaration.tagName;
|
|
516
|
+
const attributes = ((_declaration$attribut = declaration.attributes) !== null && _declaration$attribut !== void 0 ? _declaration$attribut : []).map((attribute) => {
|
|
517
|
+
var _attribute$type;
|
|
518
|
+
if (typeof attribute.name !== "string") throw new Error(`[ZEUS_VSCODE_CUSTOM_DATA_INVALID] <${tagName}> contains an attribute without a name.`);
|
|
519
|
+
const values = parseStringLiteralUnion((_attribute$type = attribute.type) === null || _attribute$type === void 0 ? void 0 : _attribute$type.text);
|
|
520
|
+
return {
|
|
521
|
+
name: attribute.name,
|
|
522
|
+
...attribute.description ? { description: attribute.description } : {},
|
|
523
|
+
...values ? { values: values.map((name) => ({ name })) } : {}
|
|
524
|
+
};
|
|
525
|
+
});
|
|
526
|
+
return {
|
|
527
|
+
name: tagName,
|
|
528
|
+
...declaration.description ? { description: declaration.description } : {},
|
|
529
|
+
...attributes.length > 0 ? { attributes } : {}
|
|
530
|
+
};
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
const names = /* @__PURE__ */ new Set();
|
|
534
|
+
for (const tag of tags) {
|
|
535
|
+
if (names.has(tag.name)) throw new Error(`[ZEUS_VSCODE_CUSTOM_DATA_INVALID] CEM declares <${tag.name}> more than once.`);
|
|
536
|
+
names.add(tag.name);
|
|
537
|
+
}
|
|
538
|
+
return `${JSON.stringify({
|
|
539
|
+
version: 1.1,
|
|
540
|
+
tags
|
|
541
|
+
}, null, 2)}\n`;
|
|
542
|
+
}
|
|
543
|
+
function parseStringLiteralUnion(typeText) {
|
|
544
|
+
if (!typeText) return void 0;
|
|
545
|
+
const parts = typeText.split(/\s+\|\s+/);
|
|
546
|
+
const values = [];
|
|
547
|
+
for (const part of parts) {
|
|
548
|
+
if (!part.startsWith("\"") || !part.endsWith("\"")) return void 0;
|
|
549
|
+
try {
|
|
550
|
+
const value = JSON.parse(part);
|
|
551
|
+
if (typeof value !== "string") return void 0;
|
|
552
|
+
values.push(value);
|
|
553
|
+
} catch {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return values.length > 0 ? values : void 0;
|
|
402
558
|
}
|
|
403
559
|
//#endregion
|
|
404
560
|
//#region packages/web-c/output-wc/src/index.ts
|
|
561
|
+
const outputWcModulePath = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
|
|
405
562
|
function wc(options = {}) {
|
|
406
563
|
var _options$register, _options$outDir, _options$stripPrefix, _options$manifestFile, _options$customElemen, _options$dts, _options$jsxDts, _options$index, _options$warnOnFileNa, _options$auto, _options$entryFileNam;
|
|
407
564
|
const registerMode = (_options$register = options.register) !== null && _options$register !== void 0 ? _options$register : "lazy";
|
|
@@ -476,15 +633,13 @@ function wc(options = {}) {
|
|
|
476
633
|
modules.push({
|
|
477
634
|
id: "zeus:wc:components.manifest",
|
|
478
635
|
fileName: joinPath("components.manifest.js"),
|
|
479
|
-
code:
|
|
480
|
-
components: ctx.manifest.components,
|
|
481
|
-
getEntryFileName: (tag) => getLazyEntryFileName(normalized.entryFileName, tag)
|
|
482
|
-
})
|
|
636
|
+
code: [...ctx.manifest.components.map((component, index) => `import { component as c${index} } from ${JSON.stringify(getVirtualComponentId(component))};`), `export const components = [${ctx.manifest.components.map((_, index) => `c${index}`).join(", ")}];`].join("\n")
|
|
483
637
|
});
|
|
484
638
|
modules.push({
|
|
485
639
|
id: "zeus:wc:loader",
|
|
486
640
|
fileName: joinPath("loader.js"),
|
|
487
|
-
code: generateLoader()
|
|
641
|
+
code: generateLoader(),
|
|
642
|
+
resolveFrom: outputWcModulePath
|
|
488
643
|
});
|
|
489
644
|
if (normalized.auto) modules.push({
|
|
490
645
|
id: "zeus:wc:auto",
|
|
@@ -501,13 +656,9 @@ function wc(options = {}) {
|
|
|
501
656
|
*/
|
|
502
657
|
modules.push({
|
|
503
658
|
id: getVirtualComponentId(component),
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
defineCustomElements();
|
|
508
|
-
|
|
509
|
-
export {};
|
|
510
|
-
`.trimStart()
|
|
659
|
+
fileName: joinPath(getFileName(component.tag)),
|
|
660
|
+
code: generateLazyRegistration(component, node_path.default.posix.relative(node_path.default.posix.dirname(joinPath(getFileName(component.tag))), joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag)))),
|
|
661
|
+
resolveFrom: outputWcModulePath
|
|
511
662
|
});
|
|
512
663
|
const fileName = joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag));
|
|
513
664
|
modules.push({
|
|
@@ -517,7 +668,8 @@ export {};
|
|
|
517
668
|
component,
|
|
518
669
|
outPath: fileName,
|
|
519
670
|
sourceImport: toAbsoluteImportPath(ctx.root, component.source)
|
|
520
|
-
})
|
|
671
|
+
}),
|
|
672
|
+
resolveFrom: outputWcModulePath
|
|
521
673
|
});
|
|
522
674
|
} else {
|
|
523
675
|
const fileName = joinPath(getFileName(component.tag));
|
|
@@ -568,6 +720,11 @@ export {};
|
|
|
568
720
|
fileName: joinPath("loader.d.ts"),
|
|
569
721
|
source: loaderDts
|
|
570
722
|
});
|
|
723
|
+
for (const component of ctx.manifest.components) files.push({
|
|
724
|
+
type: "asset",
|
|
725
|
+
fileName: joinPath(getFileName(component.tag).replace(/\.js$/, ".d.ts")),
|
|
726
|
+
source: "export declare function defineCustomElement(options?: { registry?: CustomElementRegistry }): void\n"
|
|
727
|
+
});
|
|
571
728
|
if (normalized.index) files.push({
|
|
572
729
|
type: "asset",
|
|
573
730
|
fileName: joinPath("index.d.ts"),
|
|
@@ -585,14 +742,22 @@ export {};
|
|
|
585
742
|
fileName: normalized.manifestFile,
|
|
586
743
|
source: generateZeusComponentsManifest(ctx.manifest)
|
|
587
744
|
});
|
|
588
|
-
if (normalized.customElementsFile)
|
|
589
|
-
|
|
590
|
-
fileName: normalized.customElementsFile,
|
|
591
|
-
source: generateCustomElementsJson({
|
|
745
|
+
if (normalized.customElementsFile) {
|
|
746
|
+
const customElementsJson = generateCustomElementsJson({
|
|
592
747
|
manifest: ctx.manifest,
|
|
593
748
|
getModulePath: (component) => isLazy ? joinPath(getLazyEntryFileName(normalized.entryFileName, component.tag)) : joinPath(getFileName(component.tag))
|
|
594
|
-
})
|
|
595
|
-
|
|
749
|
+
});
|
|
750
|
+
files.push({
|
|
751
|
+
type: "asset",
|
|
752
|
+
fileName: normalized.customElementsFile,
|
|
753
|
+
source: customElementsJson
|
|
754
|
+
});
|
|
755
|
+
files.push({
|
|
756
|
+
type: "asset",
|
|
757
|
+
fileName: "vscode.html-custom-data.json",
|
|
758
|
+
source: generateVSCodeCustomData(customElementsJson)
|
|
759
|
+
});
|
|
760
|
+
}
|
|
596
761
|
if (!isLazy && (dts || jsxDts)) {
|
|
597
762
|
const dtsFiles = (0, _zeus_js_component_dts.generateWCDtsFiles)(ctx.manifest, {
|
|
598
763
|
outDir: _outDir,
|