@epoch32/visage 1.1.5 → 1.2.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/vite/index.js +34 -15
- package/dist/vite/lucide.d.ts +0 -17
- package/package.json +1 -1
- package/src/vite/lucide.ts +58 -18
package/dist/vite/index.js
CHANGED
|
@@ -15,6 +15,8 @@ function parseNamedImports(importClause) {
|
|
|
15
15
|
};
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
+
var VIRTUAL_PREFIX = "virtual:visage-icons";
|
|
19
|
+
var RESOLVED_PREFIX = `\x00${VIRTUAL_PREFIX}`;
|
|
18
20
|
function visageLucide(options = {}) {
|
|
19
21
|
const aliases = options.aliases ?? ["lucide-react"];
|
|
20
22
|
return {
|
|
@@ -23,17 +25,33 @@ function visageLucide(options = {}) {
|
|
|
23
25
|
config() {
|
|
24
26
|
return {
|
|
25
27
|
optimizeDeps: {
|
|
26
|
-
exclude: aliases
|
|
28
|
+
exclude: [...aliases, VIRTUAL_PREFIX]
|
|
27
29
|
}
|
|
28
30
|
};
|
|
29
31
|
},
|
|
30
32
|
resolveId(id) {
|
|
33
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
34
|
+
return `\x00${id}`;
|
|
35
|
+
}
|
|
31
36
|
if (aliases.includes(id)) {
|
|
32
37
|
return `\x00visage-lucide:${id}`;
|
|
33
38
|
}
|
|
34
39
|
return null;
|
|
35
40
|
},
|
|
36
41
|
load(id) {
|
|
42
|
+
if (id.startsWith(RESOLVED_PREFIX)) {
|
|
43
|
+
const query = id.slice(RESOLVED_PREFIX.length);
|
|
44
|
+
const params = new URLSearchParams(query.startsWith("?") ? query.slice(1) : "");
|
|
45
|
+
const names = (params.get("icons") || "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
46
|
+
const imports = names.map((n) => `${n} as __icon_node_${n}`).join(", ");
|
|
47
|
+
const exports = names.map((n) => `export const ${n} = /* @__PURE__ */ createIcon("${n}", __icon_node_${n});`).join(`
|
|
48
|
+
`);
|
|
49
|
+
return `import { createIcon } from "visage/ui";
|
|
50
|
+
import { ${imports} } from "lucide";
|
|
51
|
+
|
|
52
|
+
${exports}
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
37
55
|
if (id.startsWith("\x00visage-lucide:")) {
|
|
38
56
|
return `
|
|
39
57
|
import * as lucideIcons from "lucide";
|
|
@@ -51,10 +69,6 @@ export const __getIcon = (name) => {
|
|
|
51
69
|
export default new Proxy({}, {
|
|
52
70
|
get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
|
|
53
71
|
});
|
|
54
|
-
|
|
55
|
-
// Dynamic proxy export for all lucide icon names
|
|
56
|
-
${Object.keys({})};
|
|
57
|
-
export * from "lucide";
|
|
58
72
|
`;
|
|
59
73
|
}
|
|
60
74
|
return null;
|
|
@@ -66,20 +80,25 @@ export * from "lucide";
|
|
|
66
80
|
let transformed = code;
|
|
67
81
|
let hasMatches = false;
|
|
68
82
|
for (const alias of aliases) {
|
|
69
|
-
const
|
|
70
|
-
transformed = transformed.replace(
|
|
83
|
+
const importRegex = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`, "g");
|
|
84
|
+
transformed = transformed.replace(importRegex, (_match, importClause) => {
|
|
71
85
|
const imports = parseNamedImports(importClause);
|
|
72
86
|
if (imports.length === 0)
|
|
73
87
|
return "";
|
|
74
88
|
hasMatches = true;
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
const queryIcons = Array.from(new Set(imports.map((i) => i.importedName))).join(",");
|
|
90
|
+
const specifiers = imports.map((i) => i.importedName === i.localName ? i.importedName : `${i.importedName} as ${i.localName}`).join(", ");
|
|
91
|
+
return `import { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
|
|
92
|
+
});
|
|
93
|
+
const exportRegex = new RegExp(`export\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`, "g");
|
|
94
|
+
transformed = transformed.replace(exportRegex, (_match, exportClause) => {
|
|
95
|
+
const exports = parseNamedImports(exportClause);
|
|
96
|
+
if (exports.length === 0)
|
|
97
|
+
return "";
|
|
98
|
+
hasMatches = true;
|
|
99
|
+
const queryIcons = Array.from(new Set(exports.map((i) => i.importedName))).join(",");
|
|
100
|
+
const specifiers = exports.map((i) => i.importedName === i.localName ? i.importedName : `${i.importedName} as ${i.localName}`).join(", ");
|
|
101
|
+
return `export { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
|
|
83
102
|
});
|
|
84
103
|
}
|
|
85
104
|
if (!hasMatches) {
|
package/dist/vite/lucide.d.ts
CHANGED
|
@@ -6,22 +6,5 @@ export interface VisageLucideOptions {
|
|
|
6
6
|
*/
|
|
7
7
|
aliases?: string[];
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
* Official Visage Lucide Vite Plugin
|
|
11
|
-
*
|
|
12
|
-
* Statically transforms `import { Icon } from "lucide-react"` at build time into
|
|
13
|
-
* native, tree-shaken Visage SVG component instances using `createIcon` and `lucide`.
|
|
14
|
-
*
|
|
15
|
-
* Example:
|
|
16
|
-
* ```ts
|
|
17
|
-
* // vite.config.ts
|
|
18
|
-
* import { defineConfig } from "vite";
|
|
19
|
-
* import visage, { visageLucide } from "visage/vite";
|
|
20
|
-
*
|
|
21
|
-
* export default defineConfig({
|
|
22
|
-
* plugins: [visage(), visageLucide()]
|
|
23
|
-
* });
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
9
|
export declare function visageLucide(options?: VisageLucideOptions): VisageVitePlugin;
|
|
27
10
|
export default visageLucide;
|
package/package.json
CHANGED
package/src/vite/lucide.ts
CHANGED
|
@@ -48,6 +48,9 @@ function parseNamedImports(importClause: string): ParsedImport[] {
|
|
|
48
48
|
* });
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
+
const VIRTUAL_PREFIX = "virtual:visage-icons";
|
|
52
|
+
const RESOLVED_PREFIX = `\0${VIRTUAL_PREFIX}`;
|
|
53
|
+
|
|
51
54
|
export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugin {
|
|
52
55
|
const aliases = options.aliases ?? ["lucide-react"];
|
|
53
56
|
|
|
@@ -58,12 +61,15 @@ export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugi
|
|
|
58
61
|
config() {
|
|
59
62
|
return {
|
|
60
63
|
optimizeDeps: {
|
|
61
|
-
exclude: aliases
|
|
64
|
+
exclude: [...aliases, VIRTUAL_PREFIX]
|
|
62
65
|
}
|
|
63
66
|
};
|
|
64
67
|
},
|
|
65
68
|
|
|
66
69
|
resolveId(id: string) {
|
|
70
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
71
|
+
return `\0${id}`;
|
|
72
|
+
}
|
|
67
73
|
if (aliases.includes(id)) {
|
|
68
74
|
return `\0visage-lucide:${id}`;
|
|
69
75
|
}
|
|
@@ -71,6 +77,22 @@ export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugi
|
|
|
71
77
|
},
|
|
72
78
|
|
|
73
79
|
load(id: string) {
|
|
80
|
+
if (id.startsWith(RESOLVED_PREFIX)) {
|
|
81
|
+
const query = id.slice(RESOLVED_PREFIX.length);
|
|
82
|
+
const params = new URLSearchParams(query.startsWith("?") ? query.slice(1) : "");
|
|
83
|
+
const names = (params.get("icons") || "")
|
|
84
|
+
.split(",")
|
|
85
|
+
.map((s) => s.trim())
|
|
86
|
+
.filter(Boolean);
|
|
87
|
+
|
|
88
|
+
const imports = names.map((n) => `${n} as __icon_node_${n}`).join(", ");
|
|
89
|
+
const exports = names
|
|
90
|
+
.map((n) => `export const ${n} = /* @__PURE__ */ createIcon("${n}", __icon_node_${n});`)
|
|
91
|
+
.join("\n");
|
|
92
|
+
|
|
93
|
+
return `import { createIcon } from "visage/ui";\nimport { ${imports} } from "lucide";\n\n${exports}\n`;
|
|
94
|
+
}
|
|
95
|
+
|
|
74
96
|
if (id.startsWith("\0visage-lucide:")) {
|
|
75
97
|
return `
|
|
76
98
|
import * as lucideIcons from "lucide";
|
|
@@ -88,10 +110,6 @@ export const __getIcon = (name) => {
|
|
|
88
110
|
export default new Proxy({}, {
|
|
89
111
|
get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
|
|
90
112
|
});
|
|
91
|
-
|
|
92
|
-
// Dynamic proxy export for all lucide icon names
|
|
93
|
-
${Object.keys({})};
|
|
94
|
-
export * from "lucide";
|
|
95
113
|
`;
|
|
96
114
|
}
|
|
97
115
|
return null;
|
|
@@ -106,26 +124,48 @@ export * from "lucide";
|
|
|
106
124
|
let hasMatches = false;
|
|
107
125
|
|
|
108
126
|
for (const alias of aliases) {
|
|
109
|
-
//
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
127
|
+
// Match: import { ... } from "alias"
|
|
128
|
+
const importRegex = new RegExp(
|
|
129
|
+
`import\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`,
|
|
130
|
+
"g"
|
|
131
|
+
);
|
|
132
|
+
transformed = transformed.replace(importRegex, (_match, importClause) => {
|
|
113
133
|
const imports = parseNamedImports(importClause);
|
|
114
134
|
if (imports.length === 0) return "";
|
|
115
|
-
|
|
116
135
|
hasMatches = true;
|
|
117
136
|
|
|
118
|
-
const
|
|
119
|
-
|
|
137
|
+
const queryIcons = Array.from(new Set(imports.map((i) => i.importedName))).join(",");
|
|
138
|
+
const specifiers = imports
|
|
139
|
+
.map((i) =>
|
|
140
|
+
i.importedName === i.localName
|
|
141
|
+
? i.importedName
|
|
142
|
+
: `${i.importedName} as ${i.localName}`
|
|
143
|
+
)
|
|
120
144
|
.join(", ");
|
|
121
145
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
return `import { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Match: export { ... } from "alias"
|
|
150
|
+
const exportRegex = new RegExp(
|
|
151
|
+
`export\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`,
|
|
152
|
+
"g"
|
|
153
|
+
);
|
|
154
|
+
transformed = transformed.replace(exportRegex, (_match, exportClause) => {
|
|
155
|
+
const exports = parseNamedImports(exportClause);
|
|
156
|
+
if (exports.length === 0) return "";
|
|
157
|
+
hasMatches = true;
|
|
158
|
+
|
|
159
|
+
const queryIcons = Array.from(new Set(exports.map((i) => i.importedName))).join(",");
|
|
160
|
+
const specifiers = exports
|
|
161
|
+
.map((i) =>
|
|
162
|
+
i.importedName === i.localName
|
|
163
|
+
? i.importedName
|
|
164
|
+
: `${i.importedName} as ${i.localName}`
|
|
165
|
+
)
|
|
166
|
+
.join(", ");
|
|
127
167
|
|
|
128
|
-
return `
|
|
168
|
+
return `export { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
|
|
129
169
|
});
|
|
130
170
|
}
|
|
131
171
|
|