@number10/phaserjsx 0.6.1 ā 4.0.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/README.md +13 -3
- package/dist/clip/stencil-clip.d.ts +86 -0
- package/dist/clip/stencil-clip.d.ts.map +1 -0
- package/dist/components/appliers/applyGestures.d.ts.map +1 -1
- package/dist/components/creators/createGestures.d.ts.map +1 -1
- package/dist/components/custom/CharText/CharText.d.ts.map +1 -1
- package/dist/components/custom/Dialog.d.ts +1 -1
- package/dist/components/custom/Divider.d.ts +1 -1
- package/dist/components/custom/Graphics.d.ts +1 -1
- package/dist/components/custom/Graphics.d.ts.map +1 -1
- package/dist/components/custom/Icon.d.ts.map +1 -1
- package/dist/components/custom/Image.d.ts.map +1 -1
- package/dist/components/custom/Joystick.d.ts +1 -1
- package/dist/components/custom/NineSlice.d.ts.map +1 -1
- package/dist/components/custom/Particles.d.ts +1 -1
- package/dist/components/custom/Particles.d.ts.map +1 -1
- package/dist/components/custom/Portal.d.ts.map +1 -1
- package/dist/components/custom/RefOriginView.d.ts +1 -1
- package/dist/components/custom/ScrollView.d.ts.map +1 -1
- package/dist/components/custom/Sprite.d.ts +1 -1
- package/dist/components/custom/Sprite.d.ts.map +1 -1
- package/dist/components/custom/Text.d.ts.map +1 -1
- package/dist/components/custom/TileSprite.d.ts +1 -1
- package/dist/components/custom/TileSprite.d.ts.map +1 -1
- package/dist/components/custom/View.d.ts.map +1 -1
- package/dist/components/custom/index.cjs +34 -36
- package/dist/components/custom/index.js +2 -37
- package/dist/components/primitives/graphics.d.ts.map +1 -1
- package/dist/components/primitives/image.d.ts.map +1 -1
- package/dist/components/primitives/nineslice.d.ts.map +1 -1
- package/dist/components/primitives/particles.d.ts.map +1 -1
- package/dist/components/primitives/sprite.d.ts.map +1 -1
- package/dist/components/primitives/text.d.ts.map +1 -1
- package/dist/components/primitives/tilesprite.d.ts.map +1 -1
- package/dist/components/primitives/view.d.ts.map +1 -1
- package/dist/custom-BN31OAJq.cjs +30826 -0
- package/dist/custom-BN31OAJq.cjs.map +1 -0
- package/dist/custom-oy3mBnrW.js +29562 -0
- package/dist/custom-oy3mBnrW.js.map +1 -0
- package/dist/fx/fx-creators/blur.d.ts.map +1 -1
- package/dist/fx/fx-creators/color-matrix.d.ts.map +1 -1
- package/dist/fx/fx-creators/glow.d.ts.map +1 -1
- package/dist/fx/fx-creators/pixelate.d.ts.map +1 -1
- package/dist/fx/fx-creators/shadow.d.ts.map +1 -1
- package/dist/fx/fx-creators/vignette.d.ts.map +1 -1
- package/dist/fx/use-fx.d.ts +3 -3
- package/dist/fx/use-fx.d.ts.map +1 -1
- package/dist/gestures/gesture-manager.d.ts +3 -1
- package/dist/gestures/gesture-manager.d.ts.map +1 -1
- package/dist/gestures/gesture-types.d.ts +1 -1
- package/dist/gestures/gesture-types.d.ts.map +1 -1
- package/dist/index.cjs +1547 -2837
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1356 -2866
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.cjs +12 -7
- package/dist/jsx-dev-runtime.cjs.map +1 -1
- package/dist/jsx-dev-runtime.js +11 -11
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.cjs +55 -33
- package/dist/jsx-runtime.cjs.map +1 -1
- package/dist/jsx-runtime.js +56 -37
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/layout/layout-engine.d.ts.map +1 -1
- package/dist/scripts/generate-icon-loaders.js +146 -143
- package/dist/scripts/generate-icon-types.js +94 -83
- package/dist/scripts/generate-icons.d.ts +1 -2
- package/dist/scripts/generate-icons.d.ts.map +1 -1
- package/dist/scripts/generate-icons.js +381 -399
- package/dist/scripts/icon-generator-config.d.ts +0 -1
- package/dist/scripts/icon-generator-config.js +7 -4
- package/dist/theme-base.d.ts.map +1 -1
- package/dist/vite-plugin-icons.d.ts +1 -2
- package/dist/vite-plugin-icons.js +109 -90
- package/package.json +24 -22
- package/dist/TransformOriginView-Dw_HKnFH.cjs +0 -17116
- package/dist/TransformOriginView-Dw_HKnFH.cjs.map +0 -1
- package/dist/TransformOriginView-i8uVBHb1.js +0 -17100
- package/dist/TransformOriginView-i8uVBHb1.js.map +0 -1
- package/dist/components/custom/index.cjs.map +0 -1
- package/dist/components/custom/index.js.map +0 -1
|
@@ -1,144 +1,146 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { watch } from "node:fs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { access, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
|
-
|
|
7
|
+
//#region src/scripts/generate-icons.ts
|
|
8
|
+
/**
|
|
9
|
+
* Unified icon generator
|
|
10
|
+
* Can generate types and/or loaders based on configuration
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* generate-icons --config ./icon-generator.config.ts
|
|
14
|
+
* generate-icons --types-only
|
|
15
|
+
* generate-icons --loaders-only
|
|
16
|
+
* generate-icons --config ./icon-generator.config.ts --watch
|
|
17
|
+
*/
|
|
18
|
+
var TS_CONFIG_EXTENSIONS = new Set([
|
|
19
|
+
".ts",
|
|
20
|
+
".mts",
|
|
21
|
+
".cts",
|
|
22
|
+
".tsx"
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* Find icon package in node_modules
|
|
26
|
+
*/
|
|
8
27
|
async function findIconPackage(packageName, cwd) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
const standardPath = join(cwd, "node_modules", packageName);
|
|
23
|
-
if (fs.existsSync(standardPath)) {
|
|
24
|
-
return standardPath;
|
|
25
|
-
}
|
|
26
|
-
throw new Error(`Could not find package: ${packageName}`);
|
|
28
|
+
const fs = await import("node:fs");
|
|
29
|
+
const pnpmBase = join(cwd, "node_modules/.pnpm");
|
|
30
|
+
if (fs.existsSync(pnpmBase)) {
|
|
31
|
+
const entries = await readdir(pnpmBase);
|
|
32
|
+
for (const entry of entries) if (entry.startsWith(`${packageName}@`)) {
|
|
33
|
+
const packagePath = join(pnpmBase, entry, "node_modules", packageName);
|
|
34
|
+
if (fs.existsSync(packagePath)) return packagePath;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const standardPath = join(cwd, "node_modules", packageName);
|
|
38
|
+
if (fs.existsSync(standardPath)) return standardPath;
|
|
39
|
+
throw new Error(`Could not find package: ${packageName}`);
|
|
27
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Recursively find all TypeScript files
|
|
43
|
+
*/
|
|
28
44
|
async function findTsFiles(dir, exclude = []) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return files;
|
|
45
|
+
const files = [];
|
|
46
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
const fullPath = join(dir, entry.name);
|
|
49
|
+
if (exclude.some((pattern) => fullPath.includes(pattern))) continue;
|
|
50
|
+
if (entry.isDirectory()) {
|
|
51
|
+
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
52
|
+
files.push(...await findTsFiles(fullPath, exclude));
|
|
53
|
+
} else if (entry.isFile() && /\.(tsx?|jsx?)$/.test(entry.name)) files.push(fullPath);
|
|
54
|
+
}
|
|
55
|
+
return files;
|
|
42
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Extract icon names from file content
|
|
59
|
+
*/
|
|
43
60
|
function extractIconNames(content, componentNames, customPatterns) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
while ((match = iconPropPattern.exec(content)) !== null) {
|
|
66
|
-
if (match[1]) {
|
|
67
|
-
iconNames.add(match[1]);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (customPatterns) {
|
|
71
|
-
for (const customPattern of customPatterns) {
|
|
72
|
-
const pattern = new RegExp(customPattern.pattern, "g");
|
|
73
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
74
|
-
const iconName = match[customPattern.captureGroup];
|
|
75
|
-
if (iconName) {
|
|
76
|
-
iconNames.add(iconName);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return iconNames;
|
|
61
|
+
const iconNames = /* @__PURE__ */ new Set();
|
|
62
|
+
let match;
|
|
63
|
+
for (const componentName of componentNames) {
|
|
64
|
+
const typePattern = new RegExp(`<${componentName}\\s+[^>]*type=(?:["']([^"']+)["']|\\{["']([^"']+)["']\\})`, "g");
|
|
65
|
+
while ((match = typePattern.exec(content)) !== null) {
|
|
66
|
+
const iconName = match[1] || match[2];
|
|
67
|
+
if (iconName) iconNames.add(iconName);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const themedPattern = /themed\.(\w*[Ii]con)\s*\?\?\s*["']([^"']+)["']/g;
|
|
71
|
+
while ((match = themedPattern.exec(content)) !== null) if (match[2]) iconNames.add(match[2]);
|
|
72
|
+
const iconPropPattern = /(?:icon|iconType):\s*["']([^"']+)["']/g;
|
|
73
|
+
while ((match = iconPropPattern.exec(content)) !== null) if (match[1]) iconNames.add(match[1]);
|
|
74
|
+
if (customPatterns) for (const customPattern of customPatterns) {
|
|
75
|
+
const pattern = new RegExp(customPattern.pattern, "g");
|
|
76
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
77
|
+
const iconName = match[customPattern.captureGroup];
|
|
78
|
+
if (iconName) iconNames.add(iconName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return iconNames;
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Load available icons from types file
|
|
85
|
+
*/
|
|
83
86
|
async function loadAvailableIcons(typesFile) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
} catch {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
87
|
+
try {
|
|
88
|
+
const match = (await readFile(typesFile, "utf-8")).match(/(?:export\s+)?type\s+\w+\s*=\s*([\s\S]+?)(?=\n\nexport|\n\/\/|$)/s);
|
|
89
|
+
if (!match?.[1]) return null;
|
|
90
|
+
const typeContent = match[1];
|
|
91
|
+
const icons = /* @__PURE__ */ new Set();
|
|
92
|
+
const iconPattern = /'([^']+)'/g;
|
|
93
|
+
let iconMatch;
|
|
94
|
+
while ((iconMatch = iconPattern.exec(typeContent)) !== null) {
|
|
95
|
+
const iconName = iconMatch[1];
|
|
96
|
+
if (iconName) icons.add(iconName);
|
|
97
|
+
}
|
|
98
|
+
return icons;
|
|
99
|
+
} catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate icon types
|
|
105
|
+
* Exported for use by Vite plugin
|
|
106
|
+
*/
|
|
103
107
|
async function generateTypes(config, cwd) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const sourceList = sourceInfos.length === 1 && sourceInfos[0] ? sourceInfos[0].name : sourceInfos.map((s) => `${s.name} (${s.count})`).join(", ");
|
|
139
|
-
const output = `/**
|
|
108
|
+
if (!config.types?.enabled) return null;
|
|
109
|
+
console.log("\nš Generating icon types...");
|
|
110
|
+
const sources = Array.isArray(config.source) ? config.source : [config.source];
|
|
111
|
+
const allIconNames = [];
|
|
112
|
+
const sourceInfos = [];
|
|
113
|
+
const sourceIconSets = /* @__PURE__ */ new Map();
|
|
114
|
+
for (let i = 0; i < sources.length; i++) {
|
|
115
|
+
const source = sources[i];
|
|
116
|
+
if (!source) continue;
|
|
117
|
+
let iconsDir;
|
|
118
|
+
let sourceName;
|
|
119
|
+
if (source.directory) {
|
|
120
|
+
iconsDir = resolve(cwd, source.directory);
|
|
121
|
+
sourceName = source.label || source.directory;
|
|
122
|
+
console.log(`š Scanning directory: ${source.directory}`);
|
|
123
|
+
} else if (source.package) {
|
|
124
|
+
iconsDir = join(await findIconPackage(source.package, cwd), source.iconsPath || "icons");
|
|
125
|
+
sourceName = source.label || source.package;
|
|
126
|
+
console.log(`š¦ Scanning package: ${source.package}`);
|
|
127
|
+
} else throw new Error("Either source.package or source.directory must be specified");
|
|
128
|
+
const iconNames = (await readdir(iconsDir)).filter((file) => file.endsWith(".svg")).map((file) => basename(file, ".svg"));
|
|
129
|
+
console.log(`ā Found ${iconNames.length} icons from ${sourceName}`);
|
|
130
|
+
allIconNames.push(...iconNames);
|
|
131
|
+
sourceInfos.push({
|
|
132
|
+
name: sourceName,
|
|
133
|
+
count: iconNames.length
|
|
134
|
+
});
|
|
135
|
+
sourceIconSets.set(i, new Set(iconNames));
|
|
136
|
+
}
|
|
137
|
+
const uniqueIconNames = [...new Set(allIconNames)].sort();
|
|
138
|
+
console.log(`ā Total unique icons: ${uniqueIconNames.length}`);
|
|
139
|
+
const typeDefinition = uniqueIconNames.map((name) => ` | '${name}'`).join("\n");
|
|
140
|
+
const typeName = config.types.typeName || "IconType";
|
|
141
|
+
const output = `/**
|
|
140
142
|
* Auto-generated icon type definitions
|
|
141
|
-
* Sources: ${
|
|
143
|
+
* Sources: ${sourceInfos.length === 1 && sourceInfos[0] ? sourceInfos[0].name : sourceInfos.map((s) => `${s.name} (${s.count})`).join(", ")}
|
|
142
144
|
* Total unique icons: ${uniqueIconNames.length}
|
|
143
145
|
*
|
|
144
146
|
* @generated by @number10/phaserjsx/generate-icons
|
|
@@ -152,158 +154,134 @@ async function generateTypes(config, cwd) {
|
|
|
152
154
|
export type ${typeName} =
|
|
153
155
|
${typeDefinition}
|
|
154
156
|
`;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
const outputPath = resolve(cwd, config.types.output);
|
|
158
|
+
await writeFile(outputPath, output, "utf-8");
|
|
159
|
+
console.log(`ā Generated: ${outputPath}`);
|
|
160
|
+
console.log(`ā Type name: ${typeName}`);
|
|
161
|
+
return {
|
|
162
|
+
iconNames: uniqueIconNames,
|
|
163
|
+
sourceIconSets
|
|
164
|
+
};
|
|
160
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Scan icon sources without generating the types file
|
|
168
|
+
* Used by Vite plugin to get sourceIconSets for loader generation without full type regeneration
|
|
169
|
+
* @param config - Icon generator configuration
|
|
170
|
+
* @param cwd - Current working directory
|
|
171
|
+
* @returns Icon names and source mapping
|
|
172
|
+
*/
|
|
161
173
|
async function scanIconSources(config, cwd) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
sourceIconSets.set(i, new Set(iconNames));
|
|
181
|
-
}
|
|
182
|
-
const uniqueIconNames = [...new Set(allIconNames)].sort();
|
|
183
|
-
return { iconNames: uniqueIconNames, sourceIconSets };
|
|
174
|
+
const sources = Array.isArray(config.source) ? config.source : [config.source];
|
|
175
|
+
const allIconNames = [];
|
|
176
|
+
const sourceIconSets = /* @__PURE__ */ new Map();
|
|
177
|
+
for (let i = 0; i < sources.length; i++) {
|
|
178
|
+
const source = sources[i];
|
|
179
|
+
if (!source) continue;
|
|
180
|
+
let iconsDir;
|
|
181
|
+
if (source.directory) iconsDir = resolve(cwd, source.directory);
|
|
182
|
+
else if (source.package) iconsDir = join(await findIconPackage(source.package, cwd), source.iconsPath || "icons");
|
|
183
|
+
else throw new Error("Either source.package or source.directory must be specified");
|
|
184
|
+
const iconNames = (await readdir(iconsDir)).filter((file) => file.endsWith(".svg")).map((file) => basename(file, ".svg"));
|
|
185
|
+
allIconNames.push(...iconNames);
|
|
186
|
+
sourceIconSets.set(i, new Set(iconNames));
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
iconNames: [...new Set(allIconNames)].sort(),
|
|
190
|
+
sourceIconSets
|
|
191
|
+
};
|
|
184
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Generate icon loaders
|
|
195
|
+
* Exported for use by Vite plugin
|
|
196
|
+
*/
|
|
185
197
|
async function generateLoaders(config, cwd, typesResult) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
iconPath = `${dirPath}/${icon}.svg`;
|
|
274
|
-
try {
|
|
275
|
-
const fullPath = resolve(cwd, dirPath, `${icon}.svg`);
|
|
276
|
-
await access(fullPath);
|
|
277
|
-
exists = true;
|
|
278
|
-
} catch {
|
|
279
|
-
exists = false;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
if (exists && iconPath) {
|
|
283
|
-
if (source.directory && config.loaders.output) {
|
|
284
|
-
const loaderDir = dirname(resolve(cwd, config.loaders.output));
|
|
285
|
-
const iconAbsPath = resolve(cwd, iconPath);
|
|
286
|
-
iconPath = relative(loaderDir, iconAbsPath);
|
|
287
|
-
iconPath = "./" + iconPath.replace(/\\/g, "/");
|
|
288
|
-
}
|
|
289
|
-
iconSourceMap.set(icon, {
|
|
290
|
-
path: iconPath,
|
|
291
|
-
isPackage: !!source.package
|
|
292
|
-
});
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
const loaderEntries = Array.from(iconSourceMap.entries()).map(([icon, { path, isPackage }]) => {
|
|
299
|
-
if (isPackage) {
|
|
300
|
-
return ` '${icon}': () => import('${path}?raw'),`;
|
|
301
|
-
} else {
|
|
302
|
-
return ` '${icon}': () => import('${path}?raw'),`;
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
const loaders = loaderEntries.join("\n");
|
|
306
|
-
const outputContent = `/**
|
|
198
|
+
if (!config.loaders?.enabled) return;
|
|
199
|
+
console.log("\nā” Generating icon loaders...");
|
|
200
|
+
const scanDir = resolve(cwd, config.loaders.scanDir);
|
|
201
|
+
const componentNames = config.loaders.componentNames || ["Icon"];
|
|
202
|
+
console.log(`š Scanning directory: ${scanDir}`);
|
|
203
|
+
console.log(`š Looking for components: ${componentNames.join(", ")}`);
|
|
204
|
+
let availableIconsSet = null;
|
|
205
|
+
let sourceIconSets = null;
|
|
206
|
+
if (typesResult) {
|
|
207
|
+
availableIconsSet = new Set(typesResult.iconNames);
|
|
208
|
+
sourceIconSets = typesResult.sourceIconSets;
|
|
209
|
+
console.log(`ā Loaded ${availableIconsSet.size} available icons for validation`);
|
|
210
|
+
} else if (config.loaders.validate && config.types?.output) {
|
|
211
|
+
availableIconsSet = await loadAvailableIcons(resolve(cwd, config.types.output));
|
|
212
|
+
if (availableIconsSet) console.log(`ā Loaded ${availableIconsSet.size} available icons for validation`);
|
|
213
|
+
}
|
|
214
|
+
const files = await findTsFiles(scanDir, config.exclude);
|
|
215
|
+
console.log(`š Found ${files.length} TypeScript files`);
|
|
216
|
+
const allIconNames = /* @__PURE__ */ new Set();
|
|
217
|
+
for (const file of files) extractIconNames(await readFile(file, "utf-8"), componentNames, config.customPatterns).forEach((icon) => allIconNames.add(icon));
|
|
218
|
+
let iconArray = Array.from(allIconNames).sort();
|
|
219
|
+
if (availableIconsSet) {
|
|
220
|
+
const invalidIcons = iconArray.filter((icon) => !availableIconsSet.has(icon));
|
|
221
|
+
if (invalidIcons.length > 0) {
|
|
222
|
+
console.warn(`ā ļø Found ${invalidIcons.length} icons not in types file:`);
|
|
223
|
+
console.warn(` ${invalidIcons.slice(0, 5).join(", ")}${invalidIcons.length > 5 ? "..." : ""}`);
|
|
224
|
+
}
|
|
225
|
+
iconArray = iconArray.filter((icon) => availableIconsSet.has(icon));
|
|
226
|
+
}
|
|
227
|
+
console.log(`ā Found ${iconArray.length} unique icons`);
|
|
228
|
+
if (iconArray.length > 0) console.log(` Icons: ${iconArray.slice(0, 10).join(", ")}${iconArray.length > 10 ? "..." : ""}`);
|
|
229
|
+
const sources = Array.isArray(config.source) ? config.source : [config.source];
|
|
230
|
+
const iconSourceMap = /* @__PURE__ */ new Map();
|
|
231
|
+
for (const icon of iconArray) if (sourceIconSets) for (let i = 0; i < sources.length; i++) {
|
|
232
|
+
const source = sources[i];
|
|
233
|
+
const iconsForThisSource = sourceIconSets.get(i);
|
|
234
|
+
if (!source || !iconsForThisSource) continue;
|
|
235
|
+
if (iconsForThisSource.has(icon)) {
|
|
236
|
+
let iconPath = "";
|
|
237
|
+
if (source.package) iconPath = `${source.package}/${source.iconsPath || "icons"}/${icon}.svg`;
|
|
238
|
+
else if (source.directory) iconPath = `${source.directory}/${icon}.svg`;
|
|
239
|
+
if (iconPath) {
|
|
240
|
+
if (source.directory && config.loaders.output) {
|
|
241
|
+
iconPath = relative(dirname(resolve(cwd, config.loaders.output)), resolve(cwd, iconPath));
|
|
242
|
+
iconPath = "./" + iconPath.replace(/\\/g, "/");
|
|
243
|
+
}
|
|
244
|
+
iconSourceMap.set(icon, {
|
|
245
|
+
path: iconPath,
|
|
246
|
+
isPackage: !!source.package
|
|
247
|
+
});
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else for (const source of sources) {
|
|
253
|
+
let iconPath = "";
|
|
254
|
+
let exists = false;
|
|
255
|
+
if (source.package) {
|
|
256
|
+
iconPath = `${source.package}/${source.iconsPath || "icons"}/${icon}.svg`;
|
|
257
|
+
exists = availableIconsSet ? availableIconsSet.has(icon) : true;
|
|
258
|
+
} else if (source.directory) {
|
|
259
|
+
const dirPath = source.directory;
|
|
260
|
+
iconPath = `${dirPath}/${icon}.svg`;
|
|
261
|
+
try {
|
|
262
|
+
await access(resolve(cwd, dirPath, `${icon}.svg`));
|
|
263
|
+
exists = true;
|
|
264
|
+
} catch {
|
|
265
|
+
exists = false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (exists && iconPath) {
|
|
269
|
+
if (source.directory && config.loaders.output) {
|
|
270
|
+
iconPath = relative(dirname(resolve(cwd, config.loaders.output)), resolve(cwd, iconPath));
|
|
271
|
+
iconPath = "./" + iconPath.replace(/\\/g, "/");
|
|
272
|
+
}
|
|
273
|
+
iconSourceMap.set(icon, {
|
|
274
|
+
path: iconPath,
|
|
275
|
+
isPackage: !!source.package
|
|
276
|
+
});
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const loaders = Array.from(iconSourceMap.entries()).map(([icon, { path, isPackage }]) => {
|
|
281
|
+
if (isPackage) return ` '${icon}': () => import('${path}?raw'),`;
|
|
282
|
+
else return ` '${icon}': () => import('${path}?raw'),`;
|
|
283
|
+
}).join("\n");
|
|
284
|
+
const outputContent = `/**
|
|
307
285
|
* Auto-generated icon loaders
|
|
308
286
|
* Generated by scanning: ${config.loaders.scanDir}
|
|
309
287
|
*
|
|
@@ -315,104 +293,109 @@ export const iconLoaders: Record<string, IconLoaderFn> = {
|
|
|
315
293
|
${loaders}
|
|
316
294
|
}
|
|
317
295
|
`;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
296
|
+
const outputPath = resolve(cwd, config.loaders.output);
|
|
297
|
+
await writeFile(outputPath, outputContent, "utf-8");
|
|
298
|
+
console.log(`ā Generated: ${outputPath}`);
|
|
299
|
+
console.log(`ā Registered ${iconArray.length} icon loaders`);
|
|
322
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Load config file
|
|
303
|
+
*/
|
|
304
|
+
/**
|
|
305
|
+
* Load icon generator config file
|
|
306
|
+
* Exported for use by Vite plugin and other tools
|
|
307
|
+
*/
|
|
323
308
|
async function loadConfig(configPath, cwd = process.cwd()) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
throw new Error(`Failed to load config from ${configPath}: ${errorMessage}`);
|
|
346
|
-
}
|
|
309
|
+
const absolutePath = resolve(cwd, configPath);
|
|
310
|
+
const fileUrl = pathToFileURL(absolutePath).href;
|
|
311
|
+
const extension = extname(absolutePath).toLowerCase();
|
|
312
|
+
try {
|
|
313
|
+
const module = await import(fileUrl);
|
|
314
|
+
return module.default || module;
|
|
315
|
+
} catch (error) {
|
|
316
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
317
|
+
if (TS_CONFIG_EXTENSIONS.has(extension) || errorMessage.includes("Unknown file extension")) try {
|
|
318
|
+
const { tsImport } = await import("tsx/esm/api");
|
|
319
|
+
const module = await tsImport(fileUrl, import.meta.url);
|
|
320
|
+
return module.default || module;
|
|
321
|
+
} catch (tsxError) {
|
|
322
|
+
const tsxMessage = tsxError instanceof Error ? tsxError.message : String(tsxError);
|
|
323
|
+
throw new Error(`Failed to load config from ${configPath}: ${tsxMessage} (after tsx fallback)`, { cause: tsxError });
|
|
324
|
+
}
|
|
325
|
+
throw new Error(`Failed to load config from ${configPath}: ${errorMessage}`, { cause: error });
|
|
326
|
+
}
|
|
347
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Run generation with config
|
|
330
|
+
*/
|
|
348
331
|
async function runGeneration(config, cwd) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
console.log("\n⨠Done!\n");
|
|
332
|
+
console.log("šØ Icon Generator");
|
|
333
|
+
console.log("ā".repeat(50));
|
|
334
|
+
await generateLoaders(config, cwd, await generateTypes(config, cwd) || void 0);
|
|
335
|
+
console.log("\n⨠Done!\n");
|
|
354
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Watch mode - monitor files and regenerate on changes
|
|
339
|
+
*/
|
|
355
340
|
async function watchMode(config, cwd) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
console.log(`š ${eventType}: ${filename}`);
|
|
392
|
-
scheduleRegenerate();
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
watcher.on("error", (error) => {
|
|
396
|
-
console.error(`ā Watch error for ${dir}:`, error);
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
console.log(`š Watching ${watchDirs.size} directories`);
|
|
400
|
-
console.log("Press Ctrl+C to stop\n");
|
|
401
|
-
await new Promise(() => {
|
|
402
|
-
});
|
|
341
|
+
console.log("šļø Watch mode enabled");
|
|
342
|
+
console.log("š Monitoring for changes...\n");
|
|
343
|
+
await runGeneration(config, cwd);
|
|
344
|
+
const watchDirs = /* @__PURE__ */ new Set();
|
|
345
|
+
if (config.loaders?.enabled) {
|
|
346
|
+
const scanDir = resolve(cwd, config.loaders.scanDir);
|
|
347
|
+
watchDirs.add(scanDir);
|
|
348
|
+
}
|
|
349
|
+
const sources = Array.isArray(config.source) ? config.source : [config.source];
|
|
350
|
+
for (const source of sources) if (source.directory) watchDirs.add(resolve(cwd, source.directory));
|
|
351
|
+
let regenerateTimeout = null;
|
|
352
|
+
const scheduleRegenerate = () => {
|
|
353
|
+
if (regenerateTimeout) clearTimeout(regenerateTimeout);
|
|
354
|
+
regenerateTimeout = setTimeout(async () => {
|
|
355
|
+
console.log("\nš Changes detected, regenerating...");
|
|
356
|
+
try {
|
|
357
|
+
await runGeneration(config, cwd);
|
|
358
|
+
} catch (error) {
|
|
359
|
+
console.error("ā Error during regeneration:", error);
|
|
360
|
+
}
|
|
361
|
+
}, 300);
|
|
362
|
+
};
|
|
363
|
+
for (const dir of watchDirs) watch(dir, { recursive: true }, (eventType, filename) => {
|
|
364
|
+
if (!filename) return;
|
|
365
|
+
if (filename.includes("node_modules") || filename.includes(".git") || filename.endsWith(".generated.ts") || filename.startsWith(".")) return;
|
|
366
|
+
if (/\.(tsx?|svg)$/.test(filename)) {
|
|
367
|
+
console.log(`š ${eventType}: ${filename}`);
|
|
368
|
+
scheduleRegenerate();
|
|
369
|
+
}
|
|
370
|
+
}).on("error", (error) => {
|
|
371
|
+
console.error(`ā Watch error for ${dir}:`, error);
|
|
372
|
+
});
|
|
373
|
+
console.log(`š Watching ${watchDirs.size} directories`);
|
|
374
|
+
console.log("Press Ctrl+C to stop\n");
|
|
375
|
+
await new Promise(() => {});
|
|
403
376
|
}
|
|
377
|
+
/**
|
|
378
|
+
* Main function
|
|
379
|
+
*/
|
|
404
380
|
async function main() {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
381
|
+
const { values } = parseArgs({ options: {
|
|
382
|
+
config: {
|
|
383
|
+
type: "string",
|
|
384
|
+
short: "c"
|
|
385
|
+
},
|
|
386
|
+
typesOnly: { type: "boolean" },
|
|
387
|
+
loadersOnly: { type: "boolean" },
|
|
388
|
+
watch: {
|
|
389
|
+
type: "boolean",
|
|
390
|
+
short: "w"
|
|
391
|
+
},
|
|
392
|
+
help: {
|
|
393
|
+
type: "boolean",
|
|
394
|
+
short: "h"
|
|
395
|
+
}
|
|
396
|
+
} });
|
|
397
|
+
if (values.help) {
|
|
398
|
+
console.log(`
|
|
416
399
|
Usage: generate-icons [options]
|
|
417
400
|
|
|
418
401
|
Options:
|
|
@@ -457,38 +440,37 @@ Examples:
|
|
|
457
440
|
# Watch mode - regenerate on file changes
|
|
458
441
|
generate-icons --config ./icon-generator.config.ts --watch
|
|
459
442
|
`);
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
443
|
+
process.exit(0);
|
|
444
|
+
}
|
|
445
|
+
if (!values.config) {
|
|
446
|
+
console.error("ā Error: --config is required");
|
|
447
|
+
console.error("Run with --help for usage information");
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
try {
|
|
451
|
+
const cwd = process.cwd();
|
|
452
|
+
let config = await loadConfig(values.config);
|
|
453
|
+
if (values.typesOnly && config.loaders) config = {
|
|
454
|
+
...config,
|
|
455
|
+
loaders: {
|
|
456
|
+
...config.loaders,
|
|
457
|
+
enabled: false
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
if (values.loadersOnly && config.types) config = {
|
|
461
|
+
...config,
|
|
462
|
+
types: {
|
|
463
|
+
...config.types,
|
|
464
|
+
enabled: false
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
if (values.watch) await watchMode(config, cwd);
|
|
468
|
+
else await runGeneration(config, cwd);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
console.error("ā Error:", error);
|
|
471
|
+
process.exit(1);
|
|
472
|
+
}
|
|
488
473
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
loadConfig,
|
|
493
|
-
scanIconSources
|
|
494
|
-
};
|
|
474
|
+
if (import.meta.url === `file://${process.argv[1]}`) main();
|
|
475
|
+
//#endregion
|
|
476
|
+
export { generateLoaders, generateTypes, loadConfig, scanIconSources };
|