react-icons-sprite 1.3.0 → 1.4.0-rc1
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 +41 -28
- package/dist/build-sprite-DEOFEWm0.mjs +472 -0
- package/dist/{collector-dvzR3TG1.mjs → collector-1bZHiz4N.mjs} +1 -1
- package/dist/compute-icon-id-C42PyoDX.mjs +84 -0
- package/dist/icon.d.mts +3 -4
- package/dist/index.d.mts +2 -2
- package/dist/plugin-options-DYfIgasR.d.mts +17 -0
- package/dist/transform-module-Cabatwdp.mjs +471 -0
- package/dist/vite/plugin.d.mts +4 -5
- package/dist/vite/plugin.mjs +5 -4
- package/dist/webpack/loader.d.mts +4 -1
- package/dist/webpack/loader.mjs +6 -4
- package/dist/webpack/plugin.d.mts +4 -5
- package/dist/webpack/plugin.mjs +3 -3
- package/package.json +44 -31
- package/dist/build-sprite-Dci5SlWn.mjs +0 -217
- package/dist/compute-icon-id-1Gop_fRM.mjs +0 -113
- package/dist/plugin-options-ByGrVpdG.d.mts +0 -9
- package/dist/transform-module-BakS0Tzh.mjs +0 -854
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactIconsSpriteIcon } from "./icon.mjs";
|
|
2
2
|
//#region src/index.d.ts
|
|
3
|
-
declare const REACT_ICONS_SPRITE_URL_PLACEHOLDER = "__SPRITE_URL_PLACEHOLDER__";
|
|
3
|
+
export declare const REACT_ICONS_SPRITE_URL_PLACEHOLDER = "__SPRITE_URL_PLACEHOLDER__";
|
|
4
4
|
//#endregion
|
|
5
|
-
export {
|
|
5
|
+
export { ReactIconsSpriteIcon };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/plugin-options.d.ts
|
|
2
|
+
type IconSourceExclusion = RegExp | readonly RegExp[];
|
|
3
|
+
type ReactIconsSpritePluginOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* Optional directory inside the bundler output where the sprite asset should be emitted.
|
|
6
|
+
*/
|
|
7
|
+
outputDir?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Icon import sources to leave as inline React components.
|
|
10
|
+
*
|
|
11
|
+
* Use this when CSS needs to target elements inside an icon SVG. Those
|
|
12
|
+
* selectors cannot cross an SVG <use> reference into the generated sprite.
|
|
13
|
+
*/
|
|
14
|
+
exclude?: IconSourceExclusion;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ReactIconsSpritePluginOptions as t };
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
import { n as normalizePackAlias, s as DEFAULT_ICON_SOURCES } from "./compute-icon-id-C42PyoDX.mjs";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
import { parseSync, rawTransferSupported, visitorKeys } from "oxc-parser";
|
|
4
|
+
//#region src/transform/edit-applier.ts
|
|
5
|
+
const applyEdits = (code, edits) => {
|
|
6
|
+
const magicString = new MagicString(code);
|
|
7
|
+
for (const edit of edits) {
|
|
8
|
+
if (edit.type === "replace") magicString.overwrite(edit.from, edit.to, edit.value);
|
|
9
|
+
if (edit.type === "insert") magicString.appendLeft(edit.pos, edit.value);
|
|
10
|
+
if (edit.type === "remove") magicString.remove(edit.from, edit.to);
|
|
11
|
+
}
|
|
12
|
+
return magicString;
|
|
13
|
+
};
|
|
14
|
+
const editStart = (edit) => {
|
|
15
|
+
return edit.type === "insert" ? edit.pos : edit.from;
|
|
16
|
+
};
|
|
17
|
+
const applyEditsToString = (code, edits, presorted = false) => {
|
|
18
|
+
if (!edits.length) return code;
|
|
19
|
+
const orderedEdits = presorted ? edits : [...edits].sort((left, right) => {
|
|
20
|
+
const startDelta = editStart(left) - editStart(right);
|
|
21
|
+
if (startDelta !== 0) return startDelta;
|
|
22
|
+
if (left.type === "insert" && right.type !== "insert") return 1;
|
|
23
|
+
if (left.type !== "insert" && right.type === "insert") return -1;
|
|
24
|
+
return 0;
|
|
25
|
+
});
|
|
26
|
+
let result = "";
|
|
27
|
+
let cursor = 0;
|
|
28
|
+
for (const edit of orderedEdits) {
|
|
29
|
+
if (edit.type === "insert") {
|
|
30
|
+
if (edit.pos <= cursor) {
|
|
31
|
+
result += edit.value;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
result += code.slice(cursor, edit.pos) + edit.value;
|
|
35
|
+
cursor = edit.pos;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
result += code.slice(cursor, edit.from);
|
|
39
|
+
if (edit.type === "replace") result += edit.value;
|
|
40
|
+
cursor = edit.to;
|
|
41
|
+
}
|
|
42
|
+
return result + code.slice(cursor);
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/transform/fast-filter.ts
|
|
46
|
+
const fastFilter = (code) => {
|
|
47
|
+
if (!code.includes("<")) return false;
|
|
48
|
+
if (!code.includes("import")) return false;
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/transform/parse-module.ts
|
|
53
|
+
const createModuleParser = (preferRawTransfer = true) => {
|
|
54
|
+
const options = {
|
|
55
|
+
sourceType: "unambiguous",
|
|
56
|
+
lang: "tsx",
|
|
57
|
+
astType: "ts",
|
|
58
|
+
preserveParens: false,
|
|
59
|
+
showSemanticErrors: true,
|
|
60
|
+
experimentalRawTransfer: preferRawTransfer && rawTransferSupported()
|
|
61
|
+
};
|
|
62
|
+
return (id, code) => {
|
|
63
|
+
const result = parseSync(id, code, options);
|
|
64
|
+
return result.errors.length ? null : result.program;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/transform/is-referenced.ts
|
|
69
|
+
const isReferenced$1 = (node, parent, grandparent) => {
|
|
70
|
+
switch (parent.type) {
|
|
71
|
+
case "MemberExpression": return parent.object === node || parent.computed;
|
|
72
|
+
case "JSXMemberExpression": return parent.object === node;
|
|
73
|
+
case "Property": return parent.key === node ? parent.computed : grandparent?.type !== "ObjectPattern";
|
|
74
|
+
case "MethodDefinition":
|
|
75
|
+
case "TSAbstractMethodDefinition":
|
|
76
|
+
case "PropertyDefinition":
|
|
77
|
+
case "TSAbstractPropertyDefinition":
|
|
78
|
+
case "AccessorProperty": return parent.key !== node || parent.computed;
|
|
79
|
+
case "VariableDeclarator": return parent.init === node;
|
|
80
|
+
case "AssignmentPattern": return parent.right === node;
|
|
81
|
+
case "FunctionDeclaration":
|
|
82
|
+
case "FunctionExpression":
|
|
83
|
+
case "TSDeclareFunction":
|
|
84
|
+
case "TSEmptyBodyFunctionExpression":
|
|
85
|
+
case "ArrowFunctionExpression": return parent.body === node;
|
|
86
|
+
case "ClassDeclaration":
|
|
87
|
+
case "ClassExpression": return parent.superClass === node;
|
|
88
|
+
case "ExportSpecifier": return parent.local === node && !(grandparent && "source" in grandparent && grandparent.source);
|
|
89
|
+
case "TSQualifiedName": return parent.left === node;
|
|
90
|
+
case "TSEnumMember": return parent.initializer === node;
|
|
91
|
+
case "ImportSpecifier":
|
|
92
|
+
case "ImportDefaultSpecifier":
|
|
93
|
+
case "ImportNamespaceSpecifier":
|
|
94
|
+
case "ImportAttribute":
|
|
95
|
+
case "ObjectPattern":
|
|
96
|
+
case "ArrayPattern":
|
|
97
|
+
case "RestElement":
|
|
98
|
+
case "CatchClause":
|
|
99
|
+
case "LabeledStatement":
|
|
100
|
+
case "BreakStatement":
|
|
101
|
+
case "ContinueStatement":
|
|
102
|
+
case "MetaProperty":
|
|
103
|
+
case "JSXAttribute": return false;
|
|
104
|
+
default: return true;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/transform/analyze-module.ts
|
|
109
|
+
const isReferenced = isReferenced$1;
|
|
110
|
+
const getBinding$1 = (scope, name) => {
|
|
111
|
+
const cached = scope.resolved[name];
|
|
112
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
113
|
+
const binding = scope.bindings[name] ?? (scope.parent && getBinding$1(scope.parent, name));
|
|
114
|
+
scope.resolved[name] = binding ?? null;
|
|
115
|
+
return binding;
|
|
116
|
+
};
|
|
117
|
+
const analyzeModule = (ast) => {
|
|
118
|
+
const imports = [];
|
|
119
|
+
const elements = [];
|
|
120
|
+
const names = /* @__PURE__ */ new Set();
|
|
121
|
+
const bindings = [];
|
|
122
|
+
const root = {
|
|
123
|
+
functionScope: true,
|
|
124
|
+
bindings: Object.create(null),
|
|
125
|
+
resolved: Object.create(null)
|
|
126
|
+
};
|
|
127
|
+
const scopes = [root];
|
|
128
|
+
const tracked = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const node of ast.body) {
|
|
130
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
131
|
+
imports.push({
|
|
132
|
+
node,
|
|
133
|
+
scope: root
|
|
134
|
+
});
|
|
135
|
+
for (const specifier of node.specifiers) {
|
|
136
|
+
tracked.add(specifier.local.name);
|
|
137
|
+
names.add(specifier.local.name);
|
|
138
|
+
const binding = {
|
|
139
|
+
identifier: specifier.local,
|
|
140
|
+
references: []
|
|
141
|
+
};
|
|
142
|
+
root.bindings[specifier.local.name] = binding;
|
|
143
|
+
bindings.push(binding);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const bind = (node, scope) => {
|
|
147
|
+
if (!node) return;
|
|
148
|
+
switch (node.type) {
|
|
149
|
+
case "Identifier":
|
|
150
|
+
if (tracked.has(node.name) && scope.bindings[node.name] === void 0) {
|
|
151
|
+
const binding = {
|
|
152
|
+
identifier: node,
|
|
153
|
+
references: []
|
|
154
|
+
};
|
|
155
|
+
scope.bindings[node.name] = binding;
|
|
156
|
+
bindings.push(binding);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
case "AssignmentPattern":
|
|
160
|
+
bind(node.left, scope);
|
|
161
|
+
return;
|
|
162
|
+
case "RestElement":
|
|
163
|
+
bind(node.argument, scope);
|
|
164
|
+
return;
|
|
165
|
+
case "ObjectPattern":
|
|
166
|
+
for (const property of node.properties) bind(property.type === "RestElement" ? property.argument : property.value, scope);
|
|
167
|
+
return;
|
|
168
|
+
case "ArrayPattern":
|
|
169
|
+
for (const element of node.elements) bind(element, scope);
|
|
170
|
+
return;
|
|
171
|
+
case "TSParameterProperty":
|
|
172
|
+
bind(node.parameter, scope);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const walk = (node, inherited, parent, grandparent) => {
|
|
177
|
+
if (node.type === "ImportDeclaration") return;
|
|
178
|
+
if (node.type === "Identifier" || node.type === "JSXIdentifier") {
|
|
179
|
+
names.add(node.name);
|
|
180
|
+
if (tracked.has(node.name) && parent && isReferenced(node, parent, grandparent)) {
|
|
181
|
+
inherited.references ??= [];
|
|
182
|
+
inherited.references.push(node);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (node.type === "JSXElement") {
|
|
187
|
+
elements.push({
|
|
188
|
+
node,
|
|
189
|
+
scope: inherited
|
|
190
|
+
});
|
|
191
|
+
const opening = node.openingElement;
|
|
192
|
+
walk(opening.name, inherited, opening, node);
|
|
193
|
+
for (const attribute of opening.attributes) if (attribute.type === "JSXSpreadAttribute") walk(attribute.argument, inherited, attribute, opening);
|
|
194
|
+
else if (attribute.value?.type === "JSXExpressionContainer") walk(attribute.value.expression, inherited, attribute.value, attribute);
|
|
195
|
+
for (const child of node.children) if (child.type === "JSXElement" || child.type === "JSXFragment") walk(child, inherited, node, parent);
|
|
196
|
+
else if (child.type === "JSXExpressionContainer" || child.type === "JSXSpreadChild") walk(child.expression, inherited, child, node);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (node.type === "JSXFragment") {
|
|
200
|
+
for (const child of node.children) if (child.type === "JSXElement" || child.type === "JSXFragment") walk(child, inherited, node, parent);
|
|
201
|
+
else if (child.type === "JSXExpressionContainer" || child.type === "JSXSpreadChild") walk(child.expression, inherited, child, node);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
let scope = inherited;
|
|
205
|
+
if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration" || node.type === "TSEnumDeclaration" || node.type === "TSModuleDeclaration") bind(node.id, inherited);
|
|
206
|
+
const isFunction = node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
207
|
+
if (isFunction || node.type === "BlockStatement" || node.type === "CatchClause" || node.type === "ForStatement" || node.type === "ForInStatement" || node.type === "ForOfStatement" || node.type === "SwitchStatement" || node.type === "ClassDeclaration" || node.type === "ClassExpression" || node.type === "StaticBlock" || node.type === "TSModuleDeclaration" || node.type === "TSEnumDeclaration") {
|
|
208
|
+
scope = {
|
|
209
|
+
parent: inherited,
|
|
210
|
+
functionScope: isFunction || node.type === "StaticBlock" || node.type === "TSModuleDeclaration",
|
|
211
|
+
bindings: Object.create(null),
|
|
212
|
+
resolved: Object.create(null)
|
|
213
|
+
};
|
|
214
|
+
scopes.push(scope);
|
|
215
|
+
}
|
|
216
|
+
if ("params" in node && isFunction) for (const parameter of node.params) bind(parameter, scope);
|
|
217
|
+
if (node.type === "FunctionExpression" || node.type === "ClassExpression" || node.type === "ClassDeclaration") bind(node.id, scope);
|
|
218
|
+
if (node.type === "TSImportEqualsDeclaration") bind(node.id, scope);
|
|
219
|
+
if (node.type === "CatchClause") bind(node.param, scope);
|
|
220
|
+
if (node.type === "VariableDeclaration") {
|
|
221
|
+
let target = scope;
|
|
222
|
+
if (node.kind === "var") while (!target.functionScope && target.parent) target = target.parent;
|
|
223
|
+
for (const declaration of node.declarations) bind(declaration.id, target);
|
|
224
|
+
}
|
|
225
|
+
if (node.type === "TSEnumDeclaration") for (const member of node.body.members) bind(member.id, scope);
|
|
226
|
+
const record = node;
|
|
227
|
+
for (const key of visitorKeys[node.type] ?? []) {
|
|
228
|
+
const child = record[key];
|
|
229
|
+
const childScope = isFunction && (key === "key" || key === "decorators") ? inherited : scope;
|
|
230
|
+
if (Array.isArray(child)) {
|
|
231
|
+
for (const item of child) if (item) walk(item, childScope, node, parent);
|
|
232
|
+
} else if (child) walk(child, childScope, node, parent);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
walk(ast, root);
|
|
236
|
+
for (const scope of scopes) for (const reference of scope.references ?? []) getBinding$1(scope, reference.name)?.references.push(reference);
|
|
237
|
+
return {
|
|
238
|
+
imports,
|
|
239
|
+
elements,
|
|
240
|
+
names,
|
|
241
|
+
bindings
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/transform/transform-module.ts
|
|
246
|
+
const getBinding = getBinding$1;
|
|
247
|
+
const parseModule = createModuleParser();
|
|
248
|
+
const ICON_COMPONENT_NAME = "ReactIconsSpriteIcon";
|
|
249
|
+
const matches = (sources, pack) => sources.some((source) => {
|
|
250
|
+
source.lastIndex = 0;
|
|
251
|
+
return source.test(pack);
|
|
252
|
+
});
|
|
253
|
+
const isDefinition = (pack) => /^@fortawesome\/[\w-]+-svg-icons$/.test(pack) || /^@hugeicons\/core-free-icons(?:\/.*)?$/.test(pack);
|
|
254
|
+
const defaultSourceHints = DEFAULT_ICON_SOURCES.map((source) => {
|
|
255
|
+
const pattern = source.source;
|
|
256
|
+
let prefix = "";
|
|
257
|
+
for (let index = 1; index < pattern.length; index++) {
|
|
258
|
+
const char = pattern[index];
|
|
259
|
+
if (char === "(" || char === "[" || char === "$") break;
|
|
260
|
+
if (char === "\\" && pattern[index + 1] === "/") index++;
|
|
261
|
+
prefix += pattern[index];
|
|
262
|
+
}
|
|
263
|
+
return prefix;
|
|
264
|
+
});
|
|
265
|
+
const hasPossibleIconSource = (code, sources, excluded) => {
|
|
266
|
+
if (code.includes("\\")) return true;
|
|
267
|
+
if (sources === DEFAULT_ICON_SOURCES && !defaultSourceHints.some((hint) => code.includes(hint))) return false;
|
|
268
|
+
for (let index = 0; index < code.length; index++) {
|
|
269
|
+
const quote = code[index];
|
|
270
|
+
if (quote !== "\"" && quote !== "'") continue;
|
|
271
|
+
const end = code.indexOf(quote, index + 1);
|
|
272
|
+
if (end === -1) continue;
|
|
273
|
+
const candidate = code.slice(index + 1, end);
|
|
274
|
+
if (matches(sources, candidate) && !matches(excluded, candidate)) return true;
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
};
|
|
278
|
+
const range = (node) => [node.start, node.end];
|
|
279
|
+
const importedName = (node) => node.type === "ImportDefaultSpecifier" ? "default" : node.type === "ImportSpecifier" ? node.imported.type === "Identifier" ? node.imported.name : node.imported.value : "*";
|
|
280
|
+
const transformModule = (code, id, register, sources = DEFAULT_ICON_SOURCES, options = {}) => {
|
|
281
|
+
const unchanged = {
|
|
282
|
+
code,
|
|
283
|
+
map: null,
|
|
284
|
+
anyReplacements: false
|
|
285
|
+
};
|
|
286
|
+
if (!fastFilter(code) || !hasPossibleIconSource(code, sources, options.excludedSources ?? [])) return unchanged;
|
|
287
|
+
let ast;
|
|
288
|
+
try {
|
|
289
|
+
const parsed = parseModule(id, code);
|
|
290
|
+
if (!parsed) return unchanged;
|
|
291
|
+
ast = parsed;
|
|
292
|
+
} catch {
|
|
293
|
+
return unchanged;
|
|
294
|
+
}
|
|
295
|
+
if (!ast.body.some((node) => node.type === "ImportDeclaration" && matches(sources, node.source.value) && !matches(options.excludedSources ?? [], node.source.value))) return unchanged;
|
|
296
|
+
const icons = /* @__PURE__ */ new Map();
|
|
297
|
+
const symbols = /* @__PURE__ */ new Map();
|
|
298
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
299
|
+
const { imports, elements, names, bindings } = analyzeModule(ast);
|
|
300
|
+
let spriteBinding;
|
|
301
|
+
for (const path of imports) {
|
|
302
|
+
const pack = path.node.source.value;
|
|
303
|
+
const supported = matches(sources, pack) && !matches(options.excludedSources ?? [], pack);
|
|
304
|
+
const definition = supported && isDefinition(pack);
|
|
305
|
+
const idPrefix = supported ? `ri-${normalizePackAlias(pack)}-` : "";
|
|
306
|
+
let exports = symbols.get(pack);
|
|
307
|
+
if (supported && !exports) {
|
|
308
|
+
exports = /* @__PURE__ */ new Map();
|
|
309
|
+
symbols.set(pack, exports);
|
|
310
|
+
}
|
|
311
|
+
for (const specifier of path.node.specifiers) {
|
|
312
|
+
if (path.node.importKind === "type" || specifier.type === "ImportSpecifier" && specifier.importKind === "type") continue;
|
|
313
|
+
const binding = getBinding(path.scope, specifier.local.name);
|
|
314
|
+
if (!binding || specifier.type === "ImportNamespaceSpecifier") continue;
|
|
315
|
+
const exportName = importedName(specifier);
|
|
316
|
+
if (pack === "react-icons-sprite" && exportName === "ReactIconsSpriteIcon") spriteBinding = binding;
|
|
317
|
+
if (pack === "@fortawesome/react-fontawesome" && exportName === "FontAwesomeIcon" || pack === "@hugeicons/react" && exportName === "HugeiconsIcon") wrappers.set(binding, pack);
|
|
318
|
+
if (supported && exports) {
|
|
319
|
+
let symbol = exports.get(exportName);
|
|
320
|
+
if (!symbol) {
|
|
321
|
+
symbol = {
|
|
322
|
+
pack,
|
|
323
|
+
exportName,
|
|
324
|
+
idPrefix,
|
|
325
|
+
definition,
|
|
326
|
+
openingReplacement: "",
|
|
327
|
+
referenceReplacement: ""
|
|
328
|
+
};
|
|
329
|
+
exports.set(exportName, symbol);
|
|
330
|
+
}
|
|
331
|
+
icons.set(binding, symbol);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (!icons.size) return unchanged;
|
|
336
|
+
let componentName = spriteBinding?.identifier.name ?? "ReactIconsSpriteIcon";
|
|
337
|
+
const reuseSprite = spriteBinding && !bindings.some((binding) => binding !== spriteBinding && binding.identifier.name === componentName);
|
|
338
|
+
if (!reuseSprite) {
|
|
339
|
+
let suffix = 0;
|
|
340
|
+
while (names.has(componentName)) componentName = ICON_COMPONENT_NAME + ++suffix;
|
|
341
|
+
}
|
|
342
|
+
const openingReplacement = (icon) => icon.openingReplacement ||= `${componentName} iconId="${icon.idPrefix}${icon.exportName}"`;
|
|
343
|
+
const referenceReplacement = (icon) => icon.referenceReplacement ||= `(props) => <${componentName} {...props} iconId="${icon.idPrefix}${icon.exportName}" />`;
|
|
344
|
+
const edits = [];
|
|
345
|
+
const replaced = /* @__PURE__ */ new Set();
|
|
346
|
+
const usedImports = /* @__PURE__ */ new Set();
|
|
347
|
+
const registrations = [
|
|
348
|
+
[],
|
|
349
|
+
[],
|
|
350
|
+
[]
|
|
351
|
+
];
|
|
352
|
+
const replace = (node, value) => {
|
|
353
|
+
edits.push({
|
|
354
|
+
type: "replace",
|
|
355
|
+
from: node.start,
|
|
356
|
+
to: node.end,
|
|
357
|
+
value
|
|
358
|
+
});
|
|
359
|
+
replaced.add(node);
|
|
360
|
+
};
|
|
361
|
+
const elementBinding = (path) => {
|
|
362
|
+
const name = path.node.openingElement.name;
|
|
363
|
+
return name.type === "JSXIdentifier" ? getBinding(path.scope, name.name) : void 0;
|
|
364
|
+
};
|
|
365
|
+
const hasIconId = (path) => path.node.openingElement.attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "iconId");
|
|
366
|
+
for (const path of elements) {
|
|
367
|
+
const binding = elementBinding(path);
|
|
368
|
+
const opening = path.node.openingElement;
|
|
369
|
+
const direct = binding && icons.get(binding);
|
|
370
|
+
if (binding && direct && !direct.definition) {
|
|
371
|
+
replace(opening.name, hasIconId(path) ? componentName : openingReplacement(direct));
|
|
372
|
+
if (path.node.closingElement) replace(path.node.closingElement.name, componentName);
|
|
373
|
+
usedImports.add(binding);
|
|
374
|
+
registrations[0].push(direct);
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
const wrapper = binding && wrappers.get(binding);
|
|
378
|
+
if (binding && wrapper) {
|
|
379
|
+
const attribute = opening.attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "icon");
|
|
380
|
+
if (attribute?.type !== "JSXAttribute" || attribute.value?.type !== "JSXExpressionContainer" || attribute.value.expression.type !== "Identifier") continue;
|
|
381
|
+
const iconBinding = getBinding(path.scope, attribute.value.expression.name);
|
|
382
|
+
const icon = iconBinding && icons.get(iconBinding);
|
|
383
|
+
if (!iconBinding || !icon?.definition || wrapper === "@hugeicons/react" !== icon.pack.startsWith("@hugeicons/")) continue;
|
|
384
|
+
replace(opening.name, hasIconId(path) ? componentName : openingReplacement(icon));
|
|
385
|
+
if (path.node.closingElement) replace(path.node.closingElement.name, componentName);
|
|
386
|
+
let to = attribute.end;
|
|
387
|
+
while (/\s/.test(code[to] ?? "") && to < code.length) to++;
|
|
388
|
+
edits.push({
|
|
389
|
+
type: "remove",
|
|
390
|
+
from: attribute.start,
|
|
391
|
+
to
|
|
392
|
+
});
|
|
393
|
+
replaced.add(attribute.value.expression);
|
|
394
|
+
usedImports.add(binding);
|
|
395
|
+
usedImports.add(iconBinding);
|
|
396
|
+
registrations[2].push(icon);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
for (const attribute of opening.attributes) {
|
|
400
|
+
if (attribute.type !== "JSXAttribute" || attribute.value?.type !== "JSXExpressionContainer" || attribute.value.expression.type !== "Identifier") continue;
|
|
401
|
+
const expression = attribute.value.expression;
|
|
402
|
+
const iconBinding = getBinding(path.scope, expression.name);
|
|
403
|
+
const icon = iconBinding && icons.get(iconBinding);
|
|
404
|
+
if (!iconBinding || !icon || icon.definition) continue;
|
|
405
|
+
replace(expression, referenceReplacement(icon));
|
|
406
|
+
usedImports.add(iconBinding);
|
|
407
|
+
registrations[1].push(icon);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const registered = /* @__PURE__ */ new Set();
|
|
411
|
+
for (const bucket of registrations) for (const icon of bucket) {
|
|
412
|
+
if (registered.has(icon)) continue;
|
|
413
|
+
registered.add(icon);
|
|
414
|
+
register(icon.pack, icon.exportName);
|
|
415
|
+
}
|
|
416
|
+
if (!edits.length) return unchanged;
|
|
417
|
+
for (const path of imports) {
|
|
418
|
+
const declaration = path.node;
|
|
419
|
+
const kept = declaration.specifiers.filter((specifier) => {
|
|
420
|
+
const binding = getBinding(path.scope, specifier.local.name);
|
|
421
|
+
return !binding || !usedImports.has(binding) || binding.references.some((reference) => !replaced.has(reference));
|
|
422
|
+
});
|
|
423
|
+
if (kept.length === declaration.specifiers.length) continue;
|
|
424
|
+
if (!kept.length) {
|
|
425
|
+
const [from, end] = range(declaration);
|
|
426
|
+
let to = end;
|
|
427
|
+
while (code[to] === " " || code[to] === " " || code[to] === "\r") to++;
|
|
428
|
+
if (code[to] === "\n") to++;
|
|
429
|
+
edits.push({
|
|
430
|
+
type: "remove",
|
|
431
|
+
from,
|
|
432
|
+
to
|
|
433
|
+
});
|
|
434
|
+
} else {
|
|
435
|
+
const ordinary = kept.filter((spec) => spec.type !== "ImportSpecifier").map((spec) => code.slice(...range(spec)));
|
|
436
|
+
const named = kept.filter((spec) => spec.type === "ImportSpecifier").map((spec) => code.slice(...range(spec)));
|
|
437
|
+
if (named.length) ordinary.push(`{ ${named.join(", ")} }`);
|
|
438
|
+
edits.push({
|
|
439
|
+
type: "replace",
|
|
440
|
+
from: declaration.start + 6,
|
|
441
|
+
to: declaration.source.start,
|
|
442
|
+
value: ` ${ordinary.join(", ")} from `
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (!reuseSprite) {
|
|
447
|
+
const specifier = componentName === "ReactIconsSpriteIcon" ? ICON_COMPONENT_NAME : `${ICON_COMPONENT_NAME} as ${componentName}`;
|
|
448
|
+
const pos = ast.body.filter((node) => node.type === "ExpressionStatement" && "directive" in node).at(-1)?.end ?? ast.hashbang?.end ?? 0;
|
|
449
|
+
edits.push({
|
|
450
|
+
type: "insert",
|
|
451
|
+
pos,
|
|
452
|
+
value: (pos ? "\n" : "") + "import { " + specifier + " } from \"react-icons-sprite\";\n"
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
if (!options.sourceMap) return {
|
|
456
|
+
code: applyEditsToString(code, edits),
|
|
457
|
+
map: null,
|
|
458
|
+
anyReplacements: true
|
|
459
|
+
};
|
|
460
|
+
const result = applyEdits(code, edits);
|
|
461
|
+
return {
|
|
462
|
+
code: result.toString(),
|
|
463
|
+
map: result.generateMap({
|
|
464
|
+
source: id,
|
|
465
|
+
hires: true
|
|
466
|
+
}),
|
|
467
|
+
anyReplacements: true
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
//#endregion
|
|
471
|
+
export { transformModule as t };
|
package/dist/vite/plugin.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { t as ReactIconsSpritePluginOptions } from "../plugin-options-
|
|
1
|
+
import { t as ReactIconsSpritePluginOptions } from "../plugin-options-DYfIgasR.mjs";
|
|
2
2
|
import { Plugin } from "vite";
|
|
3
3
|
//#region src/vite/plugin.d.ts
|
|
4
|
-
type ReactIconsSpriteVitePluginOptions = ReactIconsSpritePluginOptions;
|
|
5
|
-
declare const reactIconsSprite: (options?: ReactIconsSpriteVitePluginOptions) => Plugin;
|
|
6
|
-
//#endregion
|
|
7
|
-
export { ReactIconsSpriteVitePluginOptions, reactIconsSprite };
|
|
4
|
+
export type ReactIconsSpriteVitePluginOptions = ReactIconsSpritePluginOptions;
|
|
5
|
+
export declare const reactIconsSprite: (options?: ReactIconsSpriteVitePluginOptions) => Plugin;
|
|
6
|
+
//#endregion
|
package/dist/vite/plugin.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { REACT_ICONS_SPRITE_URL_PLACEHOLDER } from "../index.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as buildSprite } from "../build-sprite-
|
|
4
|
-
import { t as transformModule } from "../transform-module-
|
|
2
|
+
import { a as createIconSources, c as createCollector, i as createExcludedIconSources, o as createSpriteAssetName } from "../compute-icon-id-C42PyoDX.mjs";
|
|
3
|
+
import { t as buildSprite } from "../build-sprite-DEOFEWm0.mjs";
|
|
4
|
+
import { t as transformModule } from "../transform-module-Cabatwdp.mjs";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
//#region src/vite/plugin.ts
|
|
7
7
|
const reactIconsSprite = (options = {}) => {
|
|
8
8
|
const { outputDir } = options;
|
|
9
9
|
const iconSources = createIconSources();
|
|
10
|
+
const excludedIconSources = createExcludedIconSources(options.exclude);
|
|
10
11
|
const collector = createCollector();
|
|
11
12
|
let root = process.cwd();
|
|
12
13
|
return {
|
|
@@ -25,7 +26,7 @@ const reactIconsSprite = (options = {}) => {
|
|
|
25
26
|
try {
|
|
26
27
|
const { code: next, map, anyReplacements } = transformModule(code, id, (pack, exportName) => {
|
|
27
28
|
collector.add(pack, exportName, { importer: cleanId });
|
|
28
|
-
}, iconSources);
|
|
29
|
+
}, iconSources, { excludedSources: excludedIconSources });
|
|
29
30
|
if (!anyReplacements) return null;
|
|
30
31
|
return {
|
|
31
32
|
code: next,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { t as ReactIconsSpritePluginOptions } from "../plugin-options-DYfIgasR.mjs";
|
|
1
2
|
import { LoaderDefinitionFunction } from "webpack";
|
|
2
3
|
//#region src/webpack/loader.d.ts
|
|
3
|
-
|
|
4
|
+
export type ReactIconsSpriteWebpackLoaderOptions = Pick<ReactIconsSpritePluginOptions, 'exclude'>;
|
|
5
|
+
type SpriteLoader = LoaderDefinitionFunction<ReactIconsSpriteWebpackLoaderOptions>;
|
|
6
|
+
declare const reactIconsSpriteLoader: SpriteLoader;
|
|
4
7
|
//#endregion
|
|
5
8
|
export { reactIconsSpriteLoader as default };
|
package/dist/webpack/loader.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as transformModule } from "../transform-module-
|
|
3
|
-
import { t as collector } from "../collector-
|
|
1
|
+
import { a as createIconSources, i as createExcludedIconSources } from "../compute-icon-id-C42PyoDX.mjs";
|
|
2
|
+
import { t as transformModule } from "../transform-module-Cabatwdp.mjs";
|
|
3
|
+
import { t as collector } from "../collector-1bZHiz4N.mjs";
|
|
4
4
|
//#region src/webpack/loader.ts
|
|
5
5
|
const reactIconsSpriteLoader = async function(source) {
|
|
6
6
|
if (this.mode === "development") return source;
|
|
@@ -8,9 +8,11 @@ const reactIconsSpriteLoader = async function(source) {
|
|
|
8
8
|
try {
|
|
9
9
|
if (!/\.(mjs|cjs|js|jsx|ts|tsx)$/i.test(id)) return source;
|
|
10
10
|
const iconSources = createIconSources();
|
|
11
|
+
const { exclude } = this.getOptions();
|
|
12
|
+
const excludedIconSources = createExcludedIconSources(exclude);
|
|
11
13
|
const { code, anyReplacements } = transformModule(String(source), id, (pack, exportName) => {
|
|
12
14
|
collector.add(pack, exportName, { importer: id });
|
|
13
|
-
}, iconSources);
|
|
15
|
+
}, iconSources, { excludedSources: excludedIconSources });
|
|
14
16
|
if (!anyReplacements) return source;
|
|
15
17
|
return code;
|
|
16
18
|
} catch (err) {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { t as ReactIconsSpritePluginOptions } from "../plugin-options-
|
|
1
|
+
import { t as ReactIconsSpritePluginOptions } from "../plugin-options-DYfIgasR.mjs";
|
|
2
2
|
import { Compiler } from "webpack";
|
|
3
3
|
//#region src/webpack/plugin.d.ts
|
|
4
|
-
type ReactIconsSpriteWebpackPluginOptions = ReactIconsSpritePluginOptions
|
|
5
|
-
declare class ReactIconsSpriteWebpackPlugin {
|
|
4
|
+
export type ReactIconsSpriteWebpackPluginOptions = Pick<ReactIconsSpritePluginOptions, 'outputDir'>;
|
|
5
|
+
export declare class ReactIconsSpriteWebpackPlugin {
|
|
6
6
|
private readonly outputDir?;
|
|
7
7
|
constructor(options?: ReactIconsSpriteWebpackPluginOptions);
|
|
8
8
|
apply(compiler: Compiler): void;
|
|
9
9
|
}
|
|
10
|
-
//#endregion
|
|
11
|
-
export { ReactIconsSpriteWebpackPlugin, ReactIconsSpriteWebpackPluginOptions };
|
|
10
|
+
//#endregion
|
package/dist/webpack/plugin.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { REACT_ICONS_SPRITE_URL_PLACEHOLDER } from "../index.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as buildSprite } from "../build-sprite-
|
|
4
|
-
import { t as collector } from "../collector-
|
|
2
|
+
import { o as createSpriteAssetName } from "../compute-icon-id-C42PyoDX.mjs";
|
|
3
|
+
import { t as buildSprite } from "../build-sprite-DEOFEWm0.mjs";
|
|
4
|
+
import { t as collector } from "../collector-1bZHiz4N.mjs";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
//#region src/webpack/plugin.ts
|
|
7
7
|
var ReactIconsSpriteWebpackPlugin = class {
|