react-icons-sprite 1.3.1 → 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-erUJk5tA.mjs +0 -218
- 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
|
@@ -1,854 +0,0 @@
|
|
|
1
|
-
import { a as DEFAULT_ICON_SOURCES, n as normalizePackAlias } from "./compute-icon-id-1Gop_fRM.mjs";
|
|
2
|
-
import MagicString from "magic-string";
|
|
3
|
-
//#region src/transform/edit-applier.ts
|
|
4
|
-
const applyEdits = (code, edits) => {
|
|
5
|
-
const magicString = new MagicString(code);
|
|
6
|
-
for (const edit of edits) {
|
|
7
|
-
if (edit.type === "replace") magicString.overwrite(edit.from, edit.to, edit.value);
|
|
8
|
-
if (edit.type === "insert") magicString.appendLeft(edit.pos, edit.value);
|
|
9
|
-
if (edit.type === "remove") magicString.remove(edit.from, edit.to);
|
|
10
|
-
}
|
|
11
|
-
return magicString;
|
|
12
|
-
};
|
|
13
|
-
const editStart = (edit) => {
|
|
14
|
-
return edit.type === "insert" ? edit.pos : edit.from;
|
|
15
|
-
};
|
|
16
|
-
const applyEditsToString = (code, edits, presorted = false) => {
|
|
17
|
-
if (!edits.length) return code;
|
|
18
|
-
const orderedEdits = presorted ? edits : [...edits].sort((left, right) => {
|
|
19
|
-
const startDelta = editStart(left) - editStart(right);
|
|
20
|
-
if (startDelta !== 0) return startDelta;
|
|
21
|
-
if (left.type === "insert" && right.type !== "insert") return 1;
|
|
22
|
-
if (left.type !== "insert" && right.type === "insert") return -1;
|
|
23
|
-
return 0;
|
|
24
|
-
});
|
|
25
|
-
let result = "";
|
|
26
|
-
let cursor = 0;
|
|
27
|
-
for (const edit of orderedEdits) {
|
|
28
|
-
if (edit.type === "insert") {
|
|
29
|
-
if (edit.pos <= cursor) {
|
|
30
|
-
result += edit.value;
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
result += code.slice(cursor, edit.pos) + edit.value;
|
|
34
|
-
cursor = edit.pos;
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
result += code.slice(cursor, edit.from);
|
|
38
|
-
if (edit.type === "replace") result += edit.value;
|
|
39
|
-
cursor = edit.to;
|
|
40
|
-
}
|
|
41
|
-
return result + code.slice(cursor);
|
|
42
|
-
};
|
|
43
|
-
//#endregion
|
|
44
|
-
//#region src/transform/fast-filter.ts
|
|
45
|
-
const fastFilter = (code) => {
|
|
46
|
-
if (!code.includes("<")) return false;
|
|
47
|
-
if (!code.includes("import")) return false;
|
|
48
|
-
return true;
|
|
49
|
-
};
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/transform/transform-module.ts
|
|
52
|
-
const ICON_SOURCE = "react-icons-sprite";
|
|
53
|
-
const ICON_COMPONENT_NAME = "ReactIconsSpriteIcon";
|
|
54
|
-
const FONTAWESOME_REACT_PACK = "@fortawesome/react-fontawesome";
|
|
55
|
-
const HUGEICONS_REACT_PACK = "@hugeicons/react";
|
|
56
|
-
const isFontAwesomeIconPack = (pack) => {
|
|
57
|
-
return /^@fortawesome\/[\w-]+-svg-icons$/.test(pack);
|
|
58
|
-
};
|
|
59
|
-
const isHugeiconsIconPack = (pack) => {
|
|
60
|
-
return /^@hugeicons\/core-free-icons(?:\/.*)?$/.test(pack);
|
|
61
|
-
};
|
|
62
|
-
const sourceMatches = (source, pack) => {
|
|
63
|
-
source.lastIndex = 0;
|
|
64
|
-
return source.test(pack);
|
|
65
|
-
};
|
|
66
|
-
const IMPORT_RE = /import\s+([^;]+?)\s+from\s+(['"])([^'"]+)\2\s*;?/g;
|
|
67
|
-
const trimRange = (value, offset) => {
|
|
68
|
-
let start = 0;
|
|
69
|
-
let end = value.length;
|
|
70
|
-
while (start < end && /\s/.test(value[start])) start += 1;
|
|
71
|
-
while (end > start && /\s/.test(value[end - 1])) end -= 1;
|
|
72
|
-
return start === end ? null : [offset + start, offset + end];
|
|
73
|
-
};
|
|
74
|
-
const parseNamedSpecifiers = (specifier, specifierOffset, imports) => {
|
|
75
|
-
const start = specifier.indexOf("{");
|
|
76
|
-
const end = specifier.lastIndexOf("}");
|
|
77
|
-
if (start === -1 || end === -1 || end <= start) return;
|
|
78
|
-
let segmentStart = start + 1;
|
|
79
|
-
for (let index = start + 1; index <= end; index += 1) {
|
|
80
|
-
if (index !== end && specifier[index] !== ",") continue;
|
|
81
|
-
const segment = specifier.slice(segmentStart, index);
|
|
82
|
-
const range = trimRange(segment, specifierOffset + segmentStart);
|
|
83
|
-
segmentStart = index + 1;
|
|
84
|
-
if (!range) continue;
|
|
85
|
-
const text = specifier.slice(range[0] - specifierOffset, range[1] - specifierOffset);
|
|
86
|
-
if (text.startsWith("type ")) continue;
|
|
87
|
-
const aliasMatch = /^(.*?)\s+as\s+([A-Za-z_$][\w$]*)$/.exec(text);
|
|
88
|
-
const exportName = aliasMatch ? aliasMatch[1].trim() : text.trim();
|
|
89
|
-
const local = aliasMatch ? aliasMatch[2] : exportName;
|
|
90
|
-
if (exportName && local) imports.push({
|
|
91
|
-
local,
|
|
92
|
-
exportName,
|
|
93
|
-
range
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
const parseImportSpecifiers = (specifier, specifierOffset) => {
|
|
98
|
-
const specifiers = [];
|
|
99
|
-
const braceStart = specifier.indexOf("{");
|
|
100
|
-
const defaultText = (braceStart === -1 ? specifier : specifier.slice(0, braceStart)).replace(/,\s*$/, "");
|
|
101
|
-
const defaultRange = trimRange(defaultText, specifierOffset);
|
|
102
|
-
if (defaultRange && !specifier.slice(defaultRange[0] - specifierOffset, defaultRange[1] - specifierOffset).startsWith("type ")) {
|
|
103
|
-
const local = specifier.slice(defaultRange[0] - specifierOffset, defaultRange[1] - specifierOffset);
|
|
104
|
-
if (local && /^[A-Za-z_$][\w$]*$/.test(local)) specifiers.push({
|
|
105
|
-
local,
|
|
106
|
-
exportName: "default",
|
|
107
|
-
range: defaultRange
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
parseNamedSpecifiers(specifier, specifierOffset, specifiers);
|
|
111
|
-
return specifiers;
|
|
112
|
-
};
|
|
113
|
-
const countImportSpecifiers = (specifier) => {
|
|
114
|
-
let count = 0;
|
|
115
|
-
const braceStart = specifier.indexOf("{");
|
|
116
|
-
if ((braceStart === -1 ? specifier : specifier.slice(0, braceStart)).replace(/,\s*$/, "").trim()) count += 1;
|
|
117
|
-
const braceEnd = specifier.lastIndexOf("}");
|
|
118
|
-
if (braceStart !== -1 && braceEnd > braceStart) {
|
|
119
|
-
const named = specifier.slice(braceStart + 1, braceEnd);
|
|
120
|
-
for (const segment of named.split(",")) if (segment.trim()) count += 1;
|
|
121
|
-
}
|
|
122
|
-
return count;
|
|
123
|
-
};
|
|
124
|
-
const scanImportsDetailed = (code, sources) => {
|
|
125
|
-
const imports = [];
|
|
126
|
-
IMPORT_RE.lastIndex = 0;
|
|
127
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
128
|
-
const [statement, specifier, , pack] = match;
|
|
129
|
-
if (!sources.some((source) => sourceMatches(source, pack))) continue;
|
|
130
|
-
if (specifier.trim().startsWith("type ")) continue;
|
|
131
|
-
const matchStart = match.index;
|
|
132
|
-
const specifierOffset = matchStart + statement.indexOf(specifier);
|
|
133
|
-
const specifiers = parseImportSpecifiers(specifier, specifierOffset);
|
|
134
|
-
if (specifiers.length) imports.push({
|
|
135
|
-
pack,
|
|
136
|
-
declarationRange: [matchStart, matchStart + statement.length],
|
|
137
|
-
specifierRange: [specifierOffset, specifierOffset + specifier.length],
|
|
138
|
-
specifiers,
|
|
139
|
-
specifierCount: countImportSpecifiers(specifier)
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
return imports;
|
|
143
|
-
};
|
|
144
|
-
const buildScannedSymbolTable = (imports) => {
|
|
145
|
-
const items = Object.create(null);
|
|
146
|
-
let size = 0;
|
|
147
|
-
for (const item of imports) {
|
|
148
|
-
const iconIdPrefix = `ri-${normalizePackAlias(item.pack)}-`;
|
|
149
|
-
for (const specifier of item.specifiers) {
|
|
150
|
-
if (items[specifier.local] === void 0) size += 1;
|
|
151
|
-
items[specifier.local] = {
|
|
152
|
-
pack: item.pack,
|
|
153
|
-
exportName: specifier.exportName,
|
|
154
|
-
iconId: iconIdPrefix + specifier.exportName
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
items,
|
|
160
|
-
size
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
const scanSpriteIconImport = (code) => {
|
|
164
|
-
IMPORT_RE.lastIndex = 0;
|
|
165
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
166
|
-
const [, specifier, , source] = match;
|
|
167
|
-
if (source !== "react-icons-sprite") continue;
|
|
168
|
-
const specifiers = [];
|
|
169
|
-
parseNamedSpecifiers(specifier, match.index + match[0].indexOf(specifier), specifiers);
|
|
170
|
-
for (const item of specifiers) if (item.exportName === "ReactIconsSpriteIcon") return {
|
|
171
|
-
hasImport: true,
|
|
172
|
-
localName: item.local
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return {
|
|
176
|
-
hasImport: false,
|
|
177
|
-
localName: ICON_COMPONENT_NAME
|
|
178
|
-
};
|
|
179
|
-
};
|
|
180
|
-
const escapeRegExp = (value) => {
|
|
181
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
182
|
-
};
|
|
183
|
-
const isIdentifierStart = (char) => {
|
|
184
|
-
return char !== void 0 && (char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char === "_" || char === "$");
|
|
185
|
-
};
|
|
186
|
-
const isIdentifierPart = (char) => {
|
|
187
|
-
return char !== void 0 && (isIdentifierStart(char) || char >= "0" && char <= "9");
|
|
188
|
-
};
|
|
189
|
-
const isWhitespace = (char) => {
|
|
190
|
-
return char === " " || char === " " || char === "\n" || char === "\r" || char === "\f";
|
|
191
|
-
};
|
|
192
|
-
const isWhitespaceCode = (code) => {
|
|
193
|
-
return code === 32 || code === 9 || code === 10 || code === 13 || code === 12;
|
|
194
|
-
};
|
|
195
|
-
const scanJsxIconEdits = (code, symbols, componentName, usedSymbols, register, hasAnyIconId) => {
|
|
196
|
-
if (symbols.size === 0) return {
|
|
197
|
-
edits: [],
|
|
198
|
-
count: 0
|
|
199
|
-
};
|
|
200
|
-
const edits = [];
|
|
201
|
-
let count = 0;
|
|
202
|
-
for (let index = code.indexOf("<"); index !== -1; index = code.indexOf("<", index + 1)) {
|
|
203
|
-
let cursor = index + 1;
|
|
204
|
-
while (isWhitespace(code[cursor])) cursor += 1;
|
|
205
|
-
const closing = code[cursor] === "/";
|
|
206
|
-
if (closing) {
|
|
207
|
-
cursor += 1;
|
|
208
|
-
while (isWhitespace(code[cursor])) cursor += 1;
|
|
209
|
-
}
|
|
210
|
-
if (!isIdentifierStart(code[cursor])) continue;
|
|
211
|
-
const localStart = cursor;
|
|
212
|
-
cursor += 1;
|
|
213
|
-
while (isIdentifierPart(code[cursor])) cursor += 1;
|
|
214
|
-
const local = code.slice(localStart, cursor);
|
|
215
|
-
const symbol = symbols.items[local];
|
|
216
|
-
if (!symbol) continue;
|
|
217
|
-
let hasIconId = false;
|
|
218
|
-
if (hasAnyIconId && !closing) {
|
|
219
|
-
const tagEnd = findJsxOpeningTagEnd(code, cursor);
|
|
220
|
-
hasIconId = tagEnd !== -1 && hasIconIdAttribute(code, cursor, tagEnd);
|
|
221
|
-
}
|
|
222
|
-
if (closing || hasIconId) edits.push({
|
|
223
|
-
type: "replace",
|
|
224
|
-
from: localStart,
|
|
225
|
-
to: cursor,
|
|
226
|
-
value: componentName
|
|
227
|
-
});
|
|
228
|
-
else edits.push({
|
|
229
|
-
type: "replace",
|
|
230
|
-
from: localStart,
|
|
231
|
-
to: cursor,
|
|
232
|
-
value: `${componentName} iconId="${symbol.iconId}"`
|
|
233
|
-
});
|
|
234
|
-
count += 1;
|
|
235
|
-
if (!closing) {
|
|
236
|
-
usedSymbols.add(local);
|
|
237
|
-
register(symbol.pack, symbol.exportName);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return {
|
|
241
|
-
edits,
|
|
242
|
-
count
|
|
243
|
-
};
|
|
244
|
-
};
|
|
245
|
-
const scanJsxReferencePropEdits = (code, symbols, componentName, usedSymbols, register, ignoredComponentLocals) => {
|
|
246
|
-
if (symbols.size === 0) return {
|
|
247
|
-
edits: [],
|
|
248
|
-
count: 0
|
|
249
|
-
};
|
|
250
|
-
const edits = [];
|
|
251
|
-
let count = 0;
|
|
252
|
-
for (let index = code.indexOf("<"); index !== -1; index = code.indexOf("<", index + 1)) {
|
|
253
|
-
let cursor = index + 1;
|
|
254
|
-
while (isWhitespace(code[cursor])) cursor += 1;
|
|
255
|
-
if (code[cursor] === "/") continue;
|
|
256
|
-
if (!isIdentifierStart(code[cursor])) continue;
|
|
257
|
-
const componentStart = cursor;
|
|
258
|
-
cursor += 1;
|
|
259
|
-
while (isIdentifierPart(code[cursor])) cursor += 1;
|
|
260
|
-
const componentLocal = code.slice(componentStart, cursor);
|
|
261
|
-
if (symbols.items[componentLocal] || ignoredComponentLocals.has(componentLocal)) continue;
|
|
262
|
-
const tagEnd = findJsxOpeningTagEnd(code, cursor);
|
|
263
|
-
if (tagEnd === -1) continue;
|
|
264
|
-
let attributeCursor = cursor;
|
|
265
|
-
while (attributeCursor < tagEnd) {
|
|
266
|
-
while (isWhitespace(code[attributeCursor])) attributeCursor += 1;
|
|
267
|
-
if (attributeCursor >= tagEnd || code[attributeCursor] === "/") break;
|
|
268
|
-
if (code[attributeCursor] === "{") {
|
|
269
|
-
const expressionEnd = findJsxExpressionEnd(code, attributeCursor);
|
|
270
|
-
attributeCursor = expressionEnd === -1 ? tagEnd : expressionEnd + 1;
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
if (!isIdentifierStart(code[attributeCursor])) {
|
|
274
|
-
attributeCursor += 1;
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
|
-
attributeCursor += 1;
|
|
278
|
-
while (isJsxAttributeNamePart(code[attributeCursor])) attributeCursor += 1;
|
|
279
|
-
while (isWhitespace(code[attributeCursor])) attributeCursor += 1;
|
|
280
|
-
if (code[attributeCursor] !== "=") continue;
|
|
281
|
-
attributeCursor += 1;
|
|
282
|
-
while (isWhitespace(code[attributeCursor])) attributeCursor += 1;
|
|
283
|
-
const valueStart = attributeCursor;
|
|
284
|
-
if (code[valueStart] === "\"" || code[valueStart] === "'") {
|
|
285
|
-
attributeCursor = skipQuotedString(code, valueStart);
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (code[valueStart] !== "{") continue;
|
|
289
|
-
const expressionEnd = findJsxExpressionEnd(code, valueStart);
|
|
290
|
-
if (expressionEnd === -1 || expressionEnd > tagEnd) {
|
|
291
|
-
attributeCursor = tagEnd;
|
|
292
|
-
continue;
|
|
293
|
-
}
|
|
294
|
-
attributeCursor = expressionEnd + 1;
|
|
295
|
-
const expression = code.slice(valueStart + 1, expressionEnd);
|
|
296
|
-
const iconMatch = /^(\s*)([A-Za-z_$][\w$]*)(\s*)$/.exec(expression);
|
|
297
|
-
if (!iconMatch) continue;
|
|
298
|
-
const iconLocal = iconMatch[2];
|
|
299
|
-
const symbol = symbols.items[iconLocal];
|
|
300
|
-
if (!symbol || isFontAwesomeIconPack(symbol.pack) || isHugeiconsIconPack(symbol.pack)) continue;
|
|
301
|
-
const iconLocalStart = valueStart + 1 + iconMatch[1].length;
|
|
302
|
-
edits.push({
|
|
303
|
-
type: "replace",
|
|
304
|
-
from: iconLocalStart,
|
|
305
|
-
to: iconLocalStart + iconLocal.length,
|
|
306
|
-
value: `(props) => <${componentName} {...props} iconId="${symbol.iconId}" />`
|
|
307
|
-
});
|
|
308
|
-
count += 1;
|
|
309
|
-
usedSymbols.add(iconLocal);
|
|
310
|
-
register(symbol.pack, symbol.exportName);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return {
|
|
314
|
-
edits,
|
|
315
|
-
count
|
|
316
|
-
};
|
|
317
|
-
};
|
|
318
|
-
const isJsxAttributeNamePart = (char) => {
|
|
319
|
-
return isIdentifierPart(char) || char === "-" || char === "." || char === ":";
|
|
320
|
-
};
|
|
321
|
-
const skipQuotedString = (code, start) => {
|
|
322
|
-
const quote = code[start];
|
|
323
|
-
let cursor = start + 1;
|
|
324
|
-
while (cursor < code.length) {
|
|
325
|
-
if (code[cursor] === "\\") {
|
|
326
|
-
cursor += 2;
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
if (code[cursor] === quote) return cursor + 1;
|
|
330
|
-
cursor += 1;
|
|
331
|
-
}
|
|
332
|
-
return code.length;
|
|
333
|
-
};
|
|
334
|
-
const findJsxExpressionEnd = (code, start) => {
|
|
335
|
-
let quote = null;
|
|
336
|
-
let braceDepth = 0;
|
|
337
|
-
for (let index = start; index < code.length; index += 1) {
|
|
338
|
-
const char = code[index];
|
|
339
|
-
if (quote) {
|
|
340
|
-
if (char === "\\") {
|
|
341
|
-
index += 1;
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
if (char === quote) quote = null;
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
|
-
if (char === "\"" || char === "'" || char === "`") {
|
|
348
|
-
quote = char;
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
if (char === "{") {
|
|
352
|
-
braceDepth += 1;
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
if (char === "}") {
|
|
356
|
-
braceDepth -= 1;
|
|
357
|
-
if (braceDepth === 0) return index;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return -1;
|
|
361
|
-
};
|
|
362
|
-
const hasIconIdAttribute = (code, start, end) => {
|
|
363
|
-
for (let index = start; index < end; index += 1) {
|
|
364
|
-
if (code.charCodeAt(index) !== 105 || code.charCodeAt(index + 1) !== 99 || code.charCodeAt(index + 2) !== 111 || code.charCodeAt(index + 3) !== 110 || code.charCodeAt(index + 4) !== 73 || code.charCodeAt(index + 5) !== 100) continue;
|
|
365
|
-
if (isIdentifierPart(code[index - 1]) || isIdentifierPart(code[index + 6])) continue;
|
|
366
|
-
let cursor = index + 6;
|
|
367
|
-
while (isWhitespace(code[cursor])) cursor += 1;
|
|
368
|
-
if (code[cursor] === "=") return true;
|
|
369
|
-
}
|
|
370
|
-
return false;
|
|
371
|
-
};
|
|
372
|
-
const findJsxOpeningTagEnd = (code, start) => {
|
|
373
|
-
let quote = null;
|
|
374
|
-
let braceDepth = 0;
|
|
375
|
-
for (let index = start; index < code.length; index += 1) {
|
|
376
|
-
const char = code[index];
|
|
377
|
-
if (quote) {
|
|
378
|
-
if (char === quote && code[index - 1] !== "\\") quote = null;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
if (char === "\"" || char === "'" || char === "`") {
|
|
382
|
-
quote = char;
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
if (char === "{") {
|
|
386
|
-
braceDepth += 1;
|
|
387
|
-
continue;
|
|
388
|
-
}
|
|
389
|
-
if (char === "}") {
|
|
390
|
-
braceDepth -= 1;
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
if (char === ">" && braceDepth === 0) return index;
|
|
394
|
-
}
|
|
395
|
-
return -1;
|
|
396
|
-
};
|
|
397
|
-
const scanFontAwesomeComponents = (code) => {
|
|
398
|
-
const locals = /* @__PURE__ */ new Set();
|
|
399
|
-
IMPORT_RE.lastIndex = 0;
|
|
400
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
401
|
-
const [, specifier, , source] = match;
|
|
402
|
-
if (source !== FONTAWESOME_REACT_PACK) continue;
|
|
403
|
-
const specifiers = [];
|
|
404
|
-
parseNamedSpecifiers(specifier, match.index + match[0].indexOf(specifier), specifiers);
|
|
405
|
-
for (const item of specifiers) if (item.exportName === "FontAwesomeIcon") locals.add(item.local);
|
|
406
|
-
}
|
|
407
|
-
return locals;
|
|
408
|
-
};
|
|
409
|
-
const scanFontAwesomeUsages = (code, symbols, componentLocals) => {
|
|
410
|
-
if (!componentLocals.size) return [];
|
|
411
|
-
const names = [...componentLocals].map(escapeRegExp).join("|");
|
|
412
|
-
const tagRe = new RegExp(`<\\s*(${names})\\b`, "g");
|
|
413
|
-
const usages = [];
|
|
414
|
-
for (const match of code.matchAll(tagRe)) {
|
|
415
|
-
const componentLocal = match[1];
|
|
416
|
-
const componentStart = match.index + match[0].lastIndexOf(componentLocal);
|
|
417
|
-
const tagEnd = findJsxOpeningTagEnd(code, componentStart + componentLocal.length);
|
|
418
|
-
if (tagEnd === -1) continue;
|
|
419
|
-
const attributes = code.slice(componentStart + componentLocal.length, tagEnd);
|
|
420
|
-
const iconMatch = /\sicon\s*=\s*\{\s*([A-Za-z_$][\w$]*)\s*\}/.exec(attributes);
|
|
421
|
-
if (!iconMatch || iconMatch.index === void 0) continue;
|
|
422
|
-
const symbol = symbols.items[iconMatch[1]];
|
|
423
|
-
if (!symbol || !isFontAwesomeIconPack(symbol.pack)) continue;
|
|
424
|
-
const attributeStart = componentStart + componentLocal.length + iconMatch.index;
|
|
425
|
-
usages.push({
|
|
426
|
-
componentLocal,
|
|
427
|
-
componentRange: [componentStart, componentStart + componentLocal.length],
|
|
428
|
-
iconAttributeRange: [attributeStart, attributeStart + iconMatch[0].length],
|
|
429
|
-
hasIconId: /\biconId\s*=/.test(attributes),
|
|
430
|
-
iconLocal: iconMatch[1],
|
|
431
|
-
pack: symbol.pack,
|
|
432
|
-
exportName: symbol.exportName,
|
|
433
|
-
iconId: symbol.iconId
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
return usages;
|
|
437
|
-
};
|
|
438
|
-
const scanHugeiconsComponents = (code) => {
|
|
439
|
-
const locals = /* @__PURE__ */ new Set();
|
|
440
|
-
IMPORT_RE.lastIndex = 0;
|
|
441
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
442
|
-
const [, specifier, , source] = match;
|
|
443
|
-
if (source !== HUGEICONS_REACT_PACK) continue;
|
|
444
|
-
const specifiers = [];
|
|
445
|
-
parseNamedSpecifiers(specifier, match.index + match[0].indexOf(specifier), specifiers);
|
|
446
|
-
for (const item of specifiers) if (item.exportName === "HugeiconsIcon") locals.add(item.local);
|
|
447
|
-
}
|
|
448
|
-
return locals;
|
|
449
|
-
};
|
|
450
|
-
const scanHugeiconsUsages = (code, symbols, componentLocals) => {
|
|
451
|
-
if (!componentLocals.size) return [];
|
|
452
|
-
const names = [...componentLocals].map(escapeRegExp).join("|");
|
|
453
|
-
const tagRe = new RegExp(`<\\s*(${names})\\b`, "g");
|
|
454
|
-
const usages = [];
|
|
455
|
-
for (const match of code.matchAll(tagRe)) {
|
|
456
|
-
const componentLocal = match[1];
|
|
457
|
-
const componentStart = match.index + match[0].lastIndexOf(componentLocal);
|
|
458
|
-
const tagEnd = findJsxOpeningTagEnd(code, componentStart + componentLocal.length);
|
|
459
|
-
if (tagEnd === -1) continue;
|
|
460
|
-
const attributes = code.slice(componentStart + componentLocal.length, tagEnd);
|
|
461
|
-
const iconMatch = /\sicon\s*=\s*\{\s*([A-Za-z_$][\w$]*)\s*\}/.exec(attributes);
|
|
462
|
-
if (!iconMatch || iconMatch.index === void 0) continue;
|
|
463
|
-
const symbol = symbols.items[iconMatch[1]];
|
|
464
|
-
if (!symbol || !isHugeiconsIconPack(symbol.pack)) continue;
|
|
465
|
-
const attributeStart = componentStart + componentLocal.length + iconMatch.index;
|
|
466
|
-
usages.push({
|
|
467
|
-
componentLocal,
|
|
468
|
-
componentRange: [componentStart, componentStart + componentLocal.length],
|
|
469
|
-
iconAttributeRange: [attributeStart, attributeStart + iconMatch[0].length],
|
|
470
|
-
iconLocal: iconMatch[1],
|
|
471
|
-
pack: symbol.pack,
|
|
472
|
-
exportName: symbol.exportName,
|
|
473
|
-
iconId: symbol.iconId,
|
|
474
|
-
hasIconId: /\biconId\s*=/.test(attributes)
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
return usages;
|
|
478
|
-
};
|
|
479
|
-
const cleanupScannedImports = (code, imports, usedLocals) => {
|
|
480
|
-
const edits = [];
|
|
481
|
-
for (const item of imports) {
|
|
482
|
-
const usedSpecifiers = item.specifiers.filter((specifier) => usedLocals.has(specifier.local));
|
|
483
|
-
if (!usedSpecifiers.length) continue;
|
|
484
|
-
if (usedSpecifiers.length === item.specifiers.length && item.specifierCount === item.specifiers.length) {
|
|
485
|
-
edits.push({
|
|
486
|
-
type: "remove",
|
|
487
|
-
from: item.declarationRange[0],
|
|
488
|
-
to: extendToLineEnd(code, item.declarationRange[1])
|
|
489
|
-
});
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
const edit = removeImportSpecifiers(code, item, usedLocals);
|
|
493
|
-
if (edit) edits.push(edit);
|
|
494
|
-
}
|
|
495
|
-
return edits;
|
|
496
|
-
};
|
|
497
|
-
const removeImportSpecifiers = (code, item, usedLocals) => {
|
|
498
|
-
const specifierText = code.slice(item.specifierRange[0], item.specifierRange[1]);
|
|
499
|
-
const braceStart = specifierText.indexOf("{");
|
|
500
|
-
const braceEnd = specifierText.lastIndexOf("}");
|
|
501
|
-
const defaultSpecifier = item.specifiers.find((specifier) => specifier.exportName === "default");
|
|
502
|
-
const defaultLocal = (braceStart === -1 ? specifierText : specifierText.slice(0, braceStart)).replace(/,\s*$/, "").trim();
|
|
503
|
-
const parts = [];
|
|
504
|
-
if (defaultLocal && (!defaultSpecifier || !usedLocals.has(defaultSpecifier.local))) parts.push(defaultLocal);
|
|
505
|
-
if (braceStart !== -1 && braceEnd > braceStart) {
|
|
506
|
-
const namedSpecifiers = collectKeptNamedSpecifiers(specifierText.slice(braceStart + 1, braceEnd), usedLocals);
|
|
507
|
-
if (namedSpecifiers.length) parts.push(`{ ${namedSpecifiers.join(", ")} }`);
|
|
508
|
-
}
|
|
509
|
-
if (!parts.length) return {
|
|
510
|
-
type: "remove",
|
|
511
|
-
from: item.declarationRange[0],
|
|
512
|
-
to: extendToLineEnd(code, item.declarationRange[1])
|
|
513
|
-
};
|
|
514
|
-
return {
|
|
515
|
-
type: "replace",
|
|
516
|
-
from: item.specifierRange[0],
|
|
517
|
-
to: item.specifierRange[1],
|
|
518
|
-
value: parts.join(", ")
|
|
519
|
-
};
|
|
520
|
-
};
|
|
521
|
-
const collectKeptNamedSpecifiers = (namedText, usedLocals) => {
|
|
522
|
-
const kept = [];
|
|
523
|
-
let segmentStart = 0;
|
|
524
|
-
for (let index = 0; index <= namedText.length; index += 1) {
|
|
525
|
-
if (index !== namedText.length && namedText[index] !== ",") continue;
|
|
526
|
-
const text = namedText.slice(segmentStart, index).trim();
|
|
527
|
-
segmentStart = index + 1;
|
|
528
|
-
if (!text) continue;
|
|
529
|
-
if (text.startsWith("type ")) {
|
|
530
|
-
kept.push(text);
|
|
531
|
-
continue;
|
|
532
|
-
}
|
|
533
|
-
const aliasMatch = /^(.*?)\s+as\s+([A-Za-z_$][\w$]*)$/.exec(text);
|
|
534
|
-
const local = aliasMatch ? aliasMatch[2] : text;
|
|
535
|
-
if (!usedLocals.has(local)) kept.push(text);
|
|
536
|
-
}
|
|
537
|
-
return kept;
|
|
538
|
-
};
|
|
539
|
-
const cleanupScannedFontAwesomeComponentImports = (code, usedLocals) => {
|
|
540
|
-
const edits = [];
|
|
541
|
-
IMPORT_RE.lastIndex = 0;
|
|
542
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
543
|
-
const [statement, specifier, , source] = match;
|
|
544
|
-
if (source !== FONTAWESOME_REACT_PACK) continue;
|
|
545
|
-
const specifierOffset = match.index + statement.indexOf(specifier);
|
|
546
|
-
const specifiers = parseImportSpecifiers(specifier, specifierOffset);
|
|
547
|
-
const removableSpecifiers = specifiers.filter((item) => item.exportName === "FontAwesomeIcon" && usedLocals.has(item.local));
|
|
548
|
-
if (!removableSpecifiers.length) continue;
|
|
549
|
-
const edit = removeImportSpecifiers(code, {
|
|
550
|
-
pack: source,
|
|
551
|
-
declarationRange: [match.index, match.index + statement.length],
|
|
552
|
-
specifierRange: [specifierOffset, specifierOffset + specifier.length],
|
|
553
|
-
specifiers,
|
|
554
|
-
specifierCount: countImportSpecifiers(specifier)
|
|
555
|
-
}, new Set(removableSpecifiers.map((item) => item.local)));
|
|
556
|
-
if (edit) edits.push(edit);
|
|
557
|
-
}
|
|
558
|
-
return edits;
|
|
559
|
-
};
|
|
560
|
-
const cleanupScannedHugeiconsComponentImports = (code, usedLocals) => {
|
|
561
|
-
const edits = [];
|
|
562
|
-
IMPORT_RE.lastIndex = 0;
|
|
563
|
-
for (const match of code.matchAll(IMPORT_RE)) {
|
|
564
|
-
const [statement, specifier, , source] = match;
|
|
565
|
-
if (source !== HUGEICONS_REACT_PACK) continue;
|
|
566
|
-
const specifierOffset = match.index + statement.indexOf(specifier);
|
|
567
|
-
const specifiers = parseImportSpecifiers(specifier, specifierOffset);
|
|
568
|
-
const removableSpecifiers = specifiers.filter((item) => item.exportName === "HugeiconsIcon" && usedLocals.has(item.local));
|
|
569
|
-
if (!removableSpecifiers.length) continue;
|
|
570
|
-
const edit = removeImportSpecifiers(code, {
|
|
571
|
-
pack: source,
|
|
572
|
-
declarationRange: [match.index, match.index + statement.length],
|
|
573
|
-
specifierRange: [specifierOffset, specifierOffset + specifier.length],
|
|
574
|
-
specifiers,
|
|
575
|
-
specifierCount: countImportSpecifiers(specifier)
|
|
576
|
-
}, new Set(removableSpecifiers.map((item) => item.local)));
|
|
577
|
-
if (edit) edits.push(edit);
|
|
578
|
-
}
|
|
579
|
-
return edits;
|
|
580
|
-
};
|
|
581
|
-
const extendToLineEnd = (code, end) => {
|
|
582
|
-
let to = end;
|
|
583
|
-
while (to < code.length) {
|
|
584
|
-
const char = code.charCodeAt(to);
|
|
585
|
-
if (char !== 32 && char !== 9) break;
|
|
586
|
-
to += 1;
|
|
587
|
-
}
|
|
588
|
-
if (code[to] === "\r" && code[to + 1] === "\n") return to + 2;
|
|
589
|
-
if (code[to] === "\n") return to + 1;
|
|
590
|
-
return to;
|
|
591
|
-
};
|
|
592
|
-
const consumeTrailingWhitespace = (code, start) => {
|
|
593
|
-
let to = start;
|
|
594
|
-
while (to < code.length && isWhitespaceCode(code.charCodeAt(to))) to += 1;
|
|
595
|
-
return to;
|
|
596
|
-
};
|
|
597
|
-
const editRange = (edit) => {
|
|
598
|
-
if (edit.type === "insert") return null;
|
|
599
|
-
return [edit.from, edit.to];
|
|
600
|
-
};
|
|
601
|
-
const rangeContains = ([start, end], index) => {
|
|
602
|
-
return index >= start && index < end;
|
|
603
|
-
};
|
|
604
|
-
const findPreviousJsxTextBoundary = (code, start) => {
|
|
605
|
-
let index = start - 1;
|
|
606
|
-
while (index >= 0) {
|
|
607
|
-
const char = code[index];
|
|
608
|
-
if (char === ">" || char === "<" || char === "{" || char === "}") return index;
|
|
609
|
-
index -= 1;
|
|
610
|
-
}
|
|
611
|
-
return -1;
|
|
612
|
-
};
|
|
613
|
-
const findNextJsxTextBoundary = (code, start) => {
|
|
614
|
-
let index = start;
|
|
615
|
-
while (index < code.length) {
|
|
616
|
-
const char = code[index];
|
|
617
|
-
if (char === "<" || char === "{") return index;
|
|
618
|
-
index += 1;
|
|
619
|
-
}
|
|
620
|
-
return -1;
|
|
621
|
-
};
|
|
622
|
-
const isLikelyJsxTagStart = (code, index) => {
|
|
623
|
-
const next = code[index + 1];
|
|
624
|
-
return next === "/" || next === ">" || isIdentifierStart(next);
|
|
625
|
-
};
|
|
626
|
-
const isLikelyJsxTextIdentifier = (code, start, end) => {
|
|
627
|
-
const previousBoundary = findPreviousJsxTextBoundary(code, start);
|
|
628
|
-
if (previousBoundary === -1 || code[previousBoundary] !== ">" && code[previousBoundary] !== "}") return false;
|
|
629
|
-
const nextBoundary = findNextJsxTextBoundary(code, end);
|
|
630
|
-
if (nextBoundary === -1) return false;
|
|
631
|
-
if (code[nextBoundary] === "<" && !isLikelyJsxTagStart(code, nextBoundary)) return false;
|
|
632
|
-
const text = code.slice(previousBoundary + 1, nextBoundary);
|
|
633
|
-
return !/[=()[\]{};,+*/%|?]/.test(text);
|
|
634
|
-
};
|
|
635
|
-
const collectUsedLocalsOutsideRanges = (code, usedLocals, ignoredRanges) => {
|
|
636
|
-
const ranges = [...ignoredRanges].sort((left, right) => left[0] - right[0]);
|
|
637
|
-
const found = /* @__PURE__ */ new Set();
|
|
638
|
-
let rangeIndex = 0;
|
|
639
|
-
let quote = null;
|
|
640
|
-
let template = false;
|
|
641
|
-
let templateExpressionDepth = 0;
|
|
642
|
-
let lineComment = false;
|
|
643
|
-
let blockComment = false;
|
|
644
|
-
for (let index = 0; index < code.length; index += 1) {
|
|
645
|
-
while (rangeIndex < ranges.length && ranges[rangeIndex][1] <= index) rangeIndex += 1;
|
|
646
|
-
const ignoredRange = ranges[rangeIndex];
|
|
647
|
-
if (ignoredRange && rangeContains(ignoredRange, index)) {
|
|
648
|
-
index = ignoredRange[1] - 1;
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
const char = code[index];
|
|
652
|
-
const next = code[index + 1];
|
|
653
|
-
if (lineComment) {
|
|
654
|
-
if (char === "\n" || char === "\r") lineComment = false;
|
|
655
|
-
continue;
|
|
656
|
-
}
|
|
657
|
-
if (blockComment) {
|
|
658
|
-
if (char === "*" && next === "/") {
|
|
659
|
-
blockComment = false;
|
|
660
|
-
index += 1;
|
|
661
|
-
}
|
|
662
|
-
continue;
|
|
663
|
-
}
|
|
664
|
-
if (quote) {
|
|
665
|
-
if (char === "\\") {
|
|
666
|
-
index += 1;
|
|
667
|
-
continue;
|
|
668
|
-
}
|
|
669
|
-
if (char === quote) quote = null;
|
|
670
|
-
continue;
|
|
671
|
-
}
|
|
672
|
-
if (template && templateExpressionDepth === 0) {
|
|
673
|
-
if (char === "\\") {
|
|
674
|
-
index += 1;
|
|
675
|
-
continue;
|
|
676
|
-
}
|
|
677
|
-
if (char === "`") {
|
|
678
|
-
template = false;
|
|
679
|
-
continue;
|
|
680
|
-
}
|
|
681
|
-
if (char === "$" && next === "{") {
|
|
682
|
-
templateExpressionDepth = 1;
|
|
683
|
-
index += 1;
|
|
684
|
-
}
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
if (char === "/" && next === "/") {
|
|
688
|
-
lineComment = true;
|
|
689
|
-
index += 1;
|
|
690
|
-
continue;
|
|
691
|
-
}
|
|
692
|
-
if (char === "/" && next === "*") {
|
|
693
|
-
blockComment = true;
|
|
694
|
-
index += 1;
|
|
695
|
-
continue;
|
|
696
|
-
}
|
|
697
|
-
if (template && templateExpressionDepth > 0) {
|
|
698
|
-
if (char === "{") templateExpressionDepth += 1;
|
|
699
|
-
if (char === "}") {
|
|
700
|
-
templateExpressionDepth -= 1;
|
|
701
|
-
if (templateExpressionDepth === 0) continue;
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
if (char === "\"" || char === "'") {
|
|
705
|
-
quote = char;
|
|
706
|
-
continue;
|
|
707
|
-
}
|
|
708
|
-
if (char === "`") {
|
|
709
|
-
template = true;
|
|
710
|
-
continue;
|
|
711
|
-
}
|
|
712
|
-
if (!isIdentifierStart(char)) continue;
|
|
713
|
-
const start = index;
|
|
714
|
-
index += 1;
|
|
715
|
-
while (isIdentifierPart(code[index])) index += 1;
|
|
716
|
-
const local = code.slice(start, index);
|
|
717
|
-
if (usedLocals.has(local) && !isLikelyJsxTextIdentifier(code, start, index)) found.add(local);
|
|
718
|
-
index -= 1;
|
|
719
|
-
}
|
|
720
|
-
return found;
|
|
721
|
-
};
|
|
722
|
-
const filterRemovableUsedLocals = (code, imports, usedLocals, usageEdits) => {
|
|
723
|
-
const ignoredRanges = [...imports.map((item) => item.declarationRange), ...usageEdits.flatMap((edit) => {
|
|
724
|
-
const range = editRange(edit);
|
|
725
|
-
return range ? [range] : [];
|
|
726
|
-
})];
|
|
727
|
-
const liveLocals = collectUsedLocalsOutsideRanges(code, usedLocals, ignoredRanges);
|
|
728
|
-
const removable = /* @__PURE__ */ new Set();
|
|
729
|
-
for (const local of usedLocals) if (!liveLocals.has(local)) removable.add(local);
|
|
730
|
-
return removable;
|
|
731
|
-
};
|
|
732
|
-
const transformModule = (code, id, register, sources = DEFAULT_ICON_SOURCES, options = {}) => {
|
|
733
|
-
const { sourceMap = false } = options;
|
|
734
|
-
if (!fastFilter(code)) return {
|
|
735
|
-
code,
|
|
736
|
-
map: null,
|
|
737
|
-
anyReplacements: false
|
|
738
|
-
};
|
|
739
|
-
const scannedImports = scanImportsDetailed(code, sources);
|
|
740
|
-
if (!scannedImports.length) return {
|
|
741
|
-
code,
|
|
742
|
-
map: null,
|
|
743
|
-
anyReplacements: false
|
|
744
|
-
};
|
|
745
|
-
const hasPotentialFontAwesomeUsage = code.includes(FONTAWESOME_REACT_PACK) && scannedImports.some((item) => isFontAwesomeIconPack(item.pack));
|
|
746
|
-
const hasPotentialHugeiconsUsage = code.includes(HUGEICONS_REACT_PACK) && scannedImports.some((item) => isHugeiconsIconPack(item.pack));
|
|
747
|
-
const table = buildScannedSymbolTable(scannedImports);
|
|
748
|
-
if (!table.size) return {
|
|
749
|
-
code,
|
|
750
|
-
map: null,
|
|
751
|
-
anyReplacements: false
|
|
752
|
-
};
|
|
753
|
-
const spriteIconImport = code.includes("react-icons-sprite") ? scanSpriteIconImport(code) : {
|
|
754
|
-
hasImport: false,
|
|
755
|
-
localName: ICON_COMPONENT_NAME
|
|
756
|
-
};
|
|
757
|
-
const used = /* @__PURE__ */ new Set();
|
|
758
|
-
const fontAwesomeComponents = hasPotentialFontAwesomeUsage ? scanFontAwesomeComponents(code) : /* @__PURE__ */ new Set();
|
|
759
|
-
const hugeiconsComponents = hasPotentialHugeiconsUsage ? scanHugeiconsComponents(code) : /* @__PURE__ */ new Set();
|
|
760
|
-
const usedFontAwesomeComponents = /* @__PURE__ */ new Set();
|
|
761
|
-
const usedHugeiconsComponents = /* @__PURE__ */ new Set();
|
|
762
|
-
const ignoredIconPropComponentLocals = /* @__PURE__ */ new Set([...fontAwesomeComponents, ...hugeiconsComponents]);
|
|
763
|
-
const jsxScan = scanJsxIconEdits(code, table, spriteIconImport.localName, used, register, code.includes("iconId"));
|
|
764
|
-
const referencePropScan = scanJsxReferencePropEdits(code, table, spriteIconImport.localName, used, register, ignoredIconPropComponentLocals);
|
|
765
|
-
const fontAwesomeUsages = hasPotentialFontAwesomeUsage ? scanFontAwesomeUsages(code, table, fontAwesomeComponents) : [];
|
|
766
|
-
const hugeiconsUsages = hasPotentialHugeiconsUsage ? scanHugeiconsUsages(code, table, hugeiconsComponents) : [];
|
|
767
|
-
if (jsxScan.count === 0 && referencePropScan.count === 0 && !fontAwesomeUsages.length && !hugeiconsUsages.length) return {
|
|
768
|
-
code,
|
|
769
|
-
map: null,
|
|
770
|
-
anyReplacements: false
|
|
771
|
-
};
|
|
772
|
-
const edits = [...jsxScan.edits, ...referencePropScan.edits];
|
|
773
|
-
const registeredFontAwesomeIcons = /* @__PURE__ */ new Set();
|
|
774
|
-
for (const usage of fontAwesomeUsages) {
|
|
775
|
-
edits.push({
|
|
776
|
-
type: "replace",
|
|
777
|
-
from: usage.componentRange[0],
|
|
778
|
-
to: usage.componentRange[1],
|
|
779
|
-
value: spriteIconImport.localName
|
|
780
|
-
});
|
|
781
|
-
if (!usage.hasIconId) edits.push({
|
|
782
|
-
type: "insert",
|
|
783
|
-
pos: usage.componentRange[1],
|
|
784
|
-
value: ` iconId="${usage.iconId}"`
|
|
785
|
-
});
|
|
786
|
-
edits.push({
|
|
787
|
-
type: "remove",
|
|
788
|
-
from: usage.iconAttributeRange[0],
|
|
789
|
-
to: consumeTrailingWhitespace(code, usage.iconAttributeRange[1])
|
|
790
|
-
});
|
|
791
|
-
used.add(usage.iconLocal);
|
|
792
|
-
usedFontAwesomeComponents.add(usage.componentLocal);
|
|
793
|
-
const key = `${usage.pack}:${usage.exportName}`;
|
|
794
|
-
if (!registeredFontAwesomeIcons.has(key)) {
|
|
795
|
-
registeredFontAwesomeIcons.add(key);
|
|
796
|
-
register(usage.pack, usage.exportName);
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
const registeredHugeiconsIcons = /* @__PURE__ */ new Set();
|
|
800
|
-
for (const usage of hugeiconsUsages) {
|
|
801
|
-
edits.push({
|
|
802
|
-
type: "replace",
|
|
803
|
-
from: usage.componentRange[0],
|
|
804
|
-
to: usage.componentRange[1],
|
|
805
|
-
value: spriteIconImport.localName
|
|
806
|
-
});
|
|
807
|
-
if (!usage.hasIconId) edits.push({
|
|
808
|
-
type: "insert",
|
|
809
|
-
pos: usage.componentRange[1],
|
|
810
|
-
value: ` iconId="${usage.iconId}"`
|
|
811
|
-
});
|
|
812
|
-
edits.push({
|
|
813
|
-
type: "remove",
|
|
814
|
-
from: usage.iconAttributeRange[0],
|
|
815
|
-
to: consumeTrailingWhitespace(code, usage.iconAttributeRange[1])
|
|
816
|
-
});
|
|
817
|
-
used.add(usage.iconLocal);
|
|
818
|
-
usedHugeiconsComponents.add(usage.componentLocal);
|
|
819
|
-
const key = `${usage.pack}:${usage.exportName}`;
|
|
820
|
-
if (!registeredHugeiconsIcons.has(key)) {
|
|
821
|
-
registeredHugeiconsIcons.add(key);
|
|
822
|
-
register(usage.pack, usage.exportName);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
const removableUsed = filterRemovableUsedLocals(code, scannedImports, used, edits);
|
|
826
|
-
const cleanupEdits = cleanupScannedImports(code, scannedImports, removableUsed);
|
|
827
|
-
const cleanupFontAwesomeEdits = usedFontAwesomeComponents.size ? cleanupScannedFontAwesomeComponentImports(code, usedFontAwesomeComponents) : [];
|
|
828
|
-
const cleanupHugeiconsEdits = usedHugeiconsComponents.size ? cleanupScannedHugeiconsComponentImports(code, usedHugeiconsComponents) : [];
|
|
829
|
-
const canUsePresortedEdits = referencePropScan.count === 0 && cleanupFontAwesomeEdits.length === 0 && cleanupHugeiconsEdits.length === 0;
|
|
830
|
-
const allEdits = canUsePresortedEdits ? [...cleanupEdits, ...edits] : [
|
|
831
|
-
...edits,
|
|
832
|
-
...cleanupEdits,
|
|
833
|
-
...cleanupFontAwesomeEdits,
|
|
834
|
-
...cleanupHugeiconsEdits
|
|
835
|
-
];
|
|
836
|
-
const importPrefix = `import { ${ICON_COMPONENT_NAME} } from "${ICON_SOURCE}";\n`;
|
|
837
|
-
if (!sourceMap) return {
|
|
838
|
-
code: `${spriteIconImport.hasImport ? "" : importPrefix}${applyEditsToString(code, allEdits, canUsePresortedEdits)}`,
|
|
839
|
-
map: null,
|
|
840
|
-
anyReplacements: true
|
|
841
|
-
};
|
|
842
|
-
const magicString = applyEdits(code, allEdits);
|
|
843
|
-
if (!spriteIconImport.hasImport) magicString.prepend(importPrefix);
|
|
844
|
-
return {
|
|
845
|
-
code: magicString.toString(),
|
|
846
|
-
map: sourceMap ? magicString.generateMap({
|
|
847
|
-
source: id,
|
|
848
|
-
hires: true
|
|
849
|
-
}) : null,
|
|
850
|
-
anyReplacements: true
|
|
851
|
-
};
|
|
852
|
-
};
|
|
853
|
-
//#endregion
|
|
854
|
-
export { transformModule as t };
|