@zeus-js/component-dts 0.1.0-beta.0
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/component-dts.cjs.js +373 -0
- package/dist/component-dts.cjs.prod.js +373 -0
- package/dist/component-dts.d.ts +63 -0
- package/dist/component-dts.esm-bundler.js +337 -0
- package/index.js +2 -0
- package/package.json +49 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* component-dts v0.1.0-beta.0
|
|
3
|
+
* (c) 2026 baicie
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
**/
|
|
6
|
+
Object.defineProperties(exports, {
|
|
7
|
+
__esModule: { value: true },
|
|
8
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
9
|
+
});
|
|
10
|
+
//#region \0rolldown/runtime.js
|
|
11
|
+
var __create = Object.create;
|
|
12
|
+
var __defProp = Object.defineProperty;
|
|
13
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
+
key = keys[i];
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
+
get: ((k) => from[k]).bind(null, key),
|
|
22
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
//#endregion
|
|
32
|
+
let node_path = require("node:path");
|
|
33
|
+
node_path = __toESM(node_path, 1);
|
|
34
|
+
//#region packages/web-c/component-dts/src/formatType.ts
|
|
35
|
+
function formatPropType(prop) {
|
|
36
|
+
var _prop$values;
|
|
37
|
+
if ((_prop$values = prop.values) === null || _prop$values === void 0 ? void 0 : _prop$values.length) return prop.values.map((value) => JSON.stringify(value)).join(" | ");
|
|
38
|
+
switch (prop.type) {
|
|
39
|
+
case "string": return "string";
|
|
40
|
+
case "number": return "number";
|
|
41
|
+
case "boolean": return "boolean";
|
|
42
|
+
case "array": return "unknown[]";
|
|
43
|
+
case "object": return "Record<string, unknown>";
|
|
44
|
+
default: return "unknown";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function formatEventType(event) {
|
|
48
|
+
if (!event.detail) return "CustomEvent<unknown>";
|
|
49
|
+
return `CustomEvent<${formatDetailType(event.detail)}>`;
|
|
50
|
+
}
|
|
51
|
+
function formatDetailType(detail) {
|
|
52
|
+
return `{ ${Object.entries(detail).map(([name, type]) => `${safePropertyName(name)}: ${normalizeKnownType(type)}`).join("; ")} }`;
|
|
53
|
+
}
|
|
54
|
+
function normalizeKnownType(type) {
|
|
55
|
+
switch (type) {
|
|
56
|
+
case "string":
|
|
57
|
+
case "number":
|
|
58
|
+
case "boolean":
|
|
59
|
+
case "unknown":
|
|
60
|
+
case "MouseEvent":
|
|
61
|
+
case "KeyboardEvent":
|
|
62
|
+
case "PointerEvent":
|
|
63
|
+
case "FocusEvent":
|
|
64
|
+
case "InputEvent":
|
|
65
|
+
case "Event": return type;
|
|
66
|
+
case "object": return "Record<string, unknown>";
|
|
67
|
+
case "array": return "unknown[]";
|
|
68
|
+
default: return type || "unknown";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function safePropertyName(name) {
|
|
72
|
+
if (/^[A-Za-z\_$][A-Za-z0-9_$]*$/.test(name)) return name;
|
|
73
|
+
return JSON.stringify(name);
|
|
74
|
+
}
|
|
75
|
+
function isRequiredProp(prop) {
|
|
76
|
+
if (prop.default !== void 0) return false;
|
|
77
|
+
return prop.required === true;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region packages/web-c/component-dts/src/naming.ts
|
|
81
|
+
function getElementTypeName(component) {
|
|
82
|
+
if (component.name.endsWith("Element")) return component.name;
|
|
83
|
+
return `${component.name}Element`;
|
|
84
|
+
}
|
|
85
|
+
function getEventMapTypeName(component) {
|
|
86
|
+
return `${component.name}EventMap`;
|
|
87
|
+
}
|
|
88
|
+
function getPropsTypeName(component) {
|
|
89
|
+
return `${component.name}Props`;
|
|
90
|
+
}
|
|
91
|
+
function getComponentFileBaseName(tag, options) {
|
|
92
|
+
if (options.fileName) return sanitizeFileName(options.fileName(tag)).replace(/\.d\.ts$/, "");
|
|
93
|
+
let name = tag;
|
|
94
|
+
if (options.stripPrefix && name.startsWith(options.stripPrefix)) name = name.slice(options.stripPrefix.length);
|
|
95
|
+
return sanitizeFileName(name);
|
|
96
|
+
}
|
|
97
|
+
function getComponentDtsFileName(tag, options) {
|
|
98
|
+
return `${getComponentFileBaseName(tag, options)}.d.ts`;
|
|
99
|
+
}
|
|
100
|
+
function sanitizeFileName(value) {
|
|
101
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region packages/web-c/component-dts/src/generateWcDts.ts
|
|
105
|
+
function generateComponentWCDts(component) {
|
|
106
|
+
const elementTypeName = getElementTypeName(component);
|
|
107
|
+
const lines = [];
|
|
108
|
+
lines.push("/* eslint-disable */");
|
|
109
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
110
|
+
lines.push("");
|
|
111
|
+
lines.push(generateEventMap(component));
|
|
112
|
+
lines.push("");
|
|
113
|
+
lines.push(generateElementInterface(component));
|
|
114
|
+
lines.push("");
|
|
115
|
+
lines.push(`export declare const ${component.exportName}: {`);
|
|
116
|
+
lines.push(` new (): ${elementTypeName}`);
|
|
117
|
+
lines.push("}");
|
|
118
|
+
lines.push("");
|
|
119
|
+
return lines.join("\n");
|
|
120
|
+
}
|
|
121
|
+
function generateWCIndexDts(manifest, options) {
|
|
122
|
+
const lines = [];
|
|
123
|
+
lines.push("/* eslint-disable */");
|
|
124
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
125
|
+
lines.push("");
|
|
126
|
+
for (const component of manifest.components) lines.push(`import type { ${getElementTypeName(component)} } from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
127
|
+
for (const component of manifest.components) lines.push(`export * from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
128
|
+
lines.push("");
|
|
129
|
+
lines.push("declare global {");
|
|
130
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
131
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getElementTypeName(component)}`);
|
|
132
|
+
lines.push(" }");
|
|
133
|
+
lines.push("}");
|
|
134
|
+
lines.push("");
|
|
135
|
+
lines.push("export {}");
|
|
136
|
+
lines.push("");
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
139
|
+
function generateEventMap(component) {
|
|
140
|
+
const eventMapName = getEventMapTypeName(component);
|
|
141
|
+
const entries = Object.entries(component.events);
|
|
142
|
+
const lines = [];
|
|
143
|
+
lines.push(`export interface ${eventMapName} {`);
|
|
144
|
+
if (!entries.length) lines.push(" [key: string]: CustomEvent<unknown>");
|
|
145
|
+
else for (const [name, event] of entries) lines.push(` ${safePropertyName(name)}: ${formatEventType(event)}`);
|
|
146
|
+
lines.push("}");
|
|
147
|
+
return lines.join("\n");
|
|
148
|
+
}
|
|
149
|
+
function generateElementInterface(component) {
|
|
150
|
+
const elementTypeName = getElementTypeName(component);
|
|
151
|
+
const eventMapName = getEventMapTypeName(component);
|
|
152
|
+
const lines = [];
|
|
153
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
154
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
155
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
156
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
157
|
+
}
|
|
158
|
+
lines.push("");
|
|
159
|
+
lines.push(` addEventListener<K extends keyof ${eventMapName}>(`);
|
|
160
|
+
lines.push(" type: K,");
|
|
161
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
162
|
+
lines.push(" options?: boolean | AddEventListenerOptions,");
|
|
163
|
+
lines.push(" ): void");
|
|
164
|
+
lines.push("");
|
|
165
|
+
lines.push(` removeEventListener<K extends keyof ${eventMapName}>(`);
|
|
166
|
+
lines.push(" type: K,");
|
|
167
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
168
|
+
lines.push(" options?: boolean | EventListenerOptions,");
|
|
169
|
+
lines.push(" ): void");
|
|
170
|
+
lines.push("}");
|
|
171
|
+
return lines.join("\n");
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region packages/web-c/component-dts/src/generateJsxDts.ts
|
|
175
|
+
function generateWCJsxDts(manifest) {
|
|
176
|
+
const lines = [];
|
|
177
|
+
lines.push("/* eslint-disable */");
|
|
178
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
179
|
+
lines.push("");
|
|
180
|
+
for (const component of manifest.components) {
|
|
181
|
+
lines.push(generateComponentJsxProps(component));
|
|
182
|
+
lines.push("");
|
|
183
|
+
}
|
|
184
|
+
lines.push("declare global {");
|
|
185
|
+
lines.push(" namespace JSX {");
|
|
186
|
+
lines.push(" interface IntrinsicElements {");
|
|
187
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getPropsTypeName(component)}`);
|
|
188
|
+
lines.push(" }");
|
|
189
|
+
lines.push(" }");
|
|
190
|
+
lines.push("}");
|
|
191
|
+
lines.push("");
|
|
192
|
+
lines.push("export {}");
|
|
193
|
+
lines.push("");
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
function generateComponentJsxProps(component) {
|
|
197
|
+
const propsTypeName = getPropsTypeName(component);
|
|
198
|
+
const lines = [];
|
|
199
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
200
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
201
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
202
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
203
|
+
}
|
|
204
|
+
lines.push("");
|
|
205
|
+
lines.push(" children?: unknown");
|
|
206
|
+
lines.push(" class?: string");
|
|
207
|
+
lines.push(" className?: string");
|
|
208
|
+
lines.push(" style?: string | Record<string, string | number | null | undefined>");
|
|
209
|
+
lines.push(" id?: string");
|
|
210
|
+
lines.push(" role?: string");
|
|
211
|
+
lines.push(" part?: string");
|
|
212
|
+
lines.push(" slot?: string");
|
|
213
|
+
lines.push("");
|
|
214
|
+
lines.push(" [key: `data-${string}`]: unknown");
|
|
215
|
+
lines.push(" [key: `aria-${string}`]: unknown");
|
|
216
|
+
lines.push("}");
|
|
217
|
+
return lines.join("\n");
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region packages/web-c/component-dts/src/generateReactDts.ts
|
|
221
|
+
function generateReactDts(manifest) {
|
|
222
|
+
const lines = [];
|
|
223
|
+
lines.push("/* eslint-disable */");
|
|
224
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
225
|
+
lines.push("");
|
|
226
|
+
lines.push(`import type * as React from 'react'`);
|
|
227
|
+
lines.push("");
|
|
228
|
+
for (const component of manifest.components) {
|
|
229
|
+
lines.push(generateReactComponentDts(component));
|
|
230
|
+
lines.push("");
|
|
231
|
+
}
|
|
232
|
+
return lines.join("\n");
|
|
233
|
+
}
|
|
234
|
+
function generateReactComponentDts(component) {
|
|
235
|
+
const propsTypeName = getPropsTypeName(component);
|
|
236
|
+
const elementTypeName = getElementTypeName(component);
|
|
237
|
+
const lines = [];
|
|
238
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
239
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
240
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
241
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
242
|
+
}
|
|
243
|
+
lines.push("");
|
|
244
|
+
lines.push(" children?: React.ReactNode");
|
|
245
|
+
lines.push(" className?: string");
|
|
246
|
+
lines.push(" style?: React.CSSProperties");
|
|
247
|
+
for (const [name, event] of Object.entries(component.events)) {
|
|
248
|
+
const propName = toReactEventProp(name);
|
|
249
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
250
|
+
lines.push(` ${propName}?: (event: CustomEvent<${detailType}>) => void`);
|
|
251
|
+
}
|
|
252
|
+
lines.push("}");
|
|
253
|
+
lines.push("");
|
|
254
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
255
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
256
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
257
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
258
|
+
}
|
|
259
|
+
lines.push("}");
|
|
260
|
+
lines.push("");
|
|
261
|
+
lines.push(`export declare const ${component.name}: React.ForwardRefExoticComponent<`);
|
|
262
|
+
lines.push(` ${propsTypeName} & React.RefAttributes<${elementTypeName}>`);
|
|
263
|
+
lines.push(">");
|
|
264
|
+
return lines.join("\n");
|
|
265
|
+
}
|
|
266
|
+
function toReactEventProp(eventName) {
|
|
267
|
+
return "on" + eventName.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
268
|
+
}
|
|
269
|
+
//#endregion
|
|
270
|
+
//#region packages/web-c/component-dts/src/generateVueDts.ts
|
|
271
|
+
function generateVueDts(manifest) {
|
|
272
|
+
const lines = [];
|
|
273
|
+
lines.push("/* eslint-disable */");
|
|
274
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
275
|
+
lines.push("");
|
|
276
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
277
|
+
lines.push("");
|
|
278
|
+
for (const component of manifest.components) {
|
|
279
|
+
lines.push(generateVueComponentDts(component));
|
|
280
|
+
lines.push("");
|
|
281
|
+
}
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
function generateVueGlobalDts(manifest) {
|
|
285
|
+
const lines = [];
|
|
286
|
+
lines.push("/* eslint-disable */");
|
|
287
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
288
|
+
lines.push("");
|
|
289
|
+
lines.push(`import type {`);
|
|
290
|
+
for (const component of manifest.components) lines.push(` ${component.name},`);
|
|
291
|
+
lines.push(`} from './index'`);
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push(`declare module 'vue' {`);
|
|
294
|
+
lines.push(" export interface GlobalComponents {");
|
|
295
|
+
for (const component of manifest.components) lines.push(` ${component.name}: typeof ${component.name}`);
|
|
296
|
+
lines.push(" }");
|
|
297
|
+
lines.push("}");
|
|
298
|
+
lines.push("");
|
|
299
|
+
lines.push("export {}");
|
|
300
|
+
lines.push("");
|
|
301
|
+
return lines.join("\n");
|
|
302
|
+
}
|
|
303
|
+
function generateVueComponentDts(component) {
|
|
304
|
+
const propsTypeName = getPropsTypeName(component);
|
|
305
|
+
const lines = [];
|
|
306
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
307
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
308
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
309
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
310
|
+
}
|
|
311
|
+
lines.push("}");
|
|
312
|
+
lines.push("");
|
|
313
|
+
lines.push(`export declare const ${component.name}: DefineComponent<`);
|
|
314
|
+
lines.push(` ${propsTypeName},`);
|
|
315
|
+
lines.push(" {},");
|
|
316
|
+
lines.push(" {},");
|
|
317
|
+
lines.push(" {},");
|
|
318
|
+
lines.push(" {},");
|
|
319
|
+
lines.push(" {},");
|
|
320
|
+
lines.push(" {},");
|
|
321
|
+
lines.push(` ${generateVueEmitsType(component)}`);
|
|
322
|
+
lines.push(">");
|
|
323
|
+
return lines.join("\n");
|
|
324
|
+
}
|
|
325
|
+
function generateVueEmitsType(component) {
|
|
326
|
+
const entries = Object.entries(component.events);
|
|
327
|
+
if (!entries.length) return "{}";
|
|
328
|
+
return `{ ${entries.map(([name, event]) => {
|
|
329
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
330
|
+
return `${JSON.stringify(name)}: (event: CustomEvent<${detailType}>) => void`;
|
|
331
|
+
}).join("; ")} }`;
|
|
332
|
+
}
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region packages/web-c/component-dts/src/generateFiles.ts
|
|
335
|
+
function generateWCDtsFiles(manifest, options = {}) {
|
|
336
|
+
const normalized = normalizeOptions(options);
|
|
337
|
+
const files = [];
|
|
338
|
+
if (normalized.perComponent) for (const component of manifest.components) files.push({
|
|
339
|
+
fileName: node_path.default.posix.join(normalized.outDir, getComponentDtsFileName(component.tag, normalized)),
|
|
340
|
+
source: generateComponentWCDts(component)
|
|
341
|
+
});
|
|
342
|
+
if (normalized.index) files.push({
|
|
343
|
+
fileName: node_path.default.posix.join(normalized.outDir, "index.d.ts"),
|
|
344
|
+
source: generateWCIndexDts(manifest, { getComponentImportPath: (component) => `./${getComponentFileBaseName(component.tag, normalized)}` })
|
|
345
|
+
});
|
|
346
|
+
if (normalized.jsx) files.push({
|
|
347
|
+
fileName: node_path.default.posix.join(normalized.outDir, "jsx.d.ts"),
|
|
348
|
+
source: generateWCJsxDts(manifest)
|
|
349
|
+
});
|
|
350
|
+
return files;
|
|
351
|
+
}
|
|
352
|
+
function normalizeOptions(options) {
|
|
353
|
+
var _options$outDir, _options$stripPrefix, _options$perComponent, _options$index, _options$jsx;
|
|
354
|
+
return {
|
|
355
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
356
|
+
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
357
|
+
fileName: options.fileName,
|
|
358
|
+
perComponent: (_options$perComponent = options.perComponent) !== null && _options$perComponent !== void 0 ? _options$perComponent : true,
|
|
359
|
+
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
360
|
+
jsx: (_options$jsx = options.jsx) !== null && _options$jsx !== void 0 ? _options$jsx : true
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
//#endregion
|
|
364
|
+
exports.formatDetailType = formatDetailType;
|
|
365
|
+
exports.formatEventType = formatEventType;
|
|
366
|
+
exports.formatPropType = formatPropType;
|
|
367
|
+
exports.generateComponentWCDts = generateComponentWCDts;
|
|
368
|
+
exports.generateReactDts = generateReactDts;
|
|
369
|
+
exports.generateVueDts = generateVueDts;
|
|
370
|
+
exports.generateVueGlobalDts = generateVueGlobalDts;
|
|
371
|
+
exports.generateWCDtsFiles = generateWCDtsFiles;
|
|
372
|
+
exports.generateWCIndexDts = generateWCIndexDts;
|
|
373
|
+
exports.generateWCJsxDts = generateWCJsxDts;
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* component-dts v0.1.0-beta.0
|
|
3
|
+
* (c) 2026 baicie
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
**/
|
|
6
|
+
Object.defineProperties(exports, {
|
|
7
|
+
__esModule: { value: true },
|
|
8
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
9
|
+
});
|
|
10
|
+
//#region \0rolldown/runtime.js
|
|
11
|
+
var __create = Object.create;
|
|
12
|
+
var __defProp = Object.defineProperty;
|
|
13
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
+
key = keys[i];
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
+
get: ((k) => from[k]).bind(null, key),
|
|
22
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
//#endregion
|
|
32
|
+
let node_path = require("node:path");
|
|
33
|
+
node_path = __toESM(node_path, 1);
|
|
34
|
+
//#region packages/web-c/component-dts/src/formatType.ts
|
|
35
|
+
function formatPropType(prop) {
|
|
36
|
+
var _prop$values;
|
|
37
|
+
if ((_prop$values = prop.values) === null || _prop$values === void 0 ? void 0 : _prop$values.length) return prop.values.map((value) => JSON.stringify(value)).join(" | ");
|
|
38
|
+
switch (prop.type) {
|
|
39
|
+
case "string": return "string";
|
|
40
|
+
case "number": return "number";
|
|
41
|
+
case "boolean": return "boolean";
|
|
42
|
+
case "array": return "unknown[]";
|
|
43
|
+
case "object": return "Record<string, unknown>";
|
|
44
|
+
default: return "unknown";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function formatEventType(event) {
|
|
48
|
+
if (!event.detail) return "CustomEvent<unknown>";
|
|
49
|
+
return `CustomEvent<${formatDetailType(event.detail)}>`;
|
|
50
|
+
}
|
|
51
|
+
function formatDetailType(detail) {
|
|
52
|
+
return `{ ${Object.entries(detail).map(([name, type]) => `${safePropertyName(name)}: ${normalizeKnownType(type)}`).join("; ")} }`;
|
|
53
|
+
}
|
|
54
|
+
function normalizeKnownType(type) {
|
|
55
|
+
switch (type) {
|
|
56
|
+
case "string":
|
|
57
|
+
case "number":
|
|
58
|
+
case "boolean":
|
|
59
|
+
case "unknown":
|
|
60
|
+
case "MouseEvent":
|
|
61
|
+
case "KeyboardEvent":
|
|
62
|
+
case "PointerEvent":
|
|
63
|
+
case "FocusEvent":
|
|
64
|
+
case "InputEvent":
|
|
65
|
+
case "Event": return type;
|
|
66
|
+
case "object": return "Record<string, unknown>";
|
|
67
|
+
case "array": return "unknown[]";
|
|
68
|
+
default: return type || "unknown";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function safePropertyName(name) {
|
|
72
|
+
if (/^[A-Za-z\_$][A-Za-z0-9_$]*$/.test(name)) return name;
|
|
73
|
+
return JSON.stringify(name);
|
|
74
|
+
}
|
|
75
|
+
function isRequiredProp(prop) {
|
|
76
|
+
if (prop.default !== void 0) return false;
|
|
77
|
+
return prop.required === true;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region packages/web-c/component-dts/src/naming.ts
|
|
81
|
+
function getElementTypeName(component) {
|
|
82
|
+
if (component.name.endsWith("Element")) return component.name;
|
|
83
|
+
return `${component.name}Element`;
|
|
84
|
+
}
|
|
85
|
+
function getEventMapTypeName(component) {
|
|
86
|
+
return `${component.name}EventMap`;
|
|
87
|
+
}
|
|
88
|
+
function getPropsTypeName(component) {
|
|
89
|
+
return `${component.name}Props`;
|
|
90
|
+
}
|
|
91
|
+
function getComponentFileBaseName(tag, options) {
|
|
92
|
+
if (options.fileName) return sanitizeFileName(options.fileName(tag)).replace(/\.d\.ts$/, "");
|
|
93
|
+
let name = tag;
|
|
94
|
+
if (options.stripPrefix && name.startsWith(options.stripPrefix)) name = name.slice(options.stripPrefix.length);
|
|
95
|
+
return sanitizeFileName(name);
|
|
96
|
+
}
|
|
97
|
+
function getComponentDtsFileName(tag, options) {
|
|
98
|
+
return `${getComponentFileBaseName(tag, options)}.d.ts`;
|
|
99
|
+
}
|
|
100
|
+
function sanitizeFileName(value) {
|
|
101
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region packages/web-c/component-dts/src/generateWcDts.ts
|
|
105
|
+
function generateComponentWCDts(component) {
|
|
106
|
+
const elementTypeName = getElementTypeName(component);
|
|
107
|
+
const lines = [];
|
|
108
|
+
lines.push("/* eslint-disable */");
|
|
109
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
110
|
+
lines.push("");
|
|
111
|
+
lines.push(generateEventMap(component));
|
|
112
|
+
lines.push("");
|
|
113
|
+
lines.push(generateElementInterface(component));
|
|
114
|
+
lines.push("");
|
|
115
|
+
lines.push(`export declare const ${component.exportName}: {`);
|
|
116
|
+
lines.push(` new (): ${elementTypeName}`);
|
|
117
|
+
lines.push("}");
|
|
118
|
+
lines.push("");
|
|
119
|
+
return lines.join("\n");
|
|
120
|
+
}
|
|
121
|
+
function generateWCIndexDts(manifest, options) {
|
|
122
|
+
const lines = [];
|
|
123
|
+
lines.push("/* eslint-disable */");
|
|
124
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
125
|
+
lines.push("");
|
|
126
|
+
for (const component of manifest.components) lines.push(`import type { ${getElementTypeName(component)} } from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
127
|
+
for (const component of manifest.components) lines.push(`export * from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
128
|
+
lines.push("");
|
|
129
|
+
lines.push("declare global {");
|
|
130
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
131
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getElementTypeName(component)}`);
|
|
132
|
+
lines.push(" }");
|
|
133
|
+
lines.push("}");
|
|
134
|
+
lines.push("");
|
|
135
|
+
lines.push("export {}");
|
|
136
|
+
lines.push("");
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
139
|
+
function generateEventMap(component) {
|
|
140
|
+
const eventMapName = getEventMapTypeName(component);
|
|
141
|
+
const entries = Object.entries(component.events);
|
|
142
|
+
const lines = [];
|
|
143
|
+
lines.push(`export interface ${eventMapName} {`);
|
|
144
|
+
if (!entries.length) lines.push(" [key: string]: CustomEvent<unknown>");
|
|
145
|
+
else for (const [name, event] of entries) lines.push(` ${safePropertyName(name)}: ${formatEventType(event)}`);
|
|
146
|
+
lines.push("}");
|
|
147
|
+
return lines.join("\n");
|
|
148
|
+
}
|
|
149
|
+
function generateElementInterface(component) {
|
|
150
|
+
const elementTypeName = getElementTypeName(component);
|
|
151
|
+
const eventMapName = getEventMapTypeName(component);
|
|
152
|
+
const lines = [];
|
|
153
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
154
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
155
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
156
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
157
|
+
}
|
|
158
|
+
lines.push("");
|
|
159
|
+
lines.push(` addEventListener<K extends keyof ${eventMapName}>(`);
|
|
160
|
+
lines.push(" type: K,");
|
|
161
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
162
|
+
lines.push(" options?: boolean | AddEventListenerOptions,");
|
|
163
|
+
lines.push(" ): void");
|
|
164
|
+
lines.push("");
|
|
165
|
+
lines.push(` removeEventListener<K extends keyof ${eventMapName}>(`);
|
|
166
|
+
lines.push(" type: K,");
|
|
167
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
168
|
+
lines.push(" options?: boolean | EventListenerOptions,");
|
|
169
|
+
lines.push(" ): void");
|
|
170
|
+
lines.push("}");
|
|
171
|
+
return lines.join("\n");
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region packages/web-c/component-dts/src/generateJsxDts.ts
|
|
175
|
+
function generateWCJsxDts(manifest) {
|
|
176
|
+
const lines = [];
|
|
177
|
+
lines.push("/* eslint-disable */");
|
|
178
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
179
|
+
lines.push("");
|
|
180
|
+
for (const component of manifest.components) {
|
|
181
|
+
lines.push(generateComponentJsxProps(component));
|
|
182
|
+
lines.push("");
|
|
183
|
+
}
|
|
184
|
+
lines.push("declare global {");
|
|
185
|
+
lines.push(" namespace JSX {");
|
|
186
|
+
lines.push(" interface IntrinsicElements {");
|
|
187
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getPropsTypeName(component)}`);
|
|
188
|
+
lines.push(" }");
|
|
189
|
+
lines.push(" }");
|
|
190
|
+
lines.push("}");
|
|
191
|
+
lines.push("");
|
|
192
|
+
lines.push("export {}");
|
|
193
|
+
lines.push("");
|
|
194
|
+
return lines.join("\n");
|
|
195
|
+
}
|
|
196
|
+
function generateComponentJsxProps(component) {
|
|
197
|
+
const propsTypeName = getPropsTypeName(component);
|
|
198
|
+
const lines = [];
|
|
199
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
200
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
201
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
202
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
203
|
+
}
|
|
204
|
+
lines.push("");
|
|
205
|
+
lines.push(" children?: unknown");
|
|
206
|
+
lines.push(" class?: string");
|
|
207
|
+
lines.push(" className?: string");
|
|
208
|
+
lines.push(" style?: string | Record<string, string | number | null | undefined>");
|
|
209
|
+
lines.push(" id?: string");
|
|
210
|
+
lines.push(" role?: string");
|
|
211
|
+
lines.push(" part?: string");
|
|
212
|
+
lines.push(" slot?: string");
|
|
213
|
+
lines.push("");
|
|
214
|
+
lines.push(" [key: `data-${string}`]: unknown");
|
|
215
|
+
lines.push(" [key: `aria-${string}`]: unknown");
|
|
216
|
+
lines.push("}");
|
|
217
|
+
return lines.join("\n");
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region packages/web-c/component-dts/src/generateReactDts.ts
|
|
221
|
+
function generateReactDts(manifest) {
|
|
222
|
+
const lines = [];
|
|
223
|
+
lines.push("/* eslint-disable */");
|
|
224
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
225
|
+
lines.push("");
|
|
226
|
+
lines.push(`import type * as React from 'react'`);
|
|
227
|
+
lines.push("");
|
|
228
|
+
for (const component of manifest.components) {
|
|
229
|
+
lines.push(generateReactComponentDts(component));
|
|
230
|
+
lines.push("");
|
|
231
|
+
}
|
|
232
|
+
return lines.join("\n");
|
|
233
|
+
}
|
|
234
|
+
function generateReactComponentDts(component) {
|
|
235
|
+
const propsTypeName = getPropsTypeName(component);
|
|
236
|
+
const elementTypeName = getElementTypeName(component);
|
|
237
|
+
const lines = [];
|
|
238
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
239
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
240
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
241
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
242
|
+
}
|
|
243
|
+
lines.push("");
|
|
244
|
+
lines.push(" children?: React.ReactNode");
|
|
245
|
+
lines.push(" className?: string");
|
|
246
|
+
lines.push(" style?: React.CSSProperties");
|
|
247
|
+
for (const [name, event] of Object.entries(component.events)) {
|
|
248
|
+
const propName = toReactEventProp(name);
|
|
249
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
250
|
+
lines.push(` ${propName}?: (event: CustomEvent<${detailType}>) => void`);
|
|
251
|
+
}
|
|
252
|
+
lines.push("}");
|
|
253
|
+
lines.push("");
|
|
254
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
255
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
256
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
257
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
258
|
+
}
|
|
259
|
+
lines.push("}");
|
|
260
|
+
lines.push("");
|
|
261
|
+
lines.push(`export declare const ${component.name}: React.ForwardRefExoticComponent<`);
|
|
262
|
+
lines.push(` ${propsTypeName} & React.RefAttributes<${elementTypeName}>`);
|
|
263
|
+
lines.push(">");
|
|
264
|
+
return lines.join("\n");
|
|
265
|
+
}
|
|
266
|
+
function toReactEventProp(eventName) {
|
|
267
|
+
return "on" + eventName.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
268
|
+
}
|
|
269
|
+
//#endregion
|
|
270
|
+
//#region packages/web-c/component-dts/src/generateVueDts.ts
|
|
271
|
+
function generateVueDts(manifest) {
|
|
272
|
+
const lines = [];
|
|
273
|
+
lines.push("/* eslint-disable */");
|
|
274
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
275
|
+
lines.push("");
|
|
276
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
277
|
+
lines.push("");
|
|
278
|
+
for (const component of manifest.components) {
|
|
279
|
+
lines.push(generateVueComponentDts(component));
|
|
280
|
+
lines.push("");
|
|
281
|
+
}
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
function generateVueGlobalDts(manifest) {
|
|
285
|
+
const lines = [];
|
|
286
|
+
lines.push("/* eslint-disable */");
|
|
287
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
288
|
+
lines.push("");
|
|
289
|
+
lines.push(`import type {`);
|
|
290
|
+
for (const component of manifest.components) lines.push(` ${component.name},`);
|
|
291
|
+
lines.push(`} from './index'`);
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push(`declare module 'vue' {`);
|
|
294
|
+
lines.push(" export interface GlobalComponents {");
|
|
295
|
+
for (const component of manifest.components) lines.push(` ${component.name}: typeof ${component.name}`);
|
|
296
|
+
lines.push(" }");
|
|
297
|
+
lines.push("}");
|
|
298
|
+
lines.push("");
|
|
299
|
+
lines.push("export {}");
|
|
300
|
+
lines.push("");
|
|
301
|
+
return lines.join("\n");
|
|
302
|
+
}
|
|
303
|
+
function generateVueComponentDts(component) {
|
|
304
|
+
const propsTypeName = getPropsTypeName(component);
|
|
305
|
+
const lines = [];
|
|
306
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
307
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
308
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
309
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
310
|
+
}
|
|
311
|
+
lines.push("}");
|
|
312
|
+
lines.push("");
|
|
313
|
+
lines.push(`export declare const ${component.name}: DefineComponent<`);
|
|
314
|
+
lines.push(` ${propsTypeName},`);
|
|
315
|
+
lines.push(" {},");
|
|
316
|
+
lines.push(" {},");
|
|
317
|
+
lines.push(" {},");
|
|
318
|
+
lines.push(" {},");
|
|
319
|
+
lines.push(" {},");
|
|
320
|
+
lines.push(" {},");
|
|
321
|
+
lines.push(` ${generateVueEmitsType(component)}`);
|
|
322
|
+
lines.push(">");
|
|
323
|
+
return lines.join("\n");
|
|
324
|
+
}
|
|
325
|
+
function generateVueEmitsType(component) {
|
|
326
|
+
const entries = Object.entries(component.events);
|
|
327
|
+
if (!entries.length) return "{}";
|
|
328
|
+
return `{ ${entries.map(([name, event]) => {
|
|
329
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
330
|
+
return `${JSON.stringify(name)}: (event: CustomEvent<${detailType}>) => void`;
|
|
331
|
+
}).join("; ")} }`;
|
|
332
|
+
}
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region packages/web-c/component-dts/src/generateFiles.ts
|
|
335
|
+
function generateWCDtsFiles(manifest, options = {}) {
|
|
336
|
+
const normalized = normalizeOptions(options);
|
|
337
|
+
const files = [];
|
|
338
|
+
if (normalized.perComponent) for (const component of manifest.components) files.push({
|
|
339
|
+
fileName: node_path.default.posix.join(normalized.outDir, getComponentDtsFileName(component.tag, normalized)),
|
|
340
|
+
source: generateComponentWCDts(component)
|
|
341
|
+
});
|
|
342
|
+
if (normalized.index) files.push({
|
|
343
|
+
fileName: node_path.default.posix.join(normalized.outDir, "index.d.ts"),
|
|
344
|
+
source: generateWCIndexDts(manifest, { getComponentImportPath: (component) => `./${getComponentFileBaseName(component.tag, normalized)}` })
|
|
345
|
+
});
|
|
346
|
+
if (normalized.jsx) files.push({
|
|
347
|
+
fileName: node_path.default.posix.join(normalized.outDir, "jsx.d.ts"),
|
|
348
|
+
source: generateWCJsxDts(manifest)
|
|
349
|
+
});
|
|
350
|
+
return files;
|
|
351
|
+
}
|
|
352
|
+
function normalizeOptions(options) {
|
|
353
|
+
var _options$outDir, _options$stripPrefix, _options$perComponent, _options$index, _options$jsx;
|
|
354
|
+
return {
|
|
355
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
356
|
+
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
357
|
+
fileName: options.fileName,
|
|
358
|
+
perComponent: (_options$perComponent = options.perComponent) !== null && _options$perComponent !== void 0 ? _options$perComponent : true,
|
|
359
|
+
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
360
|
+
jsx: (_options$jsx = options.jsx) !== null && _options$jsx !== void 0 ? _options$jsx : true
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
//#endregion
|
|
364
|
+
exports.formatDetailType = formatDetailType;
|
|
365
|
+
exports.formatEventType = formatEventType;
|
|
366
|
+
exports.formatPropType = formatPropType;
|
|
367
|
+
exports.generateComponentWCDts = generateComponentWCDts;
|
|
368
|
+
exports.generateReactDts = generateReactDts;
|
|
369
|
+
exports.generateVueDts = generateVueDts;
|
|
370
|
+
exports.generateVueGlobalDts = generateVueGlobalDts;
|
|
371
|
+
exports.generateWCDtsFiles = generateWCDtsFiles;
|
|
372
|
+
exports.generateWCIndexDts = generateWCIndexDts;
|
|
373
|
+
exports.generateWCJsxDts = generateWCJsxDts;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ComponentRecord, ComponentManifest, ComponentEvent, ComponentProp } from '@zeus-js/component-analyzer';
|
|
2
|
+
|
|
3
|
+
export declare function generateComponentWCDts(component: ComponentRecord): string;
|
|
4
|
+
export declare function generateWCIndexDts(manifest: ComponentManifest, options: {
|
|
5
|
+
getComponentImportPath: (component: ComponentRecord) => string;
|
|
6
|
+
}): string;
|
|
7
|
+
|
|
8
|
+
export declare function generateWCJsxDts(manifest: ComponentManifest): string;
|
|
9
|
+
|
|
10
|
+
export declare function generateReactDts(manifest: ComponentManifest): string;
|
|
11
|
+
|
|
12
|
+
export declare function generateVueDts(manifest: ComponentManifest): string;
|
|
13
|
+
export declare function generateVueGlobalDts(manifest: ComponentManifest): string;
|
|
14
|
+
|
|
15
|
+
export interface DtsOutputFile {
|
|
16
|
+
fileName: string;
|
|
17
|
+
source: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ComponentDtsOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Output directory for wc dts files.
|
|
22
|
+
*
|
|
23
|
+
* @default 'wc'
|
|
24
|
+
*/
|
|
25
|
+
outDir?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Strip tag prefix when generating file names.
|
|
28
|
+
*
|
|
29
|
+
* Example:
|
|
30
|
+
* z-button -> button.d.ts
|
|
31
|
+
*/
|
|
32
|
+
stripPrefix?: string | false;
|
|
33
|
+
/**
|
|
34
|
+
* Custom component file name.
|
|
35
|
+
*/
|
|
36
|
+
fileName?: (tag: string) => string;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to generate per-component d.ts.
|
|
39
|
+
*
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
perComponent?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to generate wc/index.d.ts.
|
|
45
|
+
*
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
index?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to generate wc/jsx.d.ts.
|
|
51
|
+
*
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
jsx?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export declare function generateWCDtsFiles(manifest: ComponentManifest, options?: ComponentDtsOptions): DtsOutputFile[];
|
|
58
|
+
|
|
59
|
+
export declare function formatPropType(prop: ComponentProp): string;
|
|
60
|
+
export declare function formatEventType(event: ComponentEvent): string;
|
|
61
|
+
export declare function formatDetailType(detail: Record<string, string>): string;
|
|
62
|
+
|
|
63
|
+
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* component-dts v0.1.0-beta.0
|
|
3
|
+
* (c) 2026 baicie
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
**/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
//#region packages/web-c/component-dts/src/formatType.ts
|
|
8
|
+
function formatPropType(prop) {
|
|
9
|
+
var _prop$values;
|
|
10
|
+
if ((_prop$values = prop.values) === null || _prop$values === void 0 ? void 0 : _prop$values.length) return prop.values.map((value) => JSON.stringify(value)).join(" | ");
|
|
11
|
+
switch (prop.type) {
|
|
12
|
+
case "string": return "string";
|
|
13
|
+
case "number": return "number";
|
|
14
|
+
case "boolean": return "boolean";
|
|
15
|
+
case "array": return "unknown[]";
|
|
16
|
+
case "object": return "Record<string, unknown>";
|
|
17
|
+
default: return "unknown";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function formatEventType(event) {
|
|
21
|
+
if (!event.detail) return "CustomEvent<unknown>";
|
|
22
|
+
return `CustomEvent<${formatDetailType(event.detail)}>`;
|
|
23
|
+
}
|
|
24
|
+
function formatDetailType(detail) {
|
|
25
|
+
return `{ ${Object.entries(detail).map(([name, type]) => `${safePropertyName(name)}: ${normalizeKnownType(type)}`).join("; ")} }`;
|
|
26
|
+
}
|
|
27
|
+
function normalizeKnownType(type) {
|
|
28
|
+
switch (type) {
|
|
29
|
+
case "string":
|
|
30
|
+
case "number":
|
|
31
|
+
case "boolean":
|
|
32
|
+
case "unknown":
|
|
33
|
+
case "MouseEvent":
|
|
34
|
+
case "KeyboardEvent":
|
|
35
|
+
case "PointerEvent":
|
|
36
|
+
case "FocusEvent":
|
|
37
|
+
case "InputEvent":
|
|
38
|
+
case "Event": return type;
|
|
39
|
+
case "object": return "Record<string, unknown>";
|
|
40
|
+
case "array": return "unknown[]";
|
|
41
|
+
default: return type || "unknown";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function safePropertyName(name) {
|
|
45
|
+
if (/^[A-Za-z\_$][A-Za-z0-9_$]*$/.test(name)) return name;
|
|
46
|
+
return JSON.stringify(name);
|
|
47
|
+
}
|
|
48
|
+
function isRequiredProp(prop) {
|
|
49
|
+
if (prop.default !== void 0) return false;
|
|
50
|
+
return prop.required === true;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region packages/web-c/component-dts/src/naming.ts
|
|
54
|
+
function getElementTypeName(component) {
|
|
55
|
+
if (component.name.endsWith("Element")) return component.name;
|
|
56
|
+
return `${component.name}Element`;
|
|
57
|
+
}
|
|
58
|
+
function getEventMapTypeName(component) {
|
|
59
|
+
return `${component.name}EventMap`;
|
|
60
|
+
}
|
|
61
|
+
function getPropsTypeName(component) {
|
|
62
|
+
return `${component.name}Props`;
|
|
63
|
+
}
|
|
64
|
+
function getComponentFileBaseName(tag, options) {
|
|
65
|
+
if (options.fileName) return sanitizeFileName(options.fileName(tag)).replace(/\.d\.ts$/, "");
|
|
66
|
+
let name = tag;
|
|
67
|
+
if (options.stripPrefix && name.startsWith(options.stripPrefix)) name = name.slice(options.stripPrefix.length);
|
|
68
|
+
return sanitizeFileName(name);
|
|
69
|
+
}
|
|
70
|
+
function getComponentDtsFileName(tag, options) {
|
|
71
|
+
return `${getComponentFileBaseName(tag, options)}.d.ts`;
|
|
72
|
+
}
|
|
73
|
+
function sanitizeFileName(value) {
|
|
74
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region packages/web-c/component-dts/src/generateWcDts.ts
|
|
78
|
+
function generateComponentWCDts(component) {
|
|
79
|
+
const elementTypeName = getElementTypeName(component);
|
|
80
|
+
const lines = [];
|
|
81
|
+
lines.push("/* eslint-disable */");
|
|
82
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
83
|
+
lines.push("");
|
|
84
|
+
lines.push(generateEventMap(component));
|
|
85
|
+
lines.push("");
|
|
86
|
+
lines.push(generateElementInterface(component));
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push(`export declare const ${component.exportName}: {`);
|
|
89
|
+
lines.push(` new (): ${elementTypeName}`);
|
|
90
|
+
lines.push("}");
|
|
91
|
+
lines.push("");
|
|
92
|
+
return lines.join("\n");
|
|
93
|
+
}
|
|
94
|
+
function generateWCIndexDts(manifest, options) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
lines.push("/* eslint-disable */");
|
|
97
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
98
|
+
lines.push("");
|
|
99
|
+
for (const component of manifest.components) lines.push(`import type { ${getElementTypeName(component)} } from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
100
|
+
for (const component of manifest.components) lines.push(`export * from ${JSON.stringify(options.getComponentImportPath(component))}`);
|
|
101
|
+
lines.push("");
|
|
102
|
+
lines.push("declare global {");
|
|
103
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
104
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getElementTypeName(component)}`);
|
|
105
|
+
lines.push(" }");
|
|
106
|
+
lines.push("}");
|
|
107
|
+
lines.push("");
|
|
108
|
+
lines.push("export {}");
|
|
109
|
+
lines.push("");
|
|
110
|
+
return lines.join("\n");
|
|
111
|
+
}
|
|
112
|
+
function generateEventMap(component) {
|
|
113
|
+
const eventMapName = getEventMapTypeName(component);
|
|
114
|
+
const entries = Object.entries(component.events);
|
|
115
|
+
const lines = [];
|
|
116
|
+
lines.push(`export interface ${eventMapName} {`);
|
|
117
|
+
if (!entries.length) lines.push(" [key: string]: CustomEvent<unknown>");
|
|
118
|
+
else for (const [name, event] of entries) lines.push(` ${safePropertyName(name)}: ${formatEventType(event)}`);
|
|
119
|
+
lines.push("}");
|
|
120
|
+
return lines.join("\n");
|
|
121
|
+
}
|
|
122
|
+
function generateElementInterface(component) {
|
|
123
|
+
const elementTypeName = getElementTypeName(component);
|
|
124
|
+
const eventMapName = getEventMapTypeName(component);
|
|
125
|
+
const lines = [];
|
|
126
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
127
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
128
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
129
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
130
|
+
}
|
|
131
|
+
lines.push("");
|
|
132
|
+
lines.push(` addEventListener<K extends keyof ${eventMapName}>(`);
|
|
133
|
+
lines.push(" type: K,");
|
|
134
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
135
|
+
lines.push(" options?: boolean | AddEventListenerOptions,");
|
|
136
|
+
lines.push(" ): void");
|
|
137
|
+
lines.push("");
|
|
138
|
+
lines.push(` removeEventListener<K extends keyof ${eventMapName}>(`);
|
|
139
|
+
lines.push(" type: K,");
|
|
140
|
+
lines.push(` listener: (this: ${elementTypeName}, ev: ${eventMapName}[K]) => unknown,`);
|
|
141
|
+
lines.push(" options?: boolean | EventListenerOptions,");
|
|
142
|
+
lines.push(" ): void");
|
|
143
|
+
lines.push("}");
|
|
144
|
+
return lines.join("\n");
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region packages/web-c/component-dts/src/generateJsxDts.ts
|
|
148
|
+
function generateWCJsxDts(manifest) {
|
|
149
|
+
const lines = [];
|
|
150
|
+
lines.push("/* eslint-disable */");
|
|
151
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
152
|
+
lines.push("");
|
|
153
|
+
for (const component of manifest.components) {
|
|
154
|
+
lines.push(generateComponentJsxProps(component));
|
|
155
|
+
lines.push("");
|
|
156
|
+
}
|
|
157
|
+
lines.push("declare global {");
|
|
158
|
+
lines.push(" namespace JSX {");
|
|
159
|
+
lines.push(" interface IntrinsicElements {");
|
|
160
|
+
for (const component of manifest.components) lines.push(` ${JSON.stringify(component.tag)}: ${getPropsTypeName(component)}`);
|
|
161
|
+
lines.push(" }");
|
|
162
|
+
lines.push(" }");
|
|
163
|
+
lines.push("}");
|
|
164
|
+
lines.push("");
|
|
165
|
+
lines.push("export {}");
|
|
166
|
+
lines.push("");
|
|
167
|
+
return lines.join("\n");
|
|
168
|
+
}
|
|
169
|
+
function generateComponentJsxProps(component) {
|
|
170
|
+
const propsTypeName = getPropsTypeName(component);
|
|
171
|
+
const lines = [];
|
|
172
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
173
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
174
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
175
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
176
|
+
}
|
|
177
|
+
lines.push("");
|
|
178
|
+
lines.push(" children?: unknown");
|
|
179
|
+
lines.push(" class?: string");
|
|
180
|
+
lines.push(" className?: string");
|
|
181
|
+
lines.push(" style?: string | Record<string, string | number | null | undefined>");
|
|
182
|
+
lines.push(" id?: string");
|
|
183
|
+
lines.push(" role?: string");
|
|
184
|
+
lines.push(" part?: string");
|
|
185
|
+
lines.push(" slot?: string");
|
|
186
|
+
lines.push("");
|
|
187
|
+
lines.push(" [key: `data-${string}`]: unknown");
|
|
188
|
+
lines.push(" [key: `aria-${string}`]: unknown");
|
|
189
|
+
lines.push("}");
|
|
190
|
+
return lines.join("\n");
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region packages/web-c/component-dts/src/generateReactDts.ts
|
|
194
|
+
function generateReactDts(manifest) {
|
|
195
|
+
const lines = [];
|
|
196
|
+
lines.push("/* eslint-disable */");
|
|
197
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
198
|
+
lines.push("");
|
|
199
|
+
lines.push(`import type * as React from 'react'`);
|
|
200
|
+
lines.push("");
|
|
201
|
+
for (const component of manifest.components) {
|
|
202
|
+
lines.push(generateReactComponentDts(component));
|
|
203
|
+
lines.push("");
|
|
204
|
+
}
|
|
205
|
+
return lines.join("\n");
|
|
206
|
+
}
|
|
207
|
+
function generateReactComponentDts(component) {
|
|
208
|
+
const propsTypeName = getPropsTypeName(component);
|
|
209
|
+
const elementTypeName = getElementTypeName(component);
|
|
210
|
+
const lines = [];
|
|
211
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
212
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
213
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
214
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
215
|
+
}
|
|
216
|
+
lines.push("");
|
|
217
|
+
lines.push(" children?: React.ReactNode");
|
|
218
|
+
lines.push(" className?: string");
|
|
219
|
+
lines.push(" style?: React.CSSProperties");
|
|
220
|
+
for (const [name, event] of Object.entries(component.events)) {
|
|
221
|
+
const propName = toReactEventProp(name);
|
|
222
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
223
|
+
lines.push(` ${propName}?: (event: CustomEvent<${detailType}>) => void`);
|
|
224
|
+
}
|
|
225
|
+
lines.push("}");
|
|
226
|
+
lines.push("");
|
|
227
|
+
lines.push(`export interface ${elementTypeName} extends HTMLElement {`);
|
|
228
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
229
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
230
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
231
|
+
}
|
|
232
|
+
lines.push("}");
|
|
233
|
+
lines.push("");
|
|
234
|
+
lines.push(`export declare const ${component.name}: React.ForwardRefExoticComponent<`);
|
|
235
|
+
lines.push(` ${propsTypeName} & React.RefAttributes<${elementTypeName}>`);
|
|
236
|
+
lines.push(">");
|
|
237
|
+
return lines.join("\n");
|
|
238
|
+
}
|
|
239
|
+
function toReactEventProp(eventName) {
|
|
240
|
+
return "on" + eventName.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region packages/web-c/component-dts/src/generateVueDts.ts
|
|
244
|
+
function generateVueDts(manifest) {
|
|
245
|
+
const lines = [];
|
|
246
|
+
lines.push("/* eslint-disable */");
|
|
247
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
248
|
+
lines.push("");
|
|
249
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
250
|
+
lines.push("");
|
|
251
|
+
for (const component of manifest.components) {
|
|
252
|
+
lines.push(generateVueComponentDts(component));
|
|
253
|
+
lines.push("");
|
|
254
|
+
}
|
|
255
|
+
return lines.join("\n");
|
|
256
|
+
}
|
|
257
|
+
function generateVueGlobalDts(manifest) {
|
|
258
|
+
const lines = [];
|
|
259
|
+
lines.push("/* eslint-disable */");
|
|
260
|
+
lines.push("// Generated by @zeus-js/component-dts.");
|
|
261
|
+
lines.push("");
|
|
262
|
+
lines.push(`import type {`);
|
|
263
|
+
for (const component of manifest.components) lines.push(` ${component.name},`);
|
|
264
|
+
lines.push(`} from './index'`);
|
|
265
|
+
lines.push("");
|
|
266
|
+
lines.push(`declare module 'vue' {`);
|
|
267
|
+
lines.push(" export interface GlobalComponents {");
|
|
268
|
+
for (const component of manifest.components) lines.push(` ${component.name}: typeof ${component.name}`);
|
|
269
|
+
lines.push(" }");
|
|
270
|
+
lines.push("}");
|
|
271
|
+
lines.push("");
|
|
272
|
+
lines.push("export {}");
|
|
273
|
+
lines.push("");
|
|
274
|
+
return lines.join("\n");
|
|
275
|
+
}
|
|
276
|
+
function generateVueComponentDts(component) {
|
|
277
|
+
const propsTypeName = getPropsTypeName(component);
|
|
278
|
+
const lines = [];
|
|
279
|
+
lines.push(`export interface ${propsTypeName} {`);
|
|
280
|
+
for (const [name, prop] of Object.entries(component.props)) {
|
|
281
|
+
const optional = isRequiredProp(prop) ? "" : "?";
|
|
282
|
+
lines.push(` ${safePropertyName(name)}${optional}: ${formatPropType(prop)}`);
|
|
283
|
+
}
|
|
284
|
+
lines.push("}");
|
|
285
|
+
lines.push("");
|
|
286
|
+
lines.push(`export declare const ${component.name}: DefineComponent<`);
|
|
287
|
+
lines.push(` ${propsTypeName},`);
|
|
288
|
+
lines.push(" {},");
|
|
289
|
+
lines.push(" {},");
|
|
290
|
+
lines.push(" {},");
|
|
291
|
+
lines.push(" {},");
|
|
292
|
+
lines.push(" {},");
|
|
293
|
+
lines.push(" {},");
|
|
294
|
+
lines.push(` ${generateVueEmitsType(component)}`);
|
|
295
|
+
lines.push(">");
|
|
296
|
+
return lines.join("\n");
|
|
297
|
+
}
|
|
298
|
+
function generateVueEmitsType(component) {
|
|
299
|
+
const entries = Object.entries(component.events);
|
|
300
|
+
if (!entries.length) return "{}";
|
|
301
|
+
return `{ ${entries.map(([name, event]) => {
|
|
302
|
+
const detailType = event.detail ? formatDetailType(event.detail) : "unknown";
|
|
303
|
+
return `${JSON.stringify(name)}: (event: CustomEvent<${detailType}>) => void`;
|
|
304
|
+
}).join("; ")} }`;
|
|
305
|
+
}
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region packages/web-c/component-dts/src/generateFiles.ts
|
|
308
|
+
function generateWCDtsFiles(manifest, options = {}) {
|
|
309
|
+
const normalized = normalizeOptions(options);
|
|
310
|
+
const files = [];
|
|
311
|
+
if (normalized.perComponent) for (const component of manifest.components) files.push({
|
|
312
|
+
fileName: path.posix.join(normalized.outDir, getComponentDtsFileName(component.tag, normalized)),
|
|
313
|
+
source: generateComponentWCDts(component)
|
|
314
|
+
});
|
|
315
|
+
if (normalized.index) files.push({
|
|
316
|
+
fileName: path.posix.join(normalized.outDir, "index.d.ts"),
|
|
317
|
+
source: generateWCIndexDts(manifest, { getComponentImportPath: (component) => `./${getComponentFileBaseName(component.tag, normalized)}` })
|
|
318
|
+
});
|
|
319
|
+
if (normalized.jsx) files.push({
|
|
320
|
+
fileName: path.posix.join(normalized.outDir, "jsx.d.ts"),
|
|
321
|
+
source: generateWCJsxDts(manifest)
|
|
322
|
+
});
|
|
323
|
+
return files;
|
|
324
|
+
}
|
|
325
|
+
function normalizeOptions(options) {
|
|
326
|
+
var _options$outDir, _options$stripPrefix, _options$perComponent, _options$index, _options$jsx;
|
|
327
|
+
return {
|
|
328
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "wc",
|
|
329
|
+
stripPrefix: (_options$stripPrefix = options.stripPrefix) !== null && _options$stripPrefix !== void 0 ? _options$stripPrefix : false,
|
|
330
|
+
fileName: options.fileName,
|
|
331
|
+
perComponent: (_options$perComponent = options.perComponent) !== null && _options$perComponent !== void 0 ? _options$perComponent : true,
|
|
332
|
+
index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
|
|
333
|
+
jsx: (_options$jsx = options.jsx) !== null && _options$jsx !== void 0 ? _options$jsx : true
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
337
|
+
export { formatDetailType, formatEventType, formatPropType, generateComponentWCDts, generateReactDts, generateVueDts, generateVueGlobalDts, generateWCDtsFiles, generateWCIndexDts, generateWCJsxDts };
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zeus-js/component-dts",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "DTS generators for Zeus component manifest",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "dist/component-dts.esm-bundler.js",
|
|
8
|
+
"types": "dist/component-dts.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/component-dts.d.ts",
|
|
16
|
+
"node": {
|
|
17
|
+
"production": "./dist/component-dts.cjs.prod.js",
|
|
18
|
+
"development": "./dist/component-dts.cjs.js",
|
|
19
|
+
"default": "./index.js"
|
|
20
|
+
},
|
|
21
|
+
"module": "./dist/component-dts.esm-bundler.js",
|
|
22
|
+
"import": "./dist/component-dts.esm-bundler.js",
|
|
23
|
+
"require": "./index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/baicie/zeus"
|
|
30
|
+
},
|
|
31
|
+
"buildOptions": {
|
|
32
|
+
"name": "ZeusComponentDts",
|
|
33
|
+
"formats": [
|
|
34
|
+
"esm-bundler",
|
|
35
|
+
"cjs"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@zeus-js/component-analyzer": "0.1.0-beta.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"zeus",
|
|
43
|
+
"web-components",
|
|
44
|
+
"dts",
|
|
45
|
+
"types"
|
|
46
|
+
],
|
|
47
|
+
"author": "Baicie",
|
|
48
|
+
"license": "MIT"
|
|
49
|
+
}
|