@zeus-js/output-icons 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/output-icons.cjs.js +421 -0
- package/dist/output-icons.cjs.prod.js +421 -0
- package/dist/output-icons.d.ts +86 -0
- package/dist/output-icons.esm-bundler.js +394 -0
- package/index.js +4 -0
- package/package.json +63 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* output-icons 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/output-icons/src/generateDts.ts
|
|
35
|
+
function generateReactDts(icons) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
lines.push(`import type * as React from 'react'`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(`export interface IconProps extends React.SVGAttributes<SVGSVGElement> {`);
|
|
40
|
+
lines.push(` size?: string | number`);
|
|
41
|
+
lines.push(` title?: string`);
|
|
42
|
+
lines.push(`}`);
|
|
43
|
+
lines.push("");
|
|
44
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: React.ForwardRefExoticComponent<IconProps & React.RefAttributes<SVGSVGElement>>`);
|
|
45
|
+
lines.push("");
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
function generateVueDts(icons) {
|
|
49
|
+
const lines = [];
|
|
50
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
51
|
+
lines.push("");
|
|
52
|
+
lines.push(`export interface IconProps {`);
|
|
53
|
+
lines.push(` size?: string | number`);
|
|
54
|
+
lines.push(` title?: string`);
|
|
55
|
+
lines.push(`}`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: DefineComponent<IconProps>`);
|
|
58
|
+
lines.push("");
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
function generateStaticWcDts(icons) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const icon of icons) {
|
|
64
|
+
const className = `${icon.componentName}Element`;
|
|
65
|
+
lines.push(`export interface ${className} extends HTMLElement {`);
|
|
66
|
+
lines.push(` size?: string`);
|
|
67
|
+
lines.push(` label?: string`);
|
|
68
|
+
lines.push(`}`);
|
|
69
|
+
lines.push("");
|
|
70
|
+
lines.push(`export declare const ${icon.componentName}: {`);
|
|
71
|
+
lines.push(` new (): ${className}`);
|
|
72
|
+
lines.push(`}`);
|
|
73
|
+
lines.push("");
|
|
74
|
+
}
|
|
75
|
+
lines.push("declare global {");
|
|
76
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
77
|
+
for (const icon of icons) lines.push(` ${JSON.stringify(icon.wcTag)}: ${icon.componentName}Element`);
|
|
78
|
+
lines.push(" }");
|
|
79
|
+
lines.push("}");
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push("export {}");
|
|
82
|
+
lines.push("");
|
|
83
|
+
return lines.join("\n");
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region packages/web-c/output-icons/src/svg.ts
|
|
87
|
+
function parseSvg(source) {
|
|
88
|
+
var _svgMatch$, _svgMatch$2$trim, _svgMatch$2, _ref, _readAttribute;
|
|
89
|
+
const svgMatch = sanitizeSvg(source).match(/<svg\b([^>]*)>([\s\S]*?)<\/svg>/i);
|
|
90
|
+
if (!svgMatch) throw new Error("Invalid SVG source. Expected <svg>...</svg>.");
|
|
91
|
+
const attrs = (_svgMatch$ = svgMatch[1]) !== null && _svgMatch$ !== void 0 ? _svgMatch$ : "";
|
|
92
|
+
const innerSvg = (_svgMatch$2$trim = (_svgMatch$2 = svgMatch[2]) === null || _svgMatch$2 === void 0 ? void 0 : _svgMatch$2.trim()) !== null && _svgMatch$2$trim !== void 0 ? _svgMatch$2$trim : "";
|
|
93
|
+
return {
|
|
94
|
+
viewBox: (_ref = (_readAttribute = readAttribute(attrs, "viewBox")) !== null && _readAttribute !== void 0 ? _readAttribute : readAttribute(attrs, "viewbox")) !== null && _ref !== void 0 ? _ref : "0 0 24 24",
|
|
95
|
+
innerSvg
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function sanitizeSvg(source) {
|
|
99
|
+
return source.replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*\{[^}]*\}/gi, "");
|
|
100
|
+
}
|
|
101
|
+
function readAttribute(attrs, name) {
|
|
102
|
+
const doubleQuote = new RegExp(`${name}\\s*=\\s*"([^"]*)"`, "i").exec(attrs);
|
|
103
|
+
if (doubleQuote) return doubleQuote[1];
|
|
104
|
+
const singleQuote = new RegExp(`${name}\\s*=\\s*'([^']*)'`, "i").exec(attrs);
|
|
105
|
+
if (singleQuote) return singleQuote[1];
|
|
106
|
+
}
|
|
107
|
+
function escapeTemplateLiteral(value) {
|
|
108
|
+
return value.replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
109
|
+
}
|
|
110
|
+
function svgToDataSource(svg) {
|
|
111
|
+
return svg.trim();
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region packages/web-c/output-icons/src/generateReactIcon.ts
|
|
115
|
+
function generateReactIcon(icon) {
|
|
116
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
117
|
+
return `
|
|
118
|
+
import React from 'react';
|
|
119
|
+
|
|
120
|
+
export const ${icon.componentName} = React.forwardRef(function ${icon.componentName}(props, ref) {
|
|
121
|
+
const {
|
|
122
|
+
size = '1em',
|
|
123
|
+
title,
|
|
124
|
+
children,
|
|
125
|
+
...rest
|
|
126
|
+
} = props;
|
|
127
|
+
|
|
128
|
+
const content = children != null
|
|
129
|
+
? children
|
|
130
|
+
: React.createElement('g', {
|
|
131
|
+
dangerouslySetInnerHTML: { __html: \`${inner}\` },
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return React.createElement(
|
|
135
|
+
'svg',
|
|
136
|
+
{
|
|
137
|
+
...rest,
|
|
138
|
+
ref,
|
|
139
|
+
width: size,
|
|
140
|
+
height: size,
|
|
141
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
142
|
+
fill: 'none',
|
|
143
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
144
|
+
'aria-hidden': title ? undefined : true,
|
|
145
|
+
role: title ? 'img' : undefined,
|
|
146
|
+
},
|
|
147
|
+
title ? React.createElement('title', null, title) : null,
|
|
148
|
+
content,
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
`.trimStart();
|
|
152
|
+
}
|
|
153
|
+
function generateReactIndex(icons) {
|
|
154
|
+
return `${icons.map((icon) => {
|
|
155
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
156
|
+
}).join("\n")}\n`;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region packages/web-c/output-icons/src/generateStaticWcIcon.ts
|
|
160
|
+
function generateStaticWcIcon(icon) {
|
|
161
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
162
|
+
const className = `${icon.componentName}Element`;
|
|
163
|
+
return `
|
|
164
|
+
const INNER_SVG = \`${inner}\`;
|
|
165
|
+
const VIEW_BOX = ${JSON.stringify(icon.viewBox)};
|
|
166
|
+
|
|
167
|
+
export class ${className} extends HTMLElement {
|
|
168
|
+
static get observedAttributes() {
|
|
169
|
+
return ['size', 'label'];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
connectedCallback() {
|
|
173
|
+
this.render();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
attributeChangedCallback() {
|
|
177
|
+
this.render();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get size() {
|
|
181
|
+
return this.getAttribute('size') || '1em';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
set size(value) {
|
|
185
|
+
if (value == null) {
|
|
186
|
+
this.removeAttribute('size');
|
|
187
|
+
} else {
|
|
188
|
+
this.setAttribute('size', String(value));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
get label() {
|
|
193
|
+
return this.getAttribute('label') || '';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
set label(value) {
|
|
197
|
+
if (value == null || value === '') {
|
|
198
|
+
this.removeAttribute('label');
|
|
199
|
+
} else {
|
|
200
|
+
this.setAttribute('label', String(value));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
render() {
|
|
205
|
+
const size = this.size;
|
|
206
|
+
const label = this.label;
|
|
207
|
+
|
|
208
|
+
this.innerHTML =
|
|
209
|
+
'<svg' +
|
|
210
|
+
' part="root"' +
|
|
211
|
+
' width="' + escapeHtml(size) + '"' +
|
|
212
|
+
' height="' + escapeHtml(size) + '"' +
|
|
213
|
+
' viewBox="' + escapeHtml(VIEW_BOX) + '"' +
|
|
214
|
+
' xmlns="http://www.w3.org/2000/svg"' +
|
|
215
|
+
(label ? ' role="img" aria-label="' + escapeHtml(label) + '"' : ' aria-hidden="true"') +
|
|
216
|
+
'>' +
|
|
217
|
+
INNER_SVG +
|
|
218
|
+
'</svg>';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!customElements.get(${JSON.stringify(icon.wcTag)})) {
|
|
223
|
+
customElements.define(${JSON.stringify(icon.wcTag)}, ${className});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export const ${icon.componentName} = ${className};
|
|
227
|
+
|
|
228
|
+
function escapeHtml(value) {
|
|
229
|
+
return String(value)
|
|
230
|
+
.replace(/&/g, '&')
|
|
231
|
+
.replace(/"/g, '"')
|
|
232
|
+
.replace(/</g, '<')
|
|
233
|
+
.replace(/>/g, '>');
|
|
234
|
+
}
|
|
235
|
+
`.trimStart();
|
|
236
|
+
}
|
|
237
|
+
function generateStaticWcIndex(icons) {
|
|
238
|
+
return `${icons.map((icon) => {
|
|
239
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
240
|
+
}).join("\n")}\n`;
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region packages/web-c/output-icons/src/generateVueIcon.ts
|
|
244
|
+
function generateVueIcon(icon) {
|
|
245
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
246
|
+
return `
|
|
247
|
+
import { defineComponent, h } from 'vue';
|
|
248
|
+
|
|
249
|
+
export const ${icon.componentName} = defineComponent({
|
|
250
|
+
name: ${JSON.stringify(icon.componentName)},
|
|
251
|
+
|
|
252
|
+
props: {
|
|
253
|
+
size: {
|
|
254
|
+
type: [String, Number],
|
|
255
|
+
default: '1em',
|
|
256
|
+
},
|
|
257
|
+
title: {
|
|
258
|
+
type: String,
|
|
259
|
+
default: undefined,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
setup(props, { attrs, slots }) {
|
|
264
|
+
return () => {
|
|
265
|
+
const children = [];
|
|
266
|
+
|
|
267
|
+
if (props.title) {
|
|
268
|
+
children.push(h('title', null, props.title));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (slots.default) {
|
|
272
|
+
children.push(...slots.default());
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return h(
|
|
276
|
+
'svg',
|
|
277
|
+
{
|
|
278
|
+
...attrs,
|
|
279
|
+
width: props.size,
|
|
280
|
+
height: props.size,
|
|
281
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
282
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
283
|
+
'aria-hidden': props.title ? undefined : true,
|
|
284
|
+
role: props.title ? 'img' : undefined,
|
|
285
|
+
innerHTML: slots.default ? undefined : \`${inner}\`,
|
|
286
|
+
},
|
|
287
|
+
children,
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
`.trimStart();
|
|
293
|
+
}
|
|
294
|
+
function generateVueIndex(icons) {
|
|
295
|
+
return `${icons.map((icon) => {
|
|
296
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
297
|
+
}).join("\n")}\n`;
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region packages/web-c/output-icons/src/naming.ts
|
|
301
|
+
function toPascalCase(value) {
|
|
302
|
+
return value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("") || "Icon";
|
|
303
|
+
}
|
|
304
|
+
function toIconComponentName(name) {
|
|
305
|
+
const pascal = toPascalCase(name);
|
|
306
|
+
return pascal.endsWith("Icon") ? pascal : `${pascal}Icon`;
|
|
307
|
+
}
|
|
308
|
+
function sanitizeFileName(value) {
|
|
309
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
310
|
+
}
|
|
311
|
+
function getIconJsFileName(name) {
|
|
312
|
+
return `${sanitizeFileName(name)}.js`;
|
|
313
|
+
}
|
|
314
|
+
function getIconSvgFileName(name) {
|
|
315
|
+
return `${sanitizeFileName(name)}.svg`;
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region packages/web-c/output-icons/src/index.ts
|
|
319
|
+
function icons(options) {
|
|
320
|
+
const normalized = normalizeOptions(options);
|
|
321
|
+
return {
|
|
322
|
+
name: "zeus-output-icons",
|
|
323
|
+
virtualModules() {
|
|
324
|
+
const modules = [];
|
|
325
|
+
if (normalized.react) {
|
|
326
|
+
for (const icon of normalized.icons) modules.push({
|
|
327
|
+
id: `zeus:icons:react:${icon.name}`,
|
|
328
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, getIconJsFileName(icon.name)),
|
|
329
|
+
code: generateReactIcon(icon)
|
|
330
|
+
});
|
|
331
|
+
modules.push({
|
|
332
|
+
id: "zeus:icons:react:index",
|
|
333
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, "index.js"),
|
|
334
|
+
code: generateReactIndex(normalized.icons)
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
if (normalized.vue) {
|
|
338
|
+
for (const icon of normalized.icons) modules.push({
|
|
339
|
+
id: `zeus:icons:vue:${icon.name}`,
|
|
340
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, getIconJsFileName(icon.name)),
|
|
341
|
+
code: generateVueIcon(icon)
|
|
342
|
+
});
|
|
343
|
+
modules.push({
|
|
344
|
+
id: "zeus:icons:vue:index",
|
|
345
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, "index.js"),
|
|
346
|
+
code: generateVueIndex(normalized.icons)
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
if (normalized.wc) {
|
|
350
|
+
for (const icon of normalized.icons) modules.push({
|
|
351
|
+
id: `zeus:icons:wc:${icon.name}`,
|
|
352
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, getIconJsFileName(icon.name)),
|
|
353
|
+
code: generateStaticWcIcon(icon)
|
|
354
|
+
});
|
|
355
|
+
modules.push({
|
|
356
|
+
id: "zeus:icons:wc:index",
|
|
357
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, "index.js"),
|
|
358
|
+
code: generateStaticWcIndex(normalized.icons)
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return modules;
|
|
362
|
+
},
|
|
363
|
+
generateBundle() {
|
|
364
|
+
const files = [];
|
|
365
|
+
if (normalized.svg) for (const icon of normalized.icons) files.push({
|
|
366
|
+
type: "asset",
|
|
367
|
+
fileName: node_path.default.posix.join(normalized.outDir, "svg", getIconSvgFileName(icon.name)),
|
|
368
|
+
source: svgToDataSource(icon.svg)
|
|
369
|
+
});
|
|
370
|
+
if (normalized.dts && normalized.react) files.push({
|
|
371
|
+
type: "asset",
|
|
372
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, "index.d.ts"),
|
|
373
|
+
source: generateReactDts(normalized.icons)
|
|
374
|
+
});
|
|
375
|
+
if (normalized.dts && normalized.vue) files.push({
|
|
376
|
+
type: "asset",
|
|
377
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, "index.d.ts"),
|
|
378
|
+
source: generateVueDts(normalized.icons)
|
|
379
|
+
});
|
|
380
|
+
if (normalized.dts && normalized.wc) files.push({
|
|
381
|
+
type: "asset",
|
|
382
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, "index.d.ts"),
|
|
383
|
+
source: generateStaticWcDts(normalized.icons)
|
|
384
|
+
});
|
|
385
|
+
return files;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function normalizeOptions(options) {
|
|
390
|
+
var _options$icons, _options$outDir, _options$svg, _options$dts;
|
|
391
|
+
if (!((_options$icons = options.icons) === null || _options$icons === void 0 ? void 0 : _options$icons.length)) throw new Error("[zeus-output-icons] options.icons is required.");
|
|
392
|
+
const wcOptions = options.wc === false ? false : {
|
|
393
|
+
outDir: typeof options.wc === "object" && options.wc.outDir ? options.wc.outDir : "wc",
|
|
394
|
+
tagPrefix: typeof options.wc === "object" && options.wc.tagPrefix ? options.wc.tagPrefix : "z-icon-"
|
|
395
|
+
};
|
|
396
|
+
return {
|
|
397
|
+
icons: normalizeIcons(options.icons, wcOptions ? wcOptions.tagPrefix : "z-icon-"),
|
|
398
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "icons",
|
|
399
|
+
svg: (_options$svg = options.svg) !== null && _options$svg !== void 0 ? _options$svg : true,
|
|
400
|
+
react: options.react === false ? false : { outDir: typeof options.react === "object" && options.react.outDir ? options.react.outDir : "react" },
|
|
401
|
+
vue: options.vue === false ? false : { outDir: typeof options.vue === "object" && options.vue.outDir ? options.vue.outDir : "vue" },
|
|
402
|
+
wc: wcOptions,
|
|
403
|
+
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function normalizeIcons(icons, tagPrefix) {
|
|
407
|
+
return icons.map((icon) => {
|
|
408
|
+
const parsed = parseSvg(icon.svg);
|
|
409
|
+
return {
|
|
410
|
+
name: icon.name,
|
|
411
|
+
componentName: toIconComponentName(icon.name),
|
|
412
|
+
wcTag: `${tagPrefix}${icon.name}`,
|
|
413
|
+
svg: icon.svg,
|
|
414
|
+
title: icon.title,
|
|
415
|
+
viewBox: parsed.viewBox,
|
|
416
|
+
innerSvg: parsed.innerSvg
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
exports.default = icons;
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* output-icons 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/output-icons/src/generateDts.ts
|
|
35
|
+
function generateReactDts(icons) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
lines.push(`import type * as React from 'react'`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(`export interface IconProps extends React.SVGAttributes<SVGSVGElement> {`);
|
|
40
|
+
lines.push(` size?: string | number`);
|
|
41
|
+
lines.push(` title?: string`);
|
|
42
|
+
lines.push(`}`);
|
|
43
|
+
lines.push("");
|
|
44
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: React.ForwardRefExoticComponent<IconProps & React.RefAttributes<SVGSVGElement>>`);
|
|
45
|
+
lines.push("");
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
function generateVueDts(icons) {
|
|
49
|
+
const lines = [];
|
|
50
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
51
|
+
lines.push("");
|
|
52
|
+
lines.push(`export interface IconProps {`);
|
|
53
|
+
lines.push(` size?: string | number`);
|
|
54
|
+
lines.push(` title?: string`);
|
|
55
|
+
lines.push(`}`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: DefineComponent<IconProps>`);
|
|
58
|
+
lines.push("");
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
function generateStaticWcDts(icons) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const icon of icons) {
|
|
64
|
+
const className = `${icon.componentName}Element`;
|
|
65
|
+
lines.push(`export interface ${className} extends HTMLElement {`);
|
|
66
|
+
lines.push(` size?: string`);
|
|
67
|
+
lines.push(` label?: string`);
|
|
68
|
+
lines.push(`}`);
|
|
69
|
+
lines.push("");
|
|
70
|
+
lines.push(`export declare const ${icon.componentName}: {`);
|
|
71
|
+
lines.push(` new (): ${className}`);
|
|
72
|
+
lines.push(`}`);
|
|
73
|
+
lines.push("");
|
|
74
|
+
}
|
|
75
|
+
lines.push("declare global {");
|
|
76
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
77
|
+
for (const icon of icons) lines.push(` ${JSON.stringify(icon.wcTag)}: ${icon.componentName}Element`);
|
|
78
|
+
lines.push(" }");
|
|
79
|
+
lines.push("}");
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push("export {}");
|
|
82
|
+
lines.push("");
|
|
83
|
+
return lines.join("\n");
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region packages/web-c/output-icons/src/svg.ts
|
|
87
|
+
function parseSvg(source) {
|
|
88
|
+
var _svgMatch$, _svgMatch$2$trim, _svgMatch$2, _ref, _readAttribute;
|
|
89
|
+
const svgMatch = sanitizeSvg(source).match(/<svg\b([^>]*)>([\s\S]*?)<\/svg>/i);
|
|
90
|
+
if (!svgMatch) throw new Error("Invalid SVG source. Expected <svg>...</svg>.");
|
|
91
|
+
const attrs = (_svgMatch$ = svgMatch[1]) !== null && _svgMatch$ !== void 0 ? _svgMatch$ : "";
|
|
92
|
+
const innerSvg = (_svgMatch$2$trim = (_svgMatch$2 = svgMatch[2]) === null || _svgMatch$2 === void 0 ? void 0 : _svgMatch$2.trim()) !== null && _svgMatch$2$trim !== void 0 ? _svgMatch$2$trim : "";
|
|
93
|
+
return {
|
|
94
|
+
viewBox: (_ref = (_readAttribute = readAttribute(attrs, "viewBox")) !== null && _readAttribute !== void 0 ? _readAttribute : readAttribute(attrs, "viewbox")) !== null && _ref !== void 0 ? _ref : "0 0 24 24",
|
|
95
|
+
innerSvg
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function sanitizeSvg(source) {
|
|
99
|
+
return source.replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*\{[^}]*\}/gi, "");
|
|
100
|
+
}
|
|
101
|
+
function readAttribute(attrs, name) {
|
|
102
|
+
const doubleQuote = new RegExp(`${name}\\s*=\\s*"([^"]*)"`, "i").exec(attrs);
|
|
103
|
+
if (doubleQuote) return doubleQuote[1];
|
|
104
|
+
const singleQuote = new RegExp(`${name}\\s*=\\s*'([^']*)'`, "i").exec(attrs);
|
|
105
|
+
if (singleQuote) return singleQuote[1];
|
|
106
|
+
}
|
|
107
|
+
function escapeTemplateLiteral(value) {
|
|
108
|
+
return value.replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
109
|
+
}
|
|
110
|
+
function svgToDataSource(svg) {
|
|
111
|
+
return svg.trim();
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region packages/web-c/output-icons/src/generateReactIcon.ts
|
|
115
|
+
function generateReactIcon(icon) {
|
|
116
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
117
|
+
return `
|
|
118
|
+
import React from 'react';
|
|
119
|
+
|
|
120
|
+
export const ${icon.componentName} = React.forwardRef(function ${icon.componentName}(props, ref) {
|
|
121
|
+
const {
|
|
122
|
+
size = '1em',
|
|
123
|
+
title,
|
|
124
|
+
children,
|
|
125
|
+
...rest
|
|
126
|
+
} = props;
|
|
127
|
+
|
|
128
|
+
const content = children != null
|
|
129
|
+
? children
|
|
130
|
+
: React.createElement('g', {
|
|
131
|
+
dangerouslySetInnerHTML: { __html: \`${inner}\` },
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return React.createElement(
|
|
135
|
+
'svg',
|
|
136
|
+
{
|
|
137
|
+
...rest,
|
|
138
|
+
ref,
|
|
139
|
+
width: size,
|
|
140
|
+
height: size,
|
|
141
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
142
|
+
fill: 'none',
|
|
143
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
144
|
+
'aria-hidden': title ? undefined : true,
|
|
145
|
+
role: title ? 'img' : undefined,
|
|
146
|
+
},
|
|
147
|
+
title ? React.createElement('title', null, title) : null,
|
|
148
|
+
content,
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
`.trimStart();
|
|
152
|
+
}
|
|
153
|
+
function generateReactIndex(icons) {
|
|
154
|
+
return `${icons.map((icon) => {
|
|
155
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
156
|
+
}).join("\n")}\n`;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region packages/web-c/output-icons/src/generateStaticWcIcon.ts
|
|
160
|
+
function generateStaticWcIcon(icon) {
|
|
161
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
162
|
+
const className = `${icon.componentName}Element`;
|
|
163
|
+
return `
|
|
164
|
+
const INNER_SVG = \`${inner}\`;
|
|
165
|
+
const VIEW_BOX = ${JSON.stringify(icon.viewBox)};
|
|
166
|
+
|
|
167
|
+
export class ${className} extends HTMLElement {
|
|
168
|
+
static get observedAttributes() {
|
|
169
|
+
return ['size', 'label'];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
connectedCallback() {
|
|
173
|
+
this.render();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
attributeChangedCallback() {
|
|
177
|
+
this.render();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get size() {
|
|
181
|
+
return this.getAttribute('size') || '1em';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
set size(value) {
|
|
185
|
+
if (value == null) {
|
|
186
|
+
this.removeAttribute('size');
|
|
187
|
+
} else {
|
|
188
|
+
this.setAttribute('size', String(value));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
get label() {
|
|
193
|
+
return this.getAttribute('label') || '';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
set label(value) {
|
|
197
|
+
if (value == null || value === '') {
|
|
198
|
+
this.removeAttribute('label');
|
|
199
|
+
} else {
|
|
200
|
+
this.setAttribute('label', String(value));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
render() {
|
|
205
|
+
const size = this.size;
|
|
206
|
+
const label = this.label;
|
|
207
|
+
|
|
208
|
+
this.innerHTML =
|
|
209
|
+
'<svg' +
|
|
210
|
+
' part="root"' +
|
|
211
|
+
' width="' + escapeHtml(size) + '"' +
|
|
212
|
+
' height="' + escapeHtml(size) + '"' +
|
|
213
|
+
' viewBox="' + escapeHtml(VIEW_BOX) + '"' +
|
|
214
|
+
' xmlns="http://www.w3.org/2000/svg"' +
|
|
215
|
+
(label ? ' role="img" aria-label="' + escapeHtml(label) + '"' : ' aria-hidden="true"') +
|
|
216
|
+
'>' +
|
|
217
|
+
INNER_SVG +
|
|
218
|
+
'</svg>';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!customElements.get(${JSON.stringify(icon.wcTag)})) {
|
|
223
|
+
customElements.define(${JSON.stringify(icon.wcTag)}, ${className});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export const ${icon.componentName} = ${className};
|
|
227
|
+
|
|
228
|
+
function escapeHtml(value) {
|
|
229
|
+
return String(value)
|
|
230
|
+
.replace(/&/g, '&')
|
|
231
|
+
.replace(/"/g, '"')
|
|
232
|
+
.replace(/</g, '<')
|
|
233
|
+
.replace(/>/g, '>');
|
|
234
|
+
}
|
|
235
|
+
`.trimStart();
|
|
236
|
+
}
|
|
237
|
+
function generateStaticWcIndex(icons) {
|
|
238
|
+
return `${icons.map((icon) => {
|
|
239
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
240
|
+
}).join("\n")}\n`;
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region packages/web-c/output-icons/src/generateVueIcon.ts
|
|
244
|
+
function generateVueIcon(icon) {
|
|
245
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
246
|
+
return `
|
|
247
|
+
import { defineComponent, h } from 'vue';
|
|
248
|
+
|
|
249
|
+
export const ${icon.componentName} = defineComponent({
|
|
250
|
+
name: ${JSON.stringify(icon.componentName)},
|
|
251
|
+
|
|
252
|
+
props: {
|
|
253
|
+
size: {
|
|
254
|
+
type: [String, Number],
|
|
255
|
+
default: '1em',
|
|
256
|
+
},
|
|
257
|
+
title: {
|
|
258
|
+
type: String,
|
|
259
|
+
default: undefined,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
setup(props, { attrs, slots }) {
|
|
264
|
+
return () => {
|
|
265
|
+
const children = [];
|
|
266
|
+
|
|
267
|
+
if (props.title) {
|
|
268
|
+
children.push(h('title', null, props.title));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (slots.default) {
|
|
272
|
+
children.push(...slots.default());
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return h(
|
|
276
|
+
'svg',
|
|
277
|
+
{
|
|
278
|
+
...attrs,
|
|
279
|
+
width: props.size,
|
|
280
|
+
height: props.size,
|
|
281
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
282
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
283
|
+
'aria-hidden': props.title ? undefined : true,
|
|
284
|
+
role: props.title ? 'img' : undefined,
|
|
285
|
+
innerHTML: slots.default ? undefined : \`${inner}\`,
|
|
286
|
+
},
|
|
287
|
+
children,
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
`.trimStart();
|
|
293
|
+
}
|
|
294
|
+
function generateVueIndex(icons) {
|
|
295
|
+
return `${icons.map((icon) => {
|
|
296
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
297
|
+
}).join("\n")}\n`;
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region packages/web-c/output-icons/src/naming.ts
|
|
301
|
+
function toPascalCase(value) {
|
|
302
|
+
return value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("") || "Icon";
|
|
303
|
+
}
|
|
304
|
+
function toIconComponentName(name) {
|
|
305
|
+
const pascal = toPascalCase(name);
|
|
306
|
+
return pascal.endsWith("Icon") ? pascal : `${pascal}Icon`;
|
|
307
|
+
}
|
|
308
|
+
function sanitizeFileName(value) {
|
|
309
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
310
|
+
}
|
|
311
|
+
function getIconJsFileName(name) {
|
|
312
|
+
return `${sanitizeFileName(name)}.js`;
|
|
313
|
+
}
|
|
314
|
+
function getIconSvgFileName(name) {
|
|
315
|
+
return `${sanitizeFileName(name)}.svg`;
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region packages/web-c/output-icons/src/index.ts
|
|
319
|
+
function icons(options) {
|
|
320
|
+
const normalized = normalizeOptions(options);
|
|
321
|
+
return {
|
|
322
|
+
name: "zeus-output-icons",
|
|
323
|
+
virtualModules() {
|
|
324
|
+
const modules = [];
|
|
325
|
+
if (normalized.react) {
|
|
326
|
+
for (const icon of normalized.icons) modules.push({
|
|
327
|
+
id: `zeus:icons:react:${icon.name}`,
|
|
328
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, getIconJsFileName(icon.name)),
|
|
329
|
+
code: generateReactIcon(icon)
|
|
330
|
+
});
|
|
331
|
+
modules.push({
|
|
332
|
+
id: "zeus:icons:react:index",
|
|
333
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, "index.js"),
|
|
334
|
+
code: generateReactIndex(normalized.icons)
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
if (normalized.vue) {
|
|
338
|
+
for (const icon of normalized.icons) modules.push({
|
|
339
|
+
id: `zeus:icons:vue:${icon.name}`,
|
|
340
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, getIconJsFileName(icon.name)),
|
|
341
|
+
code: generateVueIcon(icon)
|
|
342
|
+
});
|
|
343
|
+
modules.push({
|
|
344
|
+
id: "zeus:icons:vue:index",
|
|
345
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, "index.js"),
|
|
346
|
+
code: generateVueIndex(normalized.icons)
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
if (normalized.wc) {
|
|
350
|
+
for (const icon of normalized.icons) modules.push({
|
|
351
|
+
id: `zeus:icons:wc:${icon.name}`,
|
|
352
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, getIconJsFileName(icon.name)),
|
|
353
|
+
code: generateStaticWcIcon(icon)
|
|
354
|
+
});
|
|
355
|
+
modules.push({
|
|
356
|
+
id: "zeus:icons:wc:index",
|
|
357
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, "index.js"),
|
|
358
|
+
code: generateStaticWcIndex(normalized.icons)
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return modules;
|
|
362
|
+
},
|
|
363
|
+
generateBundle() {
|
|
364
|
+
const files = [];
|
|
365
|
+
if (normalized.svg) for (const icon of normalized.icons) files.push({
|
|
366
|
+
type: "asset",
|
|
367
|
+
fileName: node_path.default.posix.join(normalized.outDir, "svg", getIconSvgFileName(icon.name)),
|
|
368
|
+
source: svgToDataSource(icon.svg)
|
|
369
|
+
});
|
|
370
|
+
if (normalized.dts && normalized.react) files.push({
|
|
371
|
+
type: "asset",
|
|
372
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.react.outDir, "index.d.ts"),
|
|
373
|
+
source: generateReactDts(normalized.icons)
|
|
374
|
+
});
|
|
375
|
+
if (normalized.dts && normalized.vue) files.push({
|
|
376
|
+
type: "asset",
|
|
377
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.vue.outDir, "index.d.ts"),
|
|
378
|
+
source: generateVueDts(normalized.icons)
|
|
379
|
+
});
|
|
380
|
+
if (normalized.dts && normalized.wc) files.push({
|
|
381
|
+
type: "asset",
|
|
382
|
+
fileName: node_path.default.posix.join(normalized.outDir, normalized.wc.outDir, "index.d.ts"),
|
|
383
|
+
source: generateStaticWcDts(normalized.icons)
|
|
384
|
+
});
|
|
385
|
+
return files;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function normalizeOptions(options) {
|
|
390
|
+
var _options$icons, _options$outDir, _options$svg, _options$dts;
|
|
391
|
+
if (!((_options$icons = options.icons) === null || _options$icons === void 0 ? void 0 : _options$icons.length)) throw new Error("[zeus-output-icons] options.icons is required.");
|
|
392
|
+
const wcOptions = options.wc === false ? false : {
|
|
393
|
+
outDir: typeof options.wc === "object" && options.wc.outDir ? options.wc.outDir : "wc",
|
|
394
|
+
tagPrefix: typeof options.wc === "object" && options.wc.tagPrefix ? options.wc.tagPrefix : "z-icon-"
|
|
395
|
+
};
|
|
396
|
+
return {
|
|
397
|
+
icons: normalizeIcons(options.icons, wcOptions ? wcOptions.tagPrefix : "z-icon-"),
|
|
398
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "icons",
|
|
399
|
+
svg: (_options$svg = options.svg) !== null && _options$svg !== void 0 ? _options$svg : true,
|
|
400
|
+
react: options.react === false ? false : { outDir: typeof options.react === "object" && options.react.outDir ? options.react.outDir : "react" },
|
|
401
|
+
vue: options.vue === false ? false : { outDir: typeof options.vue === "object" && options.vue.outDir ? options.vue.outDir : "vue" },
|
|
402
|
+
wc: wcOptions,
|
|
403
|
+
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function normalizeIcons(icons, tagPrefix) {
|
|
407
|
+
return icons.map((icon) => {
|
|
408
|
+
const parsed = parseSvg(icon.svg);
|
|
409
|
+
return {
|
|
410
|
+
name: icon.name,
|
|
411
|
+
componentName: toIconComponentName(icon.name),
|
|
412
|
+
wcTag: `${tagPrefix}${icon.name}`,
|
|
413
|
+
svg: icon.svg,
|
|
414
|
+
title: icon.title,
|
|
415
|
+
viewBox: parsed.viewBox,
|
|
416
|
+
innerSvg: parsed.innerSvg
|
|
417
|
+
};
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
exports.default = icons;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ZeusComponentPlugin } from '@zeus-js/bundler-plugin';
|
|
2
|
+
|
|
3
|
+
export interface IconSource {
|
|
4
|
+
/**
|
|
5
|
+
* Icon name.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
* check
|
|
9
|
+
* chevron-down
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Full svg source.
|
|
14
|
+
*/
|
|
15
|
+
svg: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional display name.
|
|
18
|
+
*/
|
|
19
|
+
title?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface OutputIconsOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Icon source list.
|
|
24
|
+
*
|
|
25
|
+
* MVP 先支持内联 icons。
|
|
26
|
+
* 后续可以扩展 from: string | string[] 读取 svg 文件。
|
|
27
|
+
*/
|
|
28
|
+
icons: IconSource[];
|
|
29
|
+
/**
|
|
30
|
+
* Output root.
|
|
31
|
+
*
|
|
32
|
+
* @default 'icons'
|
|
33
|
+
*/
|
|
34
|
+
outDir?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Emit raw svg files.
|
|
37
|
+
*
|
|
38
|
+
* @default true
|
|
39
|
+
*/
|
|
40
|
+
svg?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Emit React static icon components.
|
|
43
|
+
*
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
react?: boolean | ReactIconOutputOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Emit Vue static icon components.
|
|
49
|
+
*
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
52
|
+
vue?: boolean | VueIconOutputOptions;
|
|
53
|
+
/**
|
|
54
|
+
* Emit static custom elements.
|
|
55
|
+
*
|
|
56
|
+
* @default false
|
|
57
|
+
*/
|
|
58
|
+
wc?: boolean | StaticWcIconOutputOptions;
|
|
59
|
+
/**
|
|
60
|
+
* Whether to emit d.ts files.
|
|
61
|
+
*
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
dts?: boolean;
|
|
65
|
+
}
|
|
66
|
+
interface ReactIconOutputOptions {
|
|
67
|
+
outDir?: string;
|
|
68
|
+
}
|
|
69
|
+
interface VueIconOutputOptions {
|
|
70
|
+
outDir?: string;
|
|
71
|
+
}
|
|
72
|
+
interface StaticWcIconOutputOptions {
|
|
73
|
+
outDir?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Example:
|
|
76
|
+
* tagPrefix: 'z-icon-'
|
|
77
|
+
* check -> z-icon-check
|
|
78
|
+
*
|
|
79
|
+
* @default 'z-icon-'
|
|
80
|
+
*/
|
|
81
|
+
tagPrefix?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export declare function icons(options: OutputIconsOptions): ZeusComponentPlugin;
|
|
85
|
+
|
|
86
|
+
export { icons as default };
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* output-icons 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/output-icons/src/generateDts.ts
|
|
8
|
+
function generateReactDts(icons) {
|
|
9
|
+
const lines = [];
|
|
10
|
+
lines.push(`import type * as React from 'react'`);
|
|
11
|
+
lines.push("");
|
|
12
|
+
lines.push(`export interface IconProps extends React.SVGAttributes<SVGSVGElement> {`);
|
|
13
|
+
lines.push(` size?: string | number`);
|
|
14
|
+
lines.push(` title?: string`);
|
|
15
|
+
lines.push(`}`);
|
|
16
|
+
lines.push("");
|
|
17
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: React.ForwardRefExoticComponent<IconProps & React.RefAttributes<SVGSVGElement>>`);
|
|
18
|
+
lines.push("");
|
|
19
|
+
return lines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
function generateVueDts(icons) {
|
|
22
|
+
const lines = [];
|
|
23
|
+
lines.push(`import type { DefineComponent } from 'vue'`);
|
|
24
|
+
lines.push("");
|
|
25
|
+
lines.push(`export interface IconProps {`);
|
|
26
|
+
lines.push(` size?: string | number`);
|
|
27
|
+
lines.push(` title?: string`);
|
|
28
|
+
lines.push(`}`);
|
|
29
|
+
lines.push("");
|
|
30
|
+
for (const icon of icons) lines.push(`export declare const ${icon.componentName}: DefineComponent<IconProps>`);
|
|
31
|
+
lines.push("");
|
|
32
|
+
return lines.join("\n");
|
|
33
|
+
}
|
|
34
|
+
function generateStaticWcDts(icons) {
|
|
35
|
+
const lines = [];
|
|
36
|
+
for (const icon of icons) {
|
|
37
|
+
const className = `${icon.componentName}Element`;
|
|
38
|
+
lines.push(`export interface ${className} extends HTMLElement {`);
|
|
39
|
+
lines.push(` size?: string`);
|
|
40
|
+
lines.push(` label?: string`);
|
|
41
|
+
lines.push(`}`);
|
|
42
|
+
lines.push("");
|
|
43
|
+
lines.push(`export declare const ${icon.componentName}: {`);
|
|
44
|
+
lines.push(` new (): ${className}`);
|
|
45
|
+
lines.push(`}`);
|
|
46
|
+
lines.push("");
|
|
47
|
+
}
|
|
48
|
+
lines.push("declare global {");
|
|
49
|
+
lines.push(" interface HTMLElementTagNameMap {");
|
|
50
|
+
for (const icon of icons) lines.push(` ${JSON.stringify(icon.wcTag)}: ${icon.componentName}Element`);
|
|
51
|
+
lines.push(" }");
|
|
52
|
+
lines.push("}");
|
|
53
|
+
lines.push("");
|
|
54
|
+
lines.push("export {}");
|
|
55
|
+
lines.push("");
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region packages/web-c/output-icons/src/svg.ts
|
|
60
|
+
function parseSvg(source) {
|
|
61
|
+
var _svgMatch$, _svgMatch$2$trim, _svgMatch$2, _ref, _readAttribute;
|
|
62
|
+
const svgMatch = sanitizeSvg(source).match(/<svg\b([^>]*)>([\s\S]*?)<\/svg>/i);
|
|
63
|
+
if (!svgMatch) throw new Error("Invalid SVG source. Expected <svg>...</svg>.");
|
|
64
|
+
const attrs = (_svgMatch$ = svgMatch[1]) !== null && _svgMatch$ !== void 0 ? _svgMatch$ : "";
|
|
65
|
+
const innerSvg = (_svgMatch$2$trim = (_svgMatch$2 = svgMatch[2]) === null || _svgMatch$2 === void 0 ? void 0 : _svgMatch$2.trim()) !== null && _svgMatch$2$trim !== void 0 ? _svgMatch$2$trim : "";
|
|
66
|
+
return {
|
|
67
|
+
viewBox: (_ref = (_readAttribute = readAttribute(attrs, "viewBox")) !== null && _readAttribute !== void 0 ? _readAttribute : readAttribute(attrs, "viewbox")) !== null && _ref !== void 0 ? _ref : "0 0 24 24",
|
|
68
|
+
innerSvg
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function sanitizeSvg(source) {
|
|
72
|
+
return source.replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*\{[^}]*\}/gi, "");
|
|
73
|
+
}
|
|
74
|
+
function readAttribute(attrs, name) {
|
|
75
|
+
const doubleQuote = new RegExp(`${name}\\s*=\\s*"([^"]*)"`, "i").exec(attrs);
|
|
76
|
+
if (doubleQuote) return doubleQuote[1];
|
|
77
|
+
const singleQuote = new RegExp(`${name}\\s*=\\s*'([^']*)'`, "i").exec(attrs);
|
|
78
|
+
if (singleQuote) return singleQuote[1];
|
|
79
|
+
}
|
|
80
|
+
function escapeTemplateLiteral(value) {
|
|
81
|
+
return value.replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
82
|
+
}
|
|
83
|
+
function svgToDataSource(svg) {
|
|
84
|
+
return svg.trim();
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region packages/web-c/output-icons/src/generateReactIcon.ts
|
|
88
|
+
function generateReactIcon(icon) {
|
|
89
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
90
|
+
return `
|
|
91
|
+
import React from 'react';
|
|
92
|
+
|
|
93
|
+
export const ${icon.componentName} = React.forwardRef(function ${icon.componentName}(props, ref) {
|
|
94
|
+
const {
|
|
95
|
+
size = '1em',
|
|
96
|
+
title,
|
|
97
|
+
children,
|
|
98
|
+
...rest
|
|
99
|
+
} = props;
|
|
100
|
+
|
|
101
|
+
const content = children != null
|
|
102
|
+
? children
|
|
103
|
+
: React.createElement('g', {
|
|
104
|
+
dangerouslySetInnerHTML: { __html: \`${inner}\` },
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return React.createElement(
|
|
108
|
+
'svg',
|
|
109
|
+
{
|
|
110
|
+
...rest,
|
|
111
|
+
ref,
|
|
112
|
+
width: size,
|
|
113
|
+
height: size,
|
|
114
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
115
|
+
fill: 'none',
|
|
116
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
117
|
+
'aria-hidden': title ? undefined : true,
|
|
118
|
+
role: title ? 'img' : undefined,
|
|
119
|
+
},
|
|
120
|
+
title ? React.createElement('title', null, title) : null,
|
|
121
|
+
content,
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
`.trimStart();
|
|
125
|
+
}
|
|
126
|
+
function generateReactIndex(icons) {
|
|
127
|
+
return `${icons.map((icon) => {
|
|
128
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
129
|
+
}).join("\n")}\n`;
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region packages/web-c/output-icons/src/generateStaticWcIcon.ts
|
|
133
|
+
function generateStaticWcIcon(icon) {
|
|
134
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
135
|
+
const className = `${icon.componentName}Element`;
|
|
136
|
+
return `
|
|
137
|
+
const INNER_SVG = \`${inner}\`;
|
|
138
|
+
const VIEW_BOX = ${JSON.stringify(icon.viewBox)};
|
|
139
|
+
|
|
140
|
+
export class ${className} extends HTMLElement {
|
|
141
|
+
static get observedAttributes() {
|
|
142
|
+
return ['size', 'label'];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
connectedCallback() {
|
|
146
|
+
this.render();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
attributeChangedCallback() {
|
|
150
|
+
this.render();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get size() {
|
|
154
|
+
return this.getAttribute('size') || '1em';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
set size(value) {
|
|
158
|
+
if (value == null) {
|
|
159
|
+
this.removeAttribute('size');
|
|
160
|
+
} else {
|
|
161
|
+
this.setAttribute('size', String(value));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get label() {
|
|
166
|
+
return this.getAttribute('label') || '';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
set label(value) {
|
|
170
|
+
if (value == null || value === '') {
|
|
171
|
+
this.removeAttribute('label');
|
|
172
|
+
} else {
|
|
173
|
+
this.setAttribute('label', String(value));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
render() {
|
|
178
|
+
const size = this.size;
|
|
179
|
+
const label = this.label;
|
|
180
|
+
|
|
181
|
+
this.innerHTML =
|
|
182
|
+
'<svg' +
|
|
183
|
+
' part="root"' +
|
|
184
|
+
' width="' + escapeHtml(size) + '"' +
|
|
185
|
+
' height="' + escapeHtml(size) + '"' +
|
|
186
|
+
' viewBox="' + escapeHtml(VIEW_BOX) + '"' +
|
|
187
|
+
' xmlns="http://www.w3.org/2000/svg"' +
|
|
188
|
+
(label ? ' role="img" aria-label="' + escapeHtml(label) + '"' : ' aria-hidden="true"') +
|
|
189
|
+
'>' +
|
|
190
|
+
INNER_SVG +
|
|
191
|
+
'</svg>';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!customElements.get(${JSON.stringify(icon.wcTag)})) {
|
|
196
|
+
customElements.define(${JSON.stringify(icon.wcTag)}, ${className});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export const ${icon.componentName} = ${className};
|
|
200
|
+
|
|
201
|
+
function escapeHtml(value) {
|
|
202
|
+
return String(value)
|
|
203
|
+
.replace(/&/g, '&')
|
|
204
|
+
.replace(/"/g, '"')
|
|
205
|
+
.replace(/</g, '<')
|
|
206
|
+
.replace(/>/g, '>');
|
|
207
|
+
}
|
|
208
|
+
`.trimStart();
|
|
209
|
+
}
|
|
210
|
+
function generateStaticWcIndex(icons) {
|
|
211
|
+
return `${icons.map((icon) => {
|
|
212
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
213
|
+
}).join("\n")}\n`;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region packages/web-c/output-icons/src/generateVueIcon.ts
|
|
217
|
+
function generateVueIcon(icon) {
|
|
218
|
+
const inner = escapeTemplateLiteral(icon.innerSvg);
|
|
219
|
+
return `
|
|
220
|
+
import { defineComponent, h } from 'vue';
|
|
221
|
+
|
|
222
|
+
export const ${icon.componentName} = defineComponent({
|
|
223
|
+
name: ${JSON.stringify(icon.componentName)},
|
|
224
|
+
|
|
225
|
+
props: {
|
|
226
|
+
size: {
|
|
227
|
+
type: [String, Number],
|
|
228
|
+
default: '1em',
|
|
229
|
+
},
|
|
230
|
+
title: {
|
|
231
|
+
type: String,
|
|
232
|
+
default: undefined,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
setup(props, { attrs, slots }) {
|
|
237
|
+
return () => {
|
|
238
|
+
const children = [];
|
|
239
|
+
|
|
240
|
+
if (props.title) {
|
|
241
|
+
children.push(h('title', null, props.title));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (slots.default) {
|
|
245
|
+
children.push(...slots.default());
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return h(
|
|
249
|
+
'svg',
|
|
250
|
+
{
|
|
251
|
+
...attrs,
|
|
252
|
+
width: props.size,
|
|
253
|
+
height: props.size,
|
|
254
|
+
viewBox: ${JSON.stringify(icon.viewBox)},
|
|
255
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
256
|
+
'aria-hidden': props.title ? undefined : true,
|
|
257
|
+
role: props.title ? 'img' : undefined,
|
|
258
|
+
innerHTML: slots.default ? undefined : \`${inner}\`,
|
|
259
|
+
},
|
|
260
|
+
children,
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
`.trimStart();
|
|
266
|
+
}
|
|
267
|
+
function generateVueIndex(icons) {
|
|
268
|
+
return `${icons.map((icon) => {
|
|
269
|
+
return `export { ${icon.componentName} } from './${icon.name}.js';`;
|
|
270
|
+
}).join("\n")}\n`;
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region packages/web-c/output-icons/src/naming.ts
|
|
274
|
+
function toPascalCase(value) {
|
|
275
|
+
return value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("") || "Icon";
|
|
276
|
+
}
|
|
277
|
+
function toIconComponentName(name) {
|
|
278
|
+
const pascal = toPascalCase(name);
|
|
279
|
+
return pascal.endsWith("Icon") ? pascal : `${pascal}Icon`;
|
|
280
|
+
}
|
|
281
|
+
function sanitizeFileName(value) {
|
|
282
|
+
return value.trim().replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
283
|
+
}
|
|
284
|
+
function getIconJsFileName(name) {
|
|
285
|
+
return `${sanitizeFileName(name)}.js`;
|
|
286
|
+
}
|
|
287
|
+
function getIconSvgFileName(name) {
|
|
288
|
+
return `${sanitizeFileName(name)}.svg`;
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region packages/web-c/output-icons/src/index.ts
|
|
292
|
+
function icons(options) {
|
|
293
|
+
const normalized = normalizeOptions(options);
|
|
294
|
+
return {
|
|
295
|
+
name: "zeus-output-icons",
|
|
296
|
+
virtualModules() {
|
|
297
|
+
const modules = [];
|
|
298
|
+
if (normalized.react) {
|
|
299
|
+
for (const icon of normalized.icons) modules.push({
|
|
300
|
+
id: `zeus:icons:react:${icon.name}`,
|
|
301
|
+
fileName: path.posix.join(normalized.outDir, normalized.react.outDir, getIconJsFileName(icon.name)),
|
|
302
|
+
code: generateReactIcon(icon)
|
|
303
|
+
});
|
|
304
|
+
modules.push({
|
|
305
|
+
id: "zeus:icons:react:index",
|
|
306
|
+
fileName: path.posix.join(normalized.outDir, normalized.react.outDir, "index.js"),
|
|
307
|
+
code: generateReactIndex(normalized.icons)
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
if (normalized.vue) {
|
|
311
|
+
for (const icon of normalized.icons) modules.push({
|
|
312
|
+
id: `zeus:icons:vue:${icon.name}`,
|
|
313
|
+
fileName: path.posix.join(normalized.outDir, normalized.vue.outDir, getIconJsFileName(icon.name)),
|
|
314
|
+
code: generateVueIcon(icon)
|
|
315
|
+
});
|
|
316
|
+
modules.push({
|
|
317
|
+
id: "zeus:icons:vue:index",
|
|
318
|
+
fileName: path.posix.join(normalized.outDir, normalized.vue.outDir, "index.js"),
|
|
319
|
+
code: generateVueIndex(normalized.icons)
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
if (normalized.wc) {
|
|
323
|
+
for (const icon of normalized.icons) modules.push({
|
|
324
|
+
id: `zeus:icons:wc:${icon.name}`,
|
|
325
|
+
fileName: path.posix.join(normalized.outDir, normalized.wc.outDir, getIconJsFileName(icon.name)),
|
|
326
|
+
code: generateStaticWcIcon(icon)
|
|
327
|
+
});
|
|
328
|
+
modules.push({
|
|
329
|
+
id: "zeus:icons:wc:index",
|
|
330
|
+
fileName: path.posix.join(normalized.outDir, normalized.wc.outDir, "index.js"),
|
|
331
|
+
code: generateStaticWcIndex(normalized.icons)
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
return modules;
|
|
335
|
+
},
|
|
336
|
+
generateBundle() {
|
|
337
|
+
const files = [];
|
|
338
|
+
if (normalized.svg) for (const icon of normalized.icons) files.push({
|
|
339
|
+
type: "asset",
|
|
340
|
+
fileName: path.posix.join(normalized.outDir, "svg", getIconSvgFileName(icon.name)),
|
|
341
|
+
source: svgToDataSource(icon.svg)
|
|
342
|
+
});
|
|
343
|
+
if (normalized.dts && normalized.react) files.push({
|
|
344
|
+
type: "asset",
|
|
345
|
+
fileName: path.posix.join(normalized.outDir, normalized.react.outDir, "index.d.ts"),
|
|
346
|
+
source: generateReactDts(normalized.icons)
|
|
347
|
+
});
|
|
348
|
+
if (normalized.dts && normalized.vue) files.push({
|
|
349
|
+
type: "asset",
|
|
350
|
+
fileName: path.posix.join(normalized.outDir, normalized.vue.outDir, "index.d.ts"),
|
|
351
|
+
source: generateVueDts(normalized.icons)
|
|
352
|
+
});
|
|
353
|
+
if (normalized.dts && normalized.wc) files.push({
|
|
354
|
+
type: "asset",
|
|
355
|
+
fileName: path.posix.join(normalized.outDir, normalized.wc.outDir, "index.d.ts"),
|
|
356
|
+
source: generateStaticWcDts(normalized.icons)
|
|
357
|
+
});
|
|
358
|
+
return files;
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
function normalizeOptions(options) {
|
|
363
|
+
var _options$icons, _options$outDir, _options$svg, _options$dts;
|
|
364
|
+
if (!((_options$icons = options.icons) === null || _options$icons === void 0 ? void 0 : _options$icons.length)) throw new Error("[zeus-output-icons] options.icons is required.");
|
|
365
|
+
const wcOptions = options.wc === false ? false : {
|
|
366
|
+
outDir: typeof options.wc === "object" && options.wc.outDir ? options.wc.outDir : "wc",
|
|
367
|
+
tagPrefix: typeof options.wc === "object" && options.wc.tagPrefix ? options.wc.tagPrefix : "z-icon-"
|
|
368
|
+
};
|
|
369
|
+
return {
|
|
370
|
+
icons: normalizeIcons(options.icons, wcOptions ? wcOptions.tagPrefix : "z-icon-"),
|
|
371
|
+
outDir: (_options$outDir = options.outDir) !== null && _options$outDir !== void 0 ? _options$outDir : "icons",
|
|
372
|
+
svg: (_options$svg = options.svg) !== null && _options$svg !== void 0 ? _options$svg : true,
|
|
373
|
+
react: options.react === false ? false : { outDir: typeof options.react === "object" && options.react.outDir ? options.react.outDir : "react" },
|
|
374
|
+
vue: options.vue === false ? false : { outDir: typeof options.vue === "object" && options.vue.outDir ? options.vue.outDir : "vue" },
|
|
375
|
+
wc: wcOptions,
|
|
376
|
+
dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function normalizeIcons(icons, tagPrefix) {
|
|
380
|
+
return icons.map((icon) => {
|
|
381
|
+
const parsed = parseSvg(icon.svg);
|
|
382
|
+
return {
|
|
383
|
+
name: icon.name,
|
|
384
|
+
componentName: toIconComponentName(icon.name),
|
|
385
|
+
wcTag: `${tagPrefix}${icon.name}`,
|
|
386
|
+
svg: icon.svg,
|
|
387
|
+
title: icon.title,
|
|
388
|
+
viewBox: parsed.viewBox,
|
|
389
|
+
innerSvg: parsed.innerSvg
|
|
390
|
+
};
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
export { icons as default };
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zeus-js/output-icons",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "No-runtime icon output plugin for Zeus component compiler host",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "dist/output-icons.esm-bundler.js",
|
|
8
|
+
"types": "dist/output-icons.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/output-icons.d.ts",
|
|
16
|
+
"node": {
|
|
17
|
+
"production": "./dist/output-icons.cjs.prod.js",
|
|
18
|
+
"development": "./dist/output-icons.cjs.js",
|
|
19
|
+
"default": "./index.js"
|
|
20
|
+
},
|
|
21
|
+
"module": "./dist/output-icons.esm-bundler.js",
|
|
22
|
+
"import": "./dist/output-icons.esm-bundler.js",
|
|
23
|
+
"require": "./index.js"
|
|
24
|
+
},
|
|
25
|
+
"./*": "./*"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/baicie/zeus"
|
|
31
|
+
},
|
|
32
|
+
"buildOptions": {
|
|
33
|
+
"name": "ZeusOutputIcons",
|
|
34
|
+
"formats": [
|
|
35
|
+
"esm-bundler",
|
|
36
|
+
"cjs"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@zeus-js/bundler-plugin": "0.1.0-beta.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": ">=18 || >=19",
|
|
44
|
+
"vue": ">=3"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"react": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"vue": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"zeus",
|
|
56
|
+
"icons",
|
|
57
|
+
"web-components",
|
|
58
|
+
"react",
|
|
59
|
+
"vue"
|
|
60
|
+
],
|
|
61
|
+
"author": "Baicie",
|
|
62
|
+
"license": "MIT"
|
|
63
|
+
}
|