@hugeicons/migrate-core 0.1.0 → 0.1.2

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.
@@ -3,14 +3,16 @@
3
3
  * Contains exact and alias mappings from source libraries to Hugeicons
4
4
  *
5
5
  * Uses auto-generated hugeicons-map.json for accurate mappings
6
+ * Also loads library-specific mappings from the mappings/ directory
6
7
  */
7
- import { readFileSync } from 'node:fs';
8
+ import { readFileSync, existsSync } from 'node:fs';
8
9
  import { fileURLToPath } from 'node:url';
9
10
  import { dirname, join } from 'node:path';
10
11
  // Load the JSON file
11
12
  const __filename = fileURLToPath(import.meta.url);
12
13
  const __dirname = dirname(__filename);
13
14
  const mapPath = join(__dirname, 'hugeicons-map.json');
15
+ const mappingsDir = join(__dirname, 'mappings');
14
16
  let ICON_MAP;
15
17
  try {
16
18
  const content = readFileSync(mapPath, 'utf-8');
@@ -25,131 +27,206 @@ catch {
25
27
  icons: {},
26
28
  aliasMap: {},
27
29
  lucideMap: {},
30
+ fontawesomeMap: {},
28
31
  };
29
32
  }
30
33
  // ============================================================================
34
+ // Load Library-Specific Mapping Files (generated by generate-library-maps.py)
35
+ // ============================================================================
36
+ /**
37
+ * Load a library mapping file from the mappings/ directory
38
+ * Returns an empty object if the file doesn't exist
39
+ */
40
+ function loadLibraryMapping(libraryName) {
41
+ const filePath = join(mappingsDir, `${libraryName}.json`);
42
+ try {
43
+ if (existsSync(filePath)) {
44
+ const content = readFileSync(filePath, 'utf-8');
45
+ return JSON.parse(content);
46
+ }
47
+ }
48
+ catch {
49
+ // Ignore errors, return empty mapping
50
+ }
51
+ return {};
52
+ }
53
+ // Generated library mappings (source icon -> hugeicon)
54
+ // These are the primary mappings, generated by AI and validated
55
+ const GENERATED_MAPPINGS = {
56
+ fontawesome: loadLibraryMapping('fontawesome'),
57
+ lucide: loadLibraryMapping('lucide'),
58
+ heroicons: loadLibraryMapping('heroicons'),
59
+ material: loadLibraryMapping('material'),
60
+ feather: loadLibraryMapping('feather'),
61
+ tabler: loadLibraryMapping('tabler'),
62
+ phosphor: loadLibraryMapping('phosphor'),
63
+ };
64
+ /**
65
+ * Get the count of generated mappings for a library
66
+ */
67
+ export function getGeneratedMappingCount(library) {
68
+ const mappings = GENERATED_MAPPINGS[library];
69
+ return mappings ? Object.keys(mappings).length : 0;
70
+ }
71
+ /**
72
+ * Get mapping from generated library file
73
+ * This is checked FIRST before manual mappings
74
+ */
75
+ function getGeneratedMapping(library, iconName) {
76
+ const mappings = GENERATED_MAPPINGS[library];
77
+ return mappings?.[iconName];
78
+ }
79
+ // ============================================================================
31
80
  // FontAwesome Mappings (manual - these icons have different naming conventions)
32
81
  // ============================================================================
33
82
  const FONTAWESOME_MAPPINGS = {
34
- // Solid icons (fa- prefix style)
83
+ // NOTE: These mappings are validated against real Hugeicons at runtime
84
+ // The getFontAwesomeMapping function will fuzzy-match if these don't exist
85
+ // Arrows & Navigation
35
86
  'faArrowDown': 'ArrowDown01Icon',
36
87
  'faArrowLeft': 'ArrowLeft01Icon',
37
88
  'faArrowRight': 'ArrowRight01Icon',
38
89
  'faArrowUp': 'ArrowUp01Icon',
39
- 'faBell': 'Notification01Icon',
40
- 'faBolt': 'FlashOnIcon',
41
- 'faBookmark': 'Bookmark01Icon',
42
- 'faCalendar': 'Calendar01Icon',
43
- 'faCalendarAlt': 'Calendar01Icon',
44
- 'faCamera': 'Camera01Icon',
45
- 'faCheck': 'Tick01Icon',
46
- 'faCheckCircle': 'CheckmarkCircle01Icon',
47
90
  'faChevronDown': 'ArrowDown01Icon',
48
91
  'faChevronLeft': 'ArrowLeft01Icon',
49
92
  'faChevronRight': 'ArrowRight01Icon',
50
93
  'faChevronUp': 'ArrowUp01Icon',
51
- 'faCircle': 'CircleIcon',
52
- 'faClock': 'Clock01Icon',
53
- 'faCloud': 'Cloud01Icon',
54
- 'faCog': 'Settings01Icon',
55
- 'faCogs': 'Settings01Icon',
94
+ // Actions
95
+ 'faCheck': 'Tick01Icon',
96
+ 'faCheckCircle': 'CheckmarkCircle01Icon',
97
+ 'faCircleCheck': 'CheckmarkCircle01Icon',
98
+ 'faTimes': 'Cancel01Icon',
99
+ 'faXmark': 'Cancel01Icon',
100
+ 'faClose': 'Cancel01Icon',
101
+ 'faRemove': 'Cancel01Icon',
102
+ 'faTimesCircle': 'CancelCircleIcon',
103
+ 'faCircleXmark': 'CancelCircleIcon',
104
+ 'faPlus': 'Add01Icon',
105
+ 'faPlusCircle': 'AddCircleIcon',
106
+ 'faCirclePlus': 'AddCircleIcon',
107
+ 'faMinus': 'MinusSignIcon',
108
+ 'faMinusCircle': 'MinusSignCircleIcon',
109
+ 'faCircleMinus': 'MinusSignCircleIcon',
110
+ // User & Auth (using correct names)
111
+ 'faUser': 'UserIcon', // UserIcon exists, not User01Icon
112
+ 'faUserPlus': 'UserAdd01Icon', // UserAdd01Icon is the actual name
113
+ 'faUsers': 'UserGroupIcon',
114
+ 'faUserCircle': 'UserCircleIcon',
115
+ 'faCircleUser': 'UserCircleIcon',
116
+ 'faSignIn': 'Login01Icon',
117
+ 'faSignInAlt': 'Login01Icon',
118
+ 'faRightToBracket': 'Login01Icon',
119
+ 'faArrowRightToBracket': 'Login01Icon',
120
+ 'faSignOut': 'Logout01Icon',
121
+ 'faSignOutAlt': 'Logout01Icon',
122
+ 'faRightFromBracket': 'Logout01Icon',
123
+ 'faArrowRightFromBracket': 'Logout01Icon',
124
+ // Communication
125
+ 'faEnvelope': 'Mail01Icon',
56
126
  'faComment': 'Comment01Icon',
57
127
  'faComments': 'Comment01Icon',
128
+ 'faPhone': 'Call01Icon',
129
+ // Media
130
+ 'faImage': 'Image01Icon',
131
+ 'faCamera': 'Camera01Icon',
132
+ 'faVideo': 'Video01Icon',
133
+ 'faPlay': 'PlayIcon',
134
+ 'faPause': 'PauseIcon',
135
+ 'faStop': 'StopIcon',
136
+ 'faVolumeUp': 'VolumeHighIcon',
137
+ 'faVolumeMute': 'VolumeMute01Icon', // VolumeMute01Icon is the actual name
138
+ // Files & Folders
139
+ 'faFile': 'File01Icon',
140
+ 'faFileAlt': 'File01Icon',
141
+ 'faFolder': 'Folder01Icon',
142
+ 'faFolderOpen': 'FolderOpenIcon',
58
143
  'faCopy': 'Copy01Icon',
59
- 'faCreditCard': 'CreditCardIcon',
144
+ 'faClipboard': 'ClipboardIcon',
60
145
  'faDownload': 'Download01Icon',
146
+ 'faUpload': 'Upload01Icon',
147
+ 'faSave': 'FloppyDiskIcon',
148
+ 'faFloppyDisk': 'FloppyDiskIcon',
149
+ // UI & Interface
150
+ 'faBars': 'Menu01Icon',
151
+ 'faNavicon': 'Menu01Icon',
152
+ 'faCog': 'Settings01Icon',
153
+ 'faCogs': 'Settings01Icon',
154
+ 'faGear': 'Settings01Icon',
155
+ 'faGears': 'Settings01Icon',
156
+ 'faFilter': 'FilterIcon',
157
+ 'faSearch': 'Search01Icon',
158
+ 'faMagnifyingGlass': 'Search01Icon',
61
159
  'faEdit': 'Edit01Icon',
62
- 'faEnvelope': 'Mail01Icon',
160
+ 'faPen': 'Edit01Icon',
161
+ 'faPenToSquare': 'Edit01Icon',
162
+ 'faTrash': 'Delete01Icon',
163
+ 'faTrashAlt': 'Delete01Icon',
164
+ 'faTrashCan': 'Delete01Icon',
165
+ 'faRefresh': 'RefreshIcon',
166
+ 'faRotate': 'RefreshIcon',
167
+ 'faRotateRight': 'RefreshIcon',
168
+ // Status & Alerts
169
+ 'faBell': 'Notification01Icon',
63
170
  'faExclamation': 'AlertCircleIcon',
64
171
  'faExclamationCircle': 'AlertCircleIcon',
65
- 'faExclamationTriangle': 'AlertTriangleIcon',
66
- 'faExternalLink': 'LinkSquare01Icon',
67
- 'faExternalLinkAlt': 'LinkSquare01Icon',
68
- 'faEye': 'View01Icon',
69
- 'faEyeSlash': 'ViewOffIcon',
70
- 'faFile': 'File01Icon',
71
- 'faFileAlt': 'FileAttachmentIcon',
72
- 'faFilter': 'Filter01Icon',
73
- 'faFolder': 'Folder01Icon',
74
- 'faFolderOpen': 'FolderOpenIcon',
75
- 'faGlobe': 'GlobeIcon',
76
- 'faHeart': 'Favourite01Icon',
77
- 'faHome': 'Home01Icon',
78
- 'faImage': 'Image01Icon',
172
+ 'faExclamationTriangle': 'Alert01Icon',
79
173
  'faInfo': 'InformationCircleIcon',
80
174
  'faInfoCircle': 'InformationCircleIcon',
81
- 'faLink': 'Link01Icon',
82
- 'faList': 'ListIcon',
83
- 'faLock': 'SquareLock01Icon',
84
- 'faMapMarker': 'Location01Icon',
85
- 'faMapMarkerAlt': 'Location01Icon',
86
- 'faMinus': 'MinusSign01Icon',
87
- 'faMoon': 'Moon01Icon',
88
- 'faPause': 'PauseIcon',
89
- 'faPen': 'Edit01Icon',
90
- 'faPhone': 'Call01Icon',
91
- 'faPlay': 'Play01Icon',
92
- 'faPlus': 'Add01Icon',
93
- 'faPrint': 'Printer01Icon',
175
+ 'faCircleInfo': 'InformationCircleIcon',
94
176
  'faQuestion': 'HelpCircleIcon',
95
177
  'faQuestionCircle': 'HelpCircleIcon',
96
- 'faRefresh': 'Refresh01Icon',
97
- 'faSearch': 'Search01Icon',
98
- 'faShare': 'Share01Icon',
99
- 'faShield': 'ShieldIcon',
100
- 'faShoppingBag': 'ShoppingBag01Icon',
101
- 'faShoppingCart': 'ShoppingCart01Icon',
102
- 'faSignIn': 'Login01Icon',
103
- 'faSignInAlt': 'Login01Icon',
104
- 'faSignOut': 'Logout01Icon',
105
- 'faSignOutAlt': 'Logout01Icon',
106
- 'faStar': 'Star01Icon',
107
- 'faStop': 'Stop01Icon',
108
- 'faSun': 'Sun01Icon',
178
+ 'faCircleQuestion': 'HelpCircleIcon',
179
+ // Objects
180
+ 'faHome': 'Home01Icon',
181
+ 'faHouse': 'Home01Icon',
182
+ 'faCalendar': 'Calendar01Icon',
183
+ 'faCalendarAlt': 'Calendar01Icon',
184
+ 'faClock': 'Clock01Icon',
185
+ 'faHeart': 'FavouriteIcon',
186
+ 'faStar': 'StarIcon',
187
+ 'faBookmark': 'Bookmark01Icon',
109
188
  'faTag': 'Tag01Icon',
110
189
  'faTags': 'Tag01Icon',
111
- 'faTimes': 'Cancel01Icon',
112
- 'faTimesCircle': 'CancelCircleIcon',
113
- 'faTrash': 'Delete01Icon',
114
- 'faTrashAlt': 'Delete02Icon',
190
+ 'faLink': 'Link01Icon',
191
+ 'faExternalLink': 'LinkSquare01Icon',
192
+ 'faExternalLinkAlt': 'LinkSquare01Icon',
193
+ 'faGlobe': 'GlobeIcon',
194
+ 'faMapMarker': 'Location01Icon',
195
+ 'faMapMarkerAlt': 'Location01Icon',
196
+ 'faLock': 'SquareLock01Icon',
115
197
  'faUnlock': 'SquareUnlock01Icon',
116
- 'faUpload': 'Upload01Icon',
117
- 'faUser': 'User01Icon',
118
- 'faUserPlus': 'UserAdd01Icon',
119
- 'faUsers': 'UserGroup01Icon',
120
- 'faVideo': 'Video01Icon',
121
- 'faVolumeUp': 'Volume01Icon',
122
- 'faVolumeMute': 'VolumeMute01Icon',
198
+ 'faKey': 'Key01Icon',
199
+ 'faShield': 'SecurityIcon',
200
+ 'faEye': 'ViewIcon',
201
+ 'faEyeSlash': 'ViewOffIcon',
202
+ 'faSun': 'Sun01Icon',
203
+ 'faMoon': 'Moon01Icon',
204
+ 'faCloud': 'Cloud01Icon',
205
+ 'faBolt': 'FlashIcon',
123
206
  'faWifi': 'Wifi01Icon',
124
- 'faXmark': 'Cancel01Icon',
125
- 'faGear': 'Settings01Icon',
126
- 'faGears': 'Settings01Icon',
127
- 'faBars': 'Menu01Icon',
128
- 'faNavicon': 'Menu01Icon',
129
- 'faRemove': 'Cancel01Icon',
130
- 'faCircleInfo': 'InformationCircleIcon',
131
- 'faCircleQuestion': 'HelpCircleIcon',
132
- 'faCircleCheck': 'CheckmarkCircle01Icon',
133
- 'faCircleXmark': 'CancelCircleIcon',
134
- 'faCirclePlus': 'AddCircleIcon',
135
- 'faCircleMinus': 'MinusSignCircleIcon',
136
- 'faRightFromBracket': 'Logout01Icon',
137
- 'faRightToBracket': 'Login01Icon',
138
- 'faArrowRightFromBracket': 'Logout01Icon',
139
- 'faArrowRightToBracket': 'Login01Icon',
140
- 'faMagnifyingGlass': 'Search01Icon',
141
- 'faHouse': 'Home01Icon',
142
- 'faFloppyDisk': 'Save01Icon',
143
- 'faPenToSquare': 'Edit01Icon',
144
- 'faTrashCan': 'Delete01Icon',
145
- 'faRotate': 'Refresh01Icon',
146
- 'faRotateRight': 'Refresh01Icon',
147
- 'faRotateLeft': 'Undo01Icon',
207
+ 'faPrint': 'Printer01Icon',
208
+ 'faCreditCard': 'CreditCardIcon',
209
+ 'faShoppingCart': 'ShoppingCart01Icon',
210
+ 'faShoppingBag': 'ShoppingBag01Icon',
211
+ 'faShare': 'Share01Icon',
212
+ // Brands (using correct names)
213
+ 'faGithub': 'GithubIcon',
214
+ 'faTwitter': 'TwitterIcon',
215
+ 'faFacebook': 'FacebookIcon',
216
+ 'faLinkedin': 'Linkedin01Icon',
217
+ 'faInstagram': 'InstagramIcon',
218
+ 'faYoutube': 'YoutubeIcon',
219
+ 'faGoogle': 'GoogleIcon',
220
+ 'faApple': 'AppleIcon',
221
+ 'faMicrosoft': 'WindowsNewIcon',
222
+ 'faReact': 'ReactIcon',
223
+ 'faCoffee': 'Coffee01Icon',
148
224
  };
149
225
  // ============================================================================
150
226
  // Heroicons Mappings
151
227
  // ============================================================================
152
228
  const HEROICONS_MAPPINGS = {
229
+ // NOTE: These mappings use verified icon names from Hugeicons
153
230
  'AcademicCapIcon': 'GraduationCapIcon',
154
231
  'ArrowDownIcon': 'ArrowDown01Icon',
155
232
  'ArrowLeftIcon': 'ArrowLeft01Icon',
@@ -159,7 +236,7 @@ const HEROICONS_MAPPINGS = {
159
236
  'BookmarkIcon': 'Bookmark01Icon',
160
237
  'CalendarIcon': 'Calendar01Icon',
161
238
  'CameraIcon': 'Camera01Icon',
162
- 'ChartBarIcon': 'BarChart01Icon',
239
+ 'ChartBarIcon': 'ChartIcon',
163
240
  'ChatBubbleLeftIcon': 'Message01Icon',
164
241
  'CheckIcon': 'Tick01Icon',
165
242
  'CheckCircleIcon': 'CheckmarkCircle01Icon',
@@ -176,12 +253,12 @@ const HEROICONS_MAPPINGS = {
176
253
  'DocumentIcon': 'File01Icon',
177
254
  'EnvelopeIcon': 'Mail01Icon',
178
255
  'ExclamationCircleIcon': 'AlertCircleIcon',
179
- 'ExclamationTriangleIcon': 'AlertTriangleIcon',
180
- 'EyeIcon': 'View01Icon',
256
+ 'ExclamationTriangleIcon': 'Alert01Icon',
257
+ 'EyeIcon': 'ViewIcon', // ViewIcon exists
181
258
  'EyeSlashIcon': 'ViewOffIcon',
182
259
  'FolderIcon': 'Folder01Icon',
183
260
  'GlobeAltIcon': 'GlobeIcon',
184
- 'HeartIcon': 'Favourite01Icon',
261
+ 'HeartIcon': 'FavouriteIcon', // FavouriteIcon exists
185
262
  'HomeIcon': 'Home01Icon',
186
263
  'InformationCircleIcon': 'InformationCircleIcon',
187
264
  'LinkIcon': 'Link01Icon',
@@ -189,21 +266,21 @@ const HEROICONS_MAPPINGS = {
189
266
  'LockOpenIcon': 'SquareUnlock01Icon',
190
267
  'MagnifyingGlassIcon': 'Search01Icon',
191
268
  'MapPinIcon': 'Location01Icon',
192
- 'MinusIcon': 'MinusSign01Icon',
269
+ 'MinusIcon': 'MinusSignIcon', // MinusSignIcon exists
193
270
  'MoonIcon': 'Moon01Icon',
194
271
  'PencilIcon': 'Pencil01Icon',
195
272
  'PhoneIcon': 'Call01Icon',
196
273
  'PhotoIcon': 'Image01Icon',
197
- 'PlayIcon': 'Play01Icon',
274
+ 'PlayIcon': 'PlayIcon', // PlayIcon exists
198
275
  'PlusIcon': 'Add01Icon',
199
276
  'QuestionMarkCircleIcon': 'HelpCircleIcon',
200
277
  'ShoppingBagIcon': 'ShoppingBag01Icon',
201
278
  'ShoppingCartIcon': 'ShoppingCart01Icon',
202
- 'StarIcon': 'Star01Icon',
279
+ 'StarIcon': 'StarIcon', // StarIcon exists
203
280
  'SunIcon': 'Sun01Icon',
204
281
  'TrashIcon': 'Delete01Icon',
205
- 'UserIcon': 'User01Icon',
206
- 'UserGroupIcon': 'UserGroup01Icon',
282
+ 'UserIcon': 'UserIcon', // UserIcon exists, not User01Icon
283
+ 'UserGroupIcon': 'UserGroupIcon', // UserGroupIcon exists
207
284
  'UserPlusIcon': 'UserAdd01Icon',
208
285
  'XMarkIcon': 'Cancel01Icon',
209
286
  'XCircleIcon': 'CancelCircleIcon',
@@ -217,18 +294,63 @@ const HEROICONS_MAPPINGS = {
217
294
  * Library-specific mappings that override or supplement the JSON map
218
295
  */
219
296
  const LIBRARY_MAPPINGS = {
297
+ // FontAwesome packages
220
298
  '@fortawesome/fontawesome-svg-core': {
221
299
  exact: FONTAWESOME_MAPPINGS,
222
300
  aliases: {},
223
301
  },
302
+ '@fortawesome/react-fontawesome': {
303
+ exact: FONTAWESOME_MAPPINGS,
304
+ aliases: {},
305
+ },
306
+ // FontAwesome Free packages
224
307
  '@fortawesome/free-solid-svg-icons': {
225
308
  exact: FONTAWESOME_MAPPINGS,
226
309
  aliases: {},
227
310
  },
228
- '@fortawesome/react-fontawesome': {
311
+ '@fortawesome/free-regular-svg-icons': {
229
312
  exact: FONTAWESOME_MAPPINGS,
230
313
  aliases: {},
231
314
  },
315
+ '@fortawesome/free-brands-svg-icons': {
316
+ exact: FONTAWESOME_MAPPINGS,
317
+ aliases: {},
318
+ },
319
+ // FontAwesome Pro packages
320
+ '@fortawesome/pro-solid-svg-icons': {
321
+ exact: FONTAWESOME_MAPPINGS,
322
+ aliases: {},
323
+ },
324
+ '@fortawesome/pro-regular-svg-icons': {
325
+ exact: FONTAWESOME_MAPPINGS,
326
+ aliases: {},
327
+ },
328
+ '@fortawesome/pro-light-svg-icons': {
329
+ exact: FONTAWESOME_MAPPINGS,
330
+ aliases: {},
331
+ },
332
+ '@fortawesome/pro-thin-svg-icons': {
333
+ exact: FONTAWESOME_MAPPINGS,
334
+ aliases: {},
335
+ },
336
+ '@fortawesome/pro-duotone-svg-icons': {
337
+ exact: FONTAWESOME_MAPPINGS,
338
+ aliases: {},
339
+ },
340
+ // FontAwesome Sharp packages
341
+ '@fortawesome/sharp-solid-svg-icons': {
342
+ exact: FONTAWESOME_MAPPINGS,
343
+ aliases: {},
344
+ },
345
+ '@fortawesome/sharp-regular-svg-icons': {
346
+ exact: FONTAWESOME_MAPPINGS,
347
+ aliases: {},
348
+ },
349
+ '@fortawesome/sharp-light-svg-icons': {
350
+ exact: FONTAWESOME_MAPPINGS,
351
+ aliases: {},
352
+ },
353
+ // Heroicons
232
354
  '@heroicons/react': {
233
355
  exact: HEROICONS_MAPPINGS,
234
356
  aliases: {},
@@ -239,6 +361,328 @@ const LIBRARY_MAPPINGS = {
239
361
  },
240
362
  };
241
363
  // ============================================================================
364
+ // FontAwesome Helper Functions
365
+ // ============================================================================
366
+ /**
367
+ * Normalize FontAwesome icon name for lookup
368
+ * Handles various FA naming conventions:
369
+ * - faArrowRight -> ArrowRight
370
+ * - fa-arrow-right -> ArrowRight
371
+ * - arrow-right -> ArrowRight
372
+ */
373
+ export function normalizeFAIconName(name) {
374
+ // Remove 'fa' prefix (with or without dash)
375
+ let normalized = name.replace(/^fa-?/i, '');
376
+ // Convert kebab-case to PascalCase
377
+ normalized = normalized.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
378
+ // Ensure first letter is uppercase
379
+ normalized = normalized.charAt(0).toUpperCase() + normalized.slice(1);
380
+ return normalized;
381
+ }
382
+ /**
383
+ * Check if a library is a FontAwesome package
384
+ */
385
+ export function isFontAwesomeLibrary(library) {
386
+ return library.includes('@fortawesome');
387
+ }
388
+ /**
389
+ * Calculate Dice coefficient similarity between two strings
390
+ */
391
+ function diceCoefficient(str1, str2) {
392
+ if (str1 === str2)
393
+ return 1;
394
+ if (str1.length < 2 || str2.length < 2)
395
+ return 0;
396
+ const s1 = str1.toLowerCase();
397
+ const s2 = str2.toLowerCase();
398
+ const bigrams1 = new Map();
399
+ for (let i = 0; i < s1.length - 1; i++) {
400
+ const bigram = s1.substring(i, i + 2);
401
+ bigrams1.set(bigram, (bigrams1.get(bigram) || 0) + 1);
402
+ }
403
+ let intersectionSize = 0;
404
+ for (let i = 0; i < s2.length - 1; i++) {
405
+ const bigram = s2.substring(i, i + 2);
406
+ const count = bigrams1.get(bigram) || 0;
407
+ if (count > 0) {
408
+ bigrams1.set(bigram, count - 1);
409
+ intersectionSize++;
410
+ }
411
+ }
412
+ return (2.0 * intersectionSize) / (s1.length + s2.length - 2);
413
+ }
414
+ /**
415
+ * Find best fuzzy match for an icon name from available icons
416
+ */
417
+ function findBestFuzzyMatch(targetName, threshold = 0.5) {
418
+ const availableIcons = Object.keys(ICON_MAP.icons);
419
+ if (availableIcons.length === 0)
420
+ return undefined;
421
+ // Normalize target for comparison
422
+ const normalizedTarget = targetName
423
+ .replace(/^fa-?/i, '')
424
+ .replace(/Icon$/i, '')
425
+ .replace(/\d+$/, '')
426
+ .toLowerCase();
427
+ let bestMatch = null;
428
+ for (const icon of availableIcons) {
429
+ const normalizedIcon = icon
430
+ .replace(/Icon$/i, '')
431
+ .replace(/\d+$/, '')
432
+ .toLowerCase();
433
+ const score = diceCoefficient(normalizedTarget, normalizedIcon);
434
+ if (score >= threshold && (!bestMatch || score > bestMatch.score)) {
435
+ bestMatch = { icon, score };
436
+ }
437
+ }
438
+ return bestMatch?.icon;
439
+ }
440
+ /**
441
+ * Validate that an icon exists in the library
442
+ */
443
+ function validateIconExists(iconName) {
444
+ // Check if it's a valid icon in our library
445
+ if (ICON_MAP.icons[iconName]) {
446
+ return iconName;
447
+ }
448
+ // Check alias map
449
+ if (ICON_MAP.aliasMap[iconName]) {
450
+ return ICON_MAP.aliasMap[iconName];
451
+ }
452
+ return undefined;
453
+ }
454
+ /**
455
+ * Get FontAwesome mapping for an icon name
456
+ * Priority: Generated mappings -> ICON_MAP -> Manual mappings -> Fuzzy match
457
+ */
458
+ export function getFontAwesomeMapping(iconName) {
459
+ // Helper to validate and return mapping
460
+ const validateMapping = (mapping) => {
461
+ if (!mapping)
462
+ return undefined;
463
+ const validated = validateIconExists(mapping);
464
+ if (validated)
465
+ return validated;
466
+ // Try fuzzy match if the mapped icon doesn't exist
467
+ return findBestFuzzyMatch(mapping);
468
+ };
469
+ // 1. Check GENERATED mappings first (highest priority)
470
+ const generated = getGeneratedMapping('fontawesome', iconName);
471
+ if (generated) {
472
+ const result = validateMapping(generated);
473
+ if (result)
474
+ return result;
475
+ }
476
+ // Try with 'fa' prefix in generated mappings
477
+ if (!iconName.startsWith('fa')) {
478
+ const withPrefix = `fa${iconName.charAt(0).toUpperCase()}${iconName.slice(1)}`;
479
+ const generatedWithPrefix = getGeneratedMapping('fontawesome', withPrefix);
480
+ if (generatedWithPrefix) {
481
+ const result = validateMapping(generatedWithPrefix);
482
+ if (result)
483
+ return result;
484
+ }
485
+ }
486
+ // 2. Check ICON_MAP (from hugeicons-map.json)
487
+ if (ICON_MAP.fontawesomeMap?.[iconName]) {
488
+ const result = validateMapping(ICON_MAP.fontawesomeMap[iconName]);
489
+ if (result)
490
+ return result;
491
+ }
492
+ // Try with 'fa' prefix if not present
493
+ if (!iconName.startsWith('fa')) {
494
+ const withPrefix = `fa${iconName.charAt(0).toUpperCase()}${iconName.slice(1)}`;
495
+ if (ICON_MAP.fontawesomeMap?.[withPrefix]) {
496
+ const result = validateMapping(ICON_MAP.fontawesomeMap[withPrefix]);
497
+ if (result)
498
+ return result;
499
+ }
500
+ }
501
+ // Try normalized name
502
+ const normalized = normalizeFAIconName(iconName);
503
+ if (ICON_MAP.fontawesomeMap?.[normalized]) {
504
+ const result = validateMapping(ICON_MAP.fontawesomeMap[normalized]);
505
+ if (result)
506
+ return result;
507
+ }
508
+ // 3. Fall back to MANUAL mappings with validation
509
+ if (FONTAWESOME_MAPPINGS[iconName]) {
510
+ const result = validateMapping(FONTAWESOME_MAPPINGS[iconName]);
511
+ if (result)
512
+ return result;
513
+ }
514
+ // Try with 'fa' prefix in manual mappings
515
+ if (!iconName.startsWith('fa')) {
516
+ const withPrefix = `fa${iconName.charAt(0).toUpperCase()}${iconName.slice(1)}`;
517
+ if (FONTAWESOME_MAPPINGS[withPrefix]) {
518
+ const result = validateMapping(FONTAWESOME_MAPPINGS[withPrefix]);
519
+ if (result)
520
+ return result;
521
+ }
522
+ }
523
+ // 4. Last resort: fuzzy matching on the icon name itself
524
+ const fuzzyMatch = findBestFuzzyMatch(iconName);
525
+ if (fuzzyMatch)
526
+ return fuzzyMatch;
527
+ return undefined;
528
+ }
529
+ /**
530
+ * Get Lucide mapping for an icon name
531
+ * Priority: Generated mappings -> ICON_MAP -> Fuzzy match
532
+ */
533
+ export function getLucideMapping(iconName) {
534
+ const validateMapping = (mapping) => {
535
+ if (!mapping)
536
+ return undefined;
537
+ const validated = validateIconExists(mapping);
538
+ if (validated)
539
+ return validated;
540
+ return findBestFuzzyMatch(mapping);
541
+ };
542
+ // 1. Check GENERATED mappings first
543
+ const generated = getGeneratedMapping('lucide', iconName);
544
+ if (generated) {
545
+ const result = validateMapping(generated);
546
+ if (result)
547
+ return result;
548
+ }
549
+ // Try without Icon suffix
550
+ const withoutIcon = iconName.replace(/Icon$/, '');
551
+ if (withoutIcon !== iconName) {
552
+ const generatedWithoutIcon = getGeneratedMapping('lucide', withoutIcon);
553
+ if (generatedWithoutIcon) {
554
+ const result = validateMapping(generatedWithoutIcon);
555
+ if (result)
556
+ return result;
557
+ }
558
+ }
559
+ // 2. Check ICON_MAP
560
+ if (ICON_MAP.lucideMap?.[iconName]) {
561
+ const result = validateMapping(ICON_MAP.lucideMap[iconName]);
562
+ if (result)
563
+ return result;
564
+ }
565
+ if (ICON_MAP.lucideMap?.[withoutIcon]) {
566
+ const result = validateMapping(ICON_MAP.lucideMap[withoutIcon]);
567
+ if (result)
568
+ return result;
569
+ }
570
+ // 3. Fuzzy match
571
+ return findBestFuzzyMatch(iconName);
572
+ }
573
+ /**
574
+ * Get Heroicons mapping for an icon name
575
+ */
576
+ export function getHeroiconsMapping(iconName) {
577
+ const validateMapping = (mapping) => {
578
+ if (!mapping)
579
+ return undefined;
580
+ const validated = validateIconExists(mapping);
581
+ if (validated)
582
+ return validated;
583
+ return findBestFuzzyMatch(mapping);
584
+ };
585
+ // 1. Check GENERATED mappings first
586
+ const generated = getGeneratedMapping('heroicons', iconName);
587
+ if (generated) {
588
+ const result = validateMapping(generated);
589
+ if (result)
590
+ return result;
591
+ }
592
+ // 2. Check manual HEROICONS_MAPPINGS
593
+ if (HEROICONS_MAPPINGS[iconName]) {
594
+ const result = validateMapping(HEROICONS_MAPPINGS[iconName]);
595
+ if (result)
596
+ return result;
597
+ }
598
+ // 3. Fuzzy match
599
+ return findBestFuzzyMatch(iconName);
600
+ }
601
+ /**
602
+ * Get Material Icons mapping for an icon name
603
+ */
604
+ export function getMaterialMapping(iconName) {
605
+ const validateMapping = (mapping) => {
606
+ if (!mapping)
607
+ return undefined;
608
+ const validated = validateIconExists(mapping);
609
+ if (validated)
610
+ return validated;
611
+ return findBestFuzzyMatch(mapping);
612
+ };
613
+ // Check GENERATED mappings
614
+ const generated = getGeneratedMapping('material', iconName);
615
+ if (generated) {
616
+ const result = validateMapping(generated);
617
+ if (result)
618
+ return result;
619
+ }
620
+ return findBestFuzzyMatch(iconName);
621
+ }
622
+ /**
623
+ * Get Feather Icons mapping for an icon name
624
+ */
625
+ export function getFeatherMapping(iconName) {
626
+ const validateMapping = (mapping) => {
627
+ if (!mapping)
628
+ return undefined;
629
+ const validated = validateIconExists(mapping);
630
+ if (validated)
631
+ return validated;
632
+ return findBestFuzzyMatch(mapping);
633
+ };
634
+ // Check GENERATED mappings
635
+ const generated = getGeneratedMapping('feather', iconName);
636
+ if (generated) {
637
+ const result = validateMapping(generated);
638
+ if (result)
639
+ return result;
640
+ }
641
+ return findBestFuzzyMatch(iconName);
642
+ }
643
+ /**
644
+ * Get Tabler Icons mapping for an icon name
645
+ */
646
+ export function getTablerMapping(iconName) {
647
+ const validateMapping = (mapping) => {
648
+ if (!mapping)
649
+ return undefined;
650
+ const validated = validateIconExists(mapping);
651
+ if (validated)
652
+ return validated;
653
+ return findBestFuzzyMatch(mapping);
654
+ };
655
+ // Check GENERATED mappings
656
+ const generated = getGeneratedMapping('tabler', iconName);
657
+ if (generated) {
658
+ const result = validateMapping(generated);
659
+ if (result)
660
+ return result;
661
+ }
662
+ return findBestFuzzyMatch(iconName);
663
+ }
664
+ /**
665
+ * Get Phosphor Icons mapping for an icon name
666
+ */
667
+ export function getPhosphorMapping(iconName) {
668
+ const validateMapping = (mapping) => {
669
+ if (!mapping)
670
+ return undefined;
671
+ const validated = validateIconExists(mapping);
672
+ if (validated)
673
+ return validated;
674
+ return findBestFuzzyMatch(mapping);
675
+ };
676
+ // Check GENERATED mappings
677
+ const generated = getGeneratedMapping('phosphor', iconName);
678
+ if (generated) {
679
+ const result = validateMapping(generated);
680
+ if (result)
681
+ return result;
682
+ }
683
+ return findBestFuzzyMatch(iconName);
684
+ }
685
+ // ============================================================================
242
686
  // Public API
243
687
  // ============================================================================
244
688
  /**
@@ -271,6 +715,7 @@ export function getLucideAliasIfExists(iconName) {
271
715
  /**
272
716
  * Get exact mapping for a library and icon
273
717
  * For Lucide icons, prefers keeping the original name if it exists as an alias
718
+ * For FontAwesome icons, handles various naming conventions
274
719
  */
275
720
  export function getExactMapping(library, iconName) {
276
721
  // Check library-specific mappings first
@@ -278,6 +723,19 @@ export function getExactMapping(library, iconName) {
278
723
  if (libraryMappings?.exact[iconName]) {
279
724
  return libraryMappings.exact[iconName];
280
725
  }
726
+ // For FontAwesome libraries
727
+ if (isFontAwesomeLibrary(library)) {
728
+ const faMapping = getFontAwesomeMapping(iconName);
729
+ if (faMapping) {
730
+ return faMapping;
731
+ }
732
+ // Try normalized name in aliasMap as fallback
733
+ const normalized = normalizeFAIconName(iconName);
734
+ const aliasMatch = ICON_MAP.aliasMap[normalized] || ICON_MAP.aliasMap[`${normalized}Icon`];
735
+ if (aliasMatch) {
736
+ return aliasMatch;
737
+ }
738
+ }
281
739
  // For lucide-react and similar
282
740
  if (library === 'lucide-react' || library === 'lucide') {
283
741
  // Check if this Lucide name is a direct alias (e.g., "Home" -> "HomeIcon")
@@ -294,6 +752,36 @@ export function getExactMapping(library, iconName) {
294
752
  const withIcon = iconName.endsWith('Icon') ? iconName : `${iconName}Icon`;
295
753
  return ICON_MAP.lucideMap[withoutIcon] || ICON_MAP.lucideMap[withIcon];
296
754
  }
755
+ // Heroicons
756
+ if (library === '@heroicons/react' || library.startsWith('@heroicons/react/')) {
757
+ const mapping = getHeroiconsMapping(iconName);
758
+ if (mapping)
759
+ return mapping;
760
+ }
761
+ // Material Icons
762
+ if (library === '@mui/icons-material') {
763
+ const mapping = getMaterialMapping(iconName);
764
+ if (mapping)
765
+ return mapping;
766
+ }
767
+ // Feather Icons
768
+ if (library === 'react-feather' || library === 'feather-icons-react') {
769
+ const mapping = getFeatherMapping(iconName);
770
+ if (mapping)
771
+ return mapping;
772
+ }
773
+ // Tabler Icons
774
+ if (library === '@tabler/icons-react' || library === 'tabler-icons-react') {
775
+ const mapping = getTablerMapping(iconName);
776
+ if (mapping)
777
+ return mapping;
778
+ }
779
+ // Phosphor Icons
780
+ if (library === '@phosphor-icons/react' || library === 'phosphor-react') {
781
+ const mapping = getPhosphorMapping(iconName);
782
+ if (mapping)
783
+ return mapping;
784
+ }
297
785
  // Fallback: try aliasMap for any library
298
786
  return ICON_MAP.aliasMap[iconName];
299
787
  }
@@ -396,7 +884,23 @@ export function getMapStats() {
396
884
  totalIcons: ICON_MAP.totalIcons,
397
885
  totalAliases: ICON_MAP.totalAliases,
398
886
  lucideMappings: Object.keys(ICON_MAP.lucideMap).length,
887
+ fontawesomeMappings: Object.keys(ICON_MAP.fontawesomeMap || {}).length,
399
888
  generated: ICON_MAP.generated,
889
+ generatedMappings: {
890
+ fontawesome: getGeneratedMappingCount('fontawesome'),
891
+ lucide: getGeneratedMappingCount('lucide'),
892
+ heroicons: getGeneratedMappingCount('heroicons'),
893
+ material: getGeneratedMappingCount('material'),
894
+ feather: getGeneratedMappingCount('feather'),
895
+ tabler: getGeneratedMappingCount('tabler'),
896
+ phosphor: getGeneratedMappingCount('phosphor'),
897
+ },
400
898
  };
401
899
  }
900
+ /**
901
+ * Get the FontAwesome mapping dictionary
902
+ */
903
+ export function getFontAwesomeMap() {
904
+ return ICON_MAP.fontawesomeMap || {};
905
+ }
402
906
  //# sourceMappingURL=mappings.js.map