@epoch32/visage 1.1.4 → 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 +52 -13
- package/dist/vite/lucide.d.ts +0 -17
- package/package.json +1 -1
- package/src/vite/lucide.ts +76 -16
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,43 +25,80 @@ 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
|
-
return
|
|
56
|
+
return `
|
|
57
|
+
import * as lucideIcons from "lucide";
|
|
58
|
+
import { createIcon } from "visage/ui";
|
|
59
|
+
|
|
60
|
+
const cache = new Map();
|
|
61
|
+
export const __getIcon = (name) => {
|
|
62
|
+
if (cache.has(name)) return cache.get(name);
|
|
63
|
+
const node = lucideIcons[name];
|
|
64
|
+
const comp = node ? createIcon(name, node) : () => null;
|
|
65
|
+
cache.set(name, comp);
|
|
66
|
+
return comp;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default new Proxy({}, {
|
|
70
|
+
get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
|
|
71
|
+
});
|
|
72
|
+
`;
|
|
39
73
|
}
|
|
40
74
|
return null;
|
|
41
75
|
},
|
|
42
76
|
transform(code, id) {
|
|
43
|
-
if (!id.match(/\.[jt]sx
|
|
77
|
+
if (!id.match(/\.([jt]sx?|mdx?)$/) || id.includes("node_modules")) {
|
|
44
78
|
return null;
|
|
45
79
|
}
|
|
46
80
|
let transformed = code;
|
|
47
81
|
let hasMatches = false;
|
|
48
82
|
for (const alias of aliases) {
|
|
49
|
-
const
|
|
50
|
-
transformed = transformed.replace(
|
|
83
|
+
const importRegex = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*['"]${alias}['"];?`, "g");
|
|
84
|
+
transformed = transformed.replace(importRegex, (_match, importClause) => {
|
|
51
85
|
const imports = parseNamedImports(importClause);
|
|
52
86
|
if (imports.length === 0)
|
|
53
87
|
return "";
|
|
54
88
|
hasMatches = true;
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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}";`;
|
|
63
102
|
});
|
|
64
103
|
}
|
|
65
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,14 +77,46 @@ 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
|
-
return
|
|
97
|
+
return `
|
|
98
|
+
import * as lucideIcons from "lucide";
|
|
99
|
+
import { createIcon } from "visage/ui";
|
|
100
|
+
|
|
101
|
+
const cache = new Map();
|
|
102
|
+
export const __getIcon = (name) => {
|
|
103
|
+
if (cache.has(name)) return cache.get(name);
|
|
104
|
+
const node = lucideIcons[name];
|
|
105
|
+
const comp = node ? createIcon(name, node) : () => null;
|
|
106
|
+
cache.set(name, comp);
|
|
107
|
+
return comp;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default new Proxy({}, {
|
|
111
|
+
get: (_, prop) => typeof prop === "string" ? __getIcon(prop) : undefined
|
|
112
|
+
});
|
|
113
|
+
`;
|
|
76
114
|
}
|
|
77
115
|
return null;
|
|
78
116
|
},
|
|
79
117
|
|
|
80
118
|
transform(code: string, id: string) {
|
|
81
|
-
if (!id.match(/\.[jt]sx
|
|
119
|
+
if (!id.match(/\.([jt]sx?|mdx?)$/) || id.includes("node_modules")) {
|
|
82
120
|
return null;
|
|
83
121
|
}
|
|
84
122
|
|
|
@@ -86,26 +124,48 @@ export function visageLucide(options: VisageLucideOptions = {}): VisageVitePlugi
|
|
|
86
124
|
let hasMatches = false;
|
|
87
125
|
|
|
88
126
|
for (const alias of aliases) {
|
|
89
|
-
//
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
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) => {
|
|
93
133
|
const imports = parseNamedImports(importClause);
|
|
94
134
|
if (imports.length === 0) return "";
|
|
95
|
-
|
|
96
135
|
hasMatches = true;
|
|
97
136
|
|
|
98
|
-
const
|
|
99
|
-
|
|
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
|
+
)
|
|
100
144
|
.join(", ");
|
|
101
145
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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(", ");
|
|
107
167
|
|
|
108
|
-
return `
|
|
168
|
+
return `export { ${specifiers} } from "${VIRTUAL_PREFIX}?icons=${queryIcons}";`;
|
|
109
169
|
});
|
|
110
170
|
}
|
|
111
171
|
|