@iconify/tools 1.3.17 → 2.0.0-dev.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.
Files changed (147) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintignore +2 -0
  3. package/lib/colors/attribs.d.ts +16 -0
  4. package/lib/colors/attribs.js +26 -0
  5. package/lib/colors/attribs.mjs +28 -0
  6. package/lib/colors/parse.d.ts +37 -0
  7. package/lib/colors/parse.js +261 -0
  8. package/lib/colors/parse.mjs +212 -0
  9. package/lib/css/parse.d.ts +4 -0
  10. package/lib/css/parse.js +23 -0
  11. package/lib/css/parse.mjs +20 -0
  12. package/lib/css/parser/error.d.ts +11 -0
  13. package/lib/css/parser/error.js +27 -0
  14. package/lib/css/parser/error.mjs +23 -0
  15. package/lib/css/parser/export.d.ts +5 -0
  16. package/lib/css/parser/export.js +69 -0
  17. package/lib/css/parser/export.mjs +46 -0
  18. package/lib/css/parser/strings.d.ts +13 -0
  19. package/lib/css/parser/strings.js +93 -0
  20. package/lib/css/parser/strings.mjs +74 -0
  21. package/lib/css/parser/text.d.ts +17 -0
  22. package/lib/css/parser/text.js +174 -0
  23. package/lib/css/parser/text.mjs +133 -0
  24. package/lib/css/parser/tokens.d.ts +6 -0
  25. package/lib/css/parser/tokens.js +200 -0
  26. package/lib/css/parser/tokens.mjs +186 -0
  27. package/lib/css/parser/tree.d.ts +5 -0
  28. package/lib/css/parser/tree.js +44 -0
  29. package/lib/css/parser/tree.mjs +40 -0
  30. package/lib/css/parser/types.d.ts +51 -0
  31. package/lib/css/parser/types.js +2 -0
  32. package/lib/css/parser/types.mjs +0 -0
  33. package/lib/icon-set/index.d.ts +134 -0
  34. package/lib/icon-set/index.js +776 -0
  35. package/lib/icon-set/index.mjs +617 -0
  36. package/lib/icon-set/match.d.ts +6 -0
  37. package/lib/icon-set/match.js +66 -0
  38. package/lib/icon-set/match.mjs +55 -0
  39. package/lib/icon-set/merge.d.ts +5 -0
  40. package/lib/icon-set/merge.js +91 -0
  41. package/lib/icon-set/merge.mjs +75 -0
  42. package/lib/icon-set/props.d.ts +10 -0
  43. package/lib/icon-set/props.js +33 -0
  44. package/lib/icon-set/props.mjs +25 -0
  45. package/lib/icon-set/types.d.ts +68 -0
  46. package/lib/icon-set/types.js +2 -0
  47. package/lib/icon-set/types.mjs +0 -0
  48. package/lib/import/directory.d.ts +35 -0
  49. package/lib/import/directory.js +59 -0
  50. package/lib/import/directory.mjs +47 -0
  51. package/lib/misc/keyword.d.ts +4 -0
  52. package/lib/misc/keyword.js +31 -0
  53. package/lib/misc/keyword.mjs +17 -0
  54. package/lib/misc/scan.d.ts +24 -0
  55. package/lib/misc/scan.js +48 -0
  56. package/lib/misc/scan.mjs +43 -0
  57. package/lib/optimise/flags.d.ts +5 -0
  58. package/lib/optimise/flags.js +303 -0
  59. package/lib/optimise/flags.mjs +241 -0
  60. package/lib/optimise/scale.d.ts +5 -0
  61. package/lib/optimise/scale.js +42 -0
  62. package/lib/optimise/scale.mjs +22 -0
  63. package/lib/optimise/svgo.d.ts +27 -0
  64. package/lib/optimise/svgo.js +88 -0
  65. package/lib/optimise/svgo.mjs +75 -0
  66. package/lib/svg/cleanup/attribs.d.ts +5 -0
  67. package/lib/svg/cleanup/attribs.js +43 -0
  68. package/lib/svg/cleanup/attribs.mjs +36 -0
  69. package/lib/svg/cleanup/bad-tags.d.ts +5 -0
  70. package/lib/svg/cleanup/bad-tags.js +69 -0
  71. package/lib/svg/cleanup/bad-tags.mjs +68 -0
  72. package/lib/svg/cleanup/inline-style.d.ts +5 -0
  73. package/lib/svg/cleanup/inline-style.js +77 -0
  74. package/lib/svg/cleanup/inline-style.mjs +65 -0
  75. package/lib/svg/cleanup/root-svg.d.ts +5 -0
  76. package/lib/svg/cleanup/root-svg.js +106 -0
  77. package/lib/svg/cleanup/root-svg.mjs +88 -0
  78. package/lib/svg/cleanup/svgo-style.d.ts +5 -0
  79. package/lib/svg/cleanup/svgo-style.js +35 -0
  80. package/lib/svg/cleanup/svgo-style.mjs +29 -0
  81. package/lib/svg/cleanup.d.ts +5 -0
  82. package/lib/svg/cleanup.js +24 -0
  83. package/lib/svg/cleanup.mjs +16 -0
  84. package/lib/svg/data/attributes.d.ts +71 -0
  85. package/lib/svg/data/attributes.js +403 -0
  86. package/lib/svg/data/attributes.mjs +352 -0
  87. package/lib/svg/data/tags.d.ts +89 -0
  88. package/lib/svg/data/tags.js +185 -0
  89. package/lib/svg/data/tags.mjs +136 -0
  90. package/lib/svg/index.d.ts +33 -0
  91. package/lib/svg/index.js +122 -0
  92. package/lib/svg/index.mjs +85 -0
  93. package/lib/svg/parse-style.d.ts +40 -0
  94. package/lib/svg/parse-style.js +131 -0
  95. package/lib/svg/parse-style.mjs +109 -0
  96. package/lib/svg/parse.d.ts +30 -0
  97. package/lib/svg/parse.js +49 -0
  98. package/lib/svg/parse.mjs +40 -0
  99. package/package.json +167 -13
  100. package/README.md +0 -576
  101. package/license.txt +0 -21
  102. package/sample/parse.js +0 -74
  103. package/sample/source/icon-close.svg +0 -15
  104. package/sample/source/icon-confirm.svg +0 -14
  105. package/sample/source/icon-search.svg +0 -16
  106. package/src/collection.js +0 -641
  107. package/src/colors/change_palette.js +0 -227
  108. package/src/colors/get_palette.js +0 -143
  109. package/src/colors/opacify.js +0 -195
  110. package/src/export/component.js +0 -482
  111. package/src/export/dir.js +0 -109
  112. package/src/export/json.js +0 -329
  113. package/src/export/phantomjs.js +0 -76
  114. package/src/export/phantomjs_script.js +0 -125
  115. package/src/export/png.js +0 -193
  116. package/src/export/svg.js +0 -55
  117. package/src/export/templates/component.md +0 -79
  118. package/src/export/templates/info.md +0 -3
  119. package/src/export/templates/sample-react-1.md +0 -21
  120. package/src/export/templates/sample-react-2.md +0 -15
  121. package/src/export/templates/sample-react.md +0 -11
  122. package/src/export/templates/sample-svelte.md +0 -11
  123. package/src/export/templates/sample-svelte1.md +0 -22
  124. package/src/export/templates/sample-svelte2.md +0 -13
  125. package/src/export/templates/sample-vue-0.md +0 -30
  126. package/src/export/templates/sample-vue-1.md +0 -25
  127. package/src/export/templates/sample-vue-2.md +0 -27
  128. package/src/export/templates/sample-vue.md +0 -28
  129. package/src/helpers.js +0 -43
  130. package/src/import/dir.js +0 -234
  131. package/src/import/font.js +0 -402
  132. package/src/import/json.js +0 -200
  133. package/src/import/svg.js +0 -60
  134. package/src/import/web_icons.js +0 -248
  135. package/src/modules.js +0 -50
  136. package/src/optimize/crop.js +0 -554
  137. package/src/optimize/crop_script.js +0 -525
  138. package/src/optimize/flags.js +0 -430
  139. package/src/optimize/scale.js +0 -72
  140. package/src/optimize/svgo.js +0 -161
  141. package/src/optimize/tags.js +0 -522
  142. package/src/shapes/convert.js +0 -264
  143. package/src/shapes/index.js +0 -135
  144. package/src/shapes/length.js +0 -707
  145. package/src/shapes/length_script.js +0 -105
  146. package/src/shapes/options.js +0 -60
  147. package/src/svg.js +0 -162
@@ -0,0 +1,776 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.blankIconSet = exports.IconSet = exports.sortThemeKeys = void 0;
4
+ const icon_1 = require("@iconify/utils/lib/icon");
5
+ const build_1 = require("@iconify/utils/lib/svg/build");
6
+ const customisations_1 = require("@iconify/utils/lib/customisations");
7
+ const minify_1 = require("@iconify/utils/lib/icon-set/minify");
8
+ const convert_info_1 = require("@iconify/utils/lib/icon-set/convert-info");
9
+ const props_1 = require("./props");
10
+ const svg_1 = require("../svg");
11
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental, @typescript-eslint/no-unused-vars
12
+ function assertNever(v) {
13
+ //
14
+ }
15
+ // Maximum depth for looking for parent icons
16
+ // Must match depth limit in Iconify Utils (tested in unit tests by parsing same icon set with deep aliases)
17
+ const maxIteration = 6;
18
+ // Theme keys
19
+ const themeKeys = ['prefixes', 'suffixes'];
20
+ /**
21
+ * Sort theme keys: long keys first
22
+ *
23
+ * Applies changes to parameter, but also returns it
24
+ */
25
+ function sortThemeKeys(keys) {
26
+ return keys.sort((a, b) => a.length === b.length ? a.localeCompare(b) : b.length - a.length);
27
+ }
28
+ exports.sortThemeKeys = sortThemeKeys;
29
+ /**
30
+ * Export icon set
31
+ */
32
+ class IconSet {
33
+ /**
34
+ * Load icon set
35
+ */
36
+ constructor(data) {
37
+ this.load(data);
38
+ }
39
+ /**
40
+ * Load icon set
41
+ */
42
+ load(data) {
43
+ this.prefix = data.prefix;
44
+ // Defaults
45
+ const defaultProps = (0, props_1.filterProps)(data);
46
+ // Add icons
47
+ this.entries = Object.create(null);
48
+ const entries = this.entries;
49
+ for (const name in data.icons) {
50
+ const item = data.icons[name];
51
+ const entry = {
52
+ type: 'icon',
53
+ body: item.body,
54
+ props: { ...defaultProps, ...(0, props_1.filterProps)(item) },
55
+ chars: new Set(),
56
+ categories: new Set(),
57
+ };
58
+ entries[name] = entry;
59
+ }
60
+ // Add aliases
61
+ if (data.aliases) {
62
+ for (const name in data.aliases) {
63
+ const item = data.aliases[name];
64
+ const parent = item.parent;
65
+ const props = (0, props_1.filterProps)(item);
66
+ if (Object.keys(props).length) {
67
+ // Variation
68
+ const entry = {
69
+ type: 'variation',
70
+ parent,
71
+ props,
72
+ chars: new Set(),
73
+ categories: new Set(),
74
+ };
75
+ entries[name] = entry;
76
+ }
77
+ else {
78
+ // Alias
79
+ const entry = {
80
+ type: 'alias',
81
+ parent,
82
+ };
83
+ entries[name] = entry;
84
+ }
85
+ }
86
+ }
87
+ // Info
88
+ const info = data.info && (0, convert_info_1.convertIconSetInfo)(data.info);
89
+ this.info = info || void 0;
90
+ // Characters map
91
+ if (data.chars) {
92
+ for (const char in data.chars) {
93
+ const name = data.chars[char];
94
+ const icon = entries[name];
95
+ if (icon) {
96
+ switch (icon.type) {
97
+ case 'icon':
98
+ case 'variation':
99
+ icon.chars.add(char);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ // Categories
105
+ this.categories = new Set();
106
+ if (data.categories) {
107
+ for (const category in data.categories) {
108
+ const item = {
109
+ title: category,
110
+ count: 0,
111
+ };
112
+ data.categories[category].forEach((iconName) => {
113
+ const icon = entries[iconName];
114
+ switch (icon === null || icon === void 0 ? void 0 : icon.type) {
115
+ case 'icon':
116
+ case 'variation':
117
+ icon.categories.add(item);
118
+ }
119
+ });
120
+ this.categories.add(item);
121
+ this.listCategory(item);
122
+ }
123
+ }
124
+ // Themes
125
+ const prefixes = (this.prefixes = Object.create(null));
126
+ const suffixes = (this.suffixes = Object.create(null));
127
+ if (data.themes) {
128
+ // Import legacy format
129
+ for (const key in data.themes) {
130
+ const item = data.themes[key];
131
+ if (typeof item.prefix === 'string') {
132
+ // Prefix ending with with '-'
133
+ const prefix = item.prefix;
134
+ if (prefix.slice(-1) === '-') {
135
+ prefixes[prefix.slice(0, prefix.length - 1)] =
136
+ item.title;
137
+ }
138
+ }
139
+ if (typeof item.suffix === 'string') {
140
+ // Suffix starting with with '-'
141
+ const suffix = item.suffix;
142
+ if (suffix.slice(0, 1) === '-') {
143
+ suffixes[suffix.slice(1)] = item.title;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ themeKeys.forEach((prop) => {
149
+ // Copy data, overwriting imported legacy format
150
+ const items = data[prop];
151
+ if (items) {
152
+ this[prop] = Object.create(null);
153
+ for (const key in items) {
154
+ this[prop][key] = items[key];
155
+ }
156
+ }
157
+ });
158
+ }
159
+ /**
160
+ * List icons
161
+ */
162
+ list(types = ['icon', 'variation']) {
163
+ return Object.keys(this.entries).filter((name) => {
164
+ const type = this.entries[name].type;
165
+ return types.indexOf(type) !== -1;
166
+ });
167
+ }
168
+ /**
169
+ * forEach function to loop through all entries.
170
+ * Supports asynchronous callbacks.
171
+ *
172
+ * Callback should return false to stop loop.
173
+ */
174
+ async forEach(callback, types = ['icon', 'variation', 'alias']) {
175
+ const names = this.list(types);
176
+ for (let i = 0; i < names.length; i++) {
177
+ const name = names[i];
178
+ const item = this.entries[name];
179
+ if (item) {
180
+ let result = callback(name, item.type);
181
+ if (result instanceof Promise) {
182
+ result = await result;
183
+ }
184
+ if (result === false) {
185
+ return;
186
+ }
187
+ }
188
+ }
189
+ }
190
+ resolve(name, full = false) {
191
+ const entries = this.entries;
192
+ function getIcon(name, iteration) {
193
+ if (entries[name] === void 0 || iteration > maxIteration) {
194
+ // Missing or loop is too deep
195
+ return null;
196
+ }
197
+ const item = entries[name];
198
+ switch (item.type) {
199
+ case 'icon': {
200
+ const result = {
201
+ body: item.body,
202
+ ...item.props,
203
+ };
204
+ return result;
205
+ }
206
+ case 'alias':
207
+ return getIcon(item.parent, iteration + 1);
208
+ case 'variation': {
209
+ const parent = getIcon(item.parent, iteration + 1);
210
+ if (!parent) {
211
+ return null;
212
+ }
213
+ for (const key in item.props) {
214
+ const attr = key;
215
+ const value = item.props[attr];
216
+ if (value) {
217
+ if (parent[attr] === void 0) {
218
+ parent[attr] = value;
219
+ }
220
+ else {
221
+ // Merge props
222
+ switch (attr) {
223
+ case 'rotate':
224
+ parent[attr] =
225
+ (parent[attr] +
226
+ value) %
227
+ 4;
228
+ break;
229
+ case 'hFlip':
230
+ case 'vFlip':
231
+ parent[attr] = !parent[attr];
232
+ break;
233
+ default:
234
+ parent[attr] = value;
235
+ break;
236
+ }
237
+ }
238
+ }
239
+ }
240
+ return parent;
241
+ }
242
+ default:
243
+ assertNever(item);
244
+ return null;
245
+ }
246
+ }
247
+ const result = getIcon(name, 0);
248
+ // Return icon
249
+ return result && full ? (0, icon_1.fullIcon)(result) : result;
250
+ }
251
+ /**
252
+ * Generate HTML
253
+ */
254
+ toString(name, custommisations = {
255
+ width: 'auto',
256
+ height: 'auto',
257
+ }) {
258
+ const item = this.resolve(name, true);
259
+ if (!item) {
260
+ return null;
261
+ }
262
+ const result = (0, build_1.iconToSVG)(item, {
263
+ ...customisations_1.defaults,
264
+ ...custommisations,
265
+ });
266
+ const attributes = Object.keys(result.attributes)
267
+ .map((key) => ` ${key}="${result.attributes[key]}"`)
268
+ .join('');
269
+ return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"${attributes}>${result.body}</svg>`;
270
+ }
271
+ /**
272
+ * Get SVG instance for icon
273
+ */
274
+ toSVG(name) {
275
+ const html = this.toString(name);
276
+ return html ? new svg_1.SVG(html) : null;
277
+ }
278
+ /**
279
+ * Export icon set
280
+ */
281
+ export(validate = true) {
282
+ const icons = Object.create(null);
283
+ const aliases = Object.create(null);
284
+ // Add icons
285
+ const names = Object.keys(this.entries);
286
+ names.sort((a, b) => a.localeCompare(b));
287
+ names.forEach((name) => {
288
+ const item = this.entries[name];
289
+ switch (item.type) {
290
+ case 'icon': {
291
+ const icon = {
292
+ body: item.body,
293
+ ...item.props,
294
+ };
295
+ icons[name] = icon;
296
+ break;
297
+ }
298
+ case 'alias':
299
+ case 'variation': {
300
+ if (validate && !this.resolve(name)) {
301
+ break;
302
+ }
303
+ const props = item.type === 'variation' ? item.props : {};
304
+ const alias = {
305
+ parent: item.parent,
306
+ ...props,
307
+ };
308
+ aliases[name] = alias;
309
+ break;
310
+ }
311
+ default: {
312
+ assertNever(item);
313
+ }
314
+ }
315
+ });
316
+ // Add info
317
+ let info;
318
+ if (this.info) {
319
+ // Update icons count and clone object
320
+ this.info.total = this.count();
321
+ info = JSON.parse(JSON.stringify(this.info));
322
+ }
323
+ // Generate result
324
+ const result = {
325
+ prefix: this.prefix,
326
+ };
327
+ if (info) {
328
+ result.info = info;
329
+ }
330
+ result.icons = icons;
331
+ if (Object.keys(aliases).length) {
332
+ result.aliases = aliases;
333
+ }
334
+ // Add characters
335
+ const chars = this.chars(Object.keys(icons).concat(Object.keys(aliases)));
336
+ if (Object.keys(chars).length) {
337
+ result.chars = chars;
338
+ }
339
+ // Get categories
340
+ const categories = Object.create(null);
341
+ Array.from(this.categories)
342
+ // Sort
343
+ .sort((a, b) => a.title.localeCompare(b.title))
344
+ // Get list of icons
345
+ .forEach((item) => {
346
+ const names = this.listCategory(item);
347
+ if (names) {
348
+ categories[item.title] = names;
349
+ }
350
+ });
351
+ if (Object.keys(categories).length) {
352
+ result.categories = categories;
353
+ }
354
+ // Add themes
355
+ themeKeys.forEach((prop) => {
356
+ const items = this[prop];
357
+ const keys = Object.keys(items);
358
+ if (keys.length) {
359
+ // Sort theme and get matching icon names
360
+ sortThemeKeys(keys);
361
+ const sortedTheme = Object.create(null);
362
+ const tested = this.checkTheme(prop === 'prefixes');
363
+ // Add all themes that aren't empty
364
+ keys.forEach((key) => {
365
+ if (tested.valid[key].length) {
366
+ sortedTheme[key] = items[key];
367
+ }
368
+ });
369
+ // Make sure themes do exist
370
+ if (Object.keys(sortedTheme).length) {
371
+ result[prop] = sortedTheme;
372
+ }
373
+ }
374
+ });
375
+ // Minify icon set
376
+ (0, minify_1.minifyIconSet)(result);
377
+ return result;
378
+ }
379
+ /**
380
+ * Get characters map
381
+ */
382
+ chars(names) {
383
+ const chars = Object.create(null);
384
+ if (!names) {
385
+ names = Object.keys(this.entries);
386
+ }
387
+ for (let i = 0; i < names.length; i++) {
388
+ const name = names[i];
389
+ const item = this.entries[name];
390
+ switch (item.type) {
391
+ case 'icon':
392
+ case 'variation':
393
+ item.chars.forEach((char) => {
394
+ chars[char] = name;
395
+ });
396
+ }
397
+ }
398
+ return chars;
399
+ }
400
+ /**
401
+ * Filter icons
402
+ */
403
+ _filter(callback) {
404
+ const names = [];
405
+ for (const key in this.entries) {
406
+ const item = this.entries[key];
407
+ switch (item.type) {
408
+ case 'icon': {
409
+ if (callback(key, item)) {
410
+ names.push(key);
411
+ }
412
+ break;
413
+ }
414
+ case 'variation':
415
+ case 'alias': {
416
+ // Resolve alias to make sure parent icon is not hidden
417
+ const icon = this.resolve(key);
418
+ if (icon && callback(key, item, icon)) {
419
+ names.push(key);
420
+ }
421
+ break;
422
+ }
423
+ }
424
+ }
425
+ return names;
426
+ }
427
+ /**
428
+ * Count icons
429
+ */
430
+ count() {
431
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental
432
+ return this._filter((key, item, icon) => {
433
+ if (item.type === 'alias' || item.props.hidden || (icon === null || icon === void 0 ? void 0 : icon.hidden)) {
434
+ return false;
435
+ }
436
+ return true;
437
+ }).length;
438
+ }
439
+ /**
440
+ * Find category by title
441
+ */
442
+ _findCategory(title, add) {
443
+ const categoryItem = Array.from(this.categories).find((item) => item.title === title);
444
+ if (categoryItem) {
445
+ return categoryItem;
446
+ }
447
+ if (add) {
448
+ const newItem = {
449
+ title,
450
+ count: 0,
451
+ };
452
+ this.categories.add(newItem);
453
+ return newItem;
454
+ }
455
+ return null;
456
+ }
457
+ /**
458
+ * Count icons in category, remove category if empty
459
+ *
460
+ * Hidden icons and aliases do not count
461
+ */
462
+ listCategory(category) {
463
+ // Find item
464
+ const categoryItem = typeof category === 'string'
465
+ ? this._findCategory(category, false)
466
+ : category;
467
+ if (!categoryItem) {
468
+ return null;
469
+ }
470
+ // Find icons
471
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental
472
+ const icons = this._filter((key, item, icon) => {
473
+ if (item.type === 'alias' || item.props.hidden || (icon === null || icon === void 0 ? void 0 : icon.hidden)) {
474
+ return false;
475
+ }
476
+ return item.categories.has(categoryItem);
477
+ });
478
+ // Update count, remove category if empty
479
+ const count = icons.length;
480
+ categoryItem.count = count;
481
+ if (!count) {
482
+ this.categories.delete(categoryItem);
483
+ return null;
484
+ }
485
+ return icons;
486
+ }
487
+ /**
488
+ * Check if icon exists
489
+ */
490
+ exists(name) {
491
+ return !!this.entries[name];
492
+ }
493
+ /**
494
+ * Remove icons. Returns number of removed icons
495
+ *
496
+ * If removeDependencies is a string, it represents new parent for all aliases of removed icon.
497
+ */
498
+ remove(name, removeDependencies = true) {
499
+ const entries = this.entries;
500
+ const names = new Set();
501
+ // Check if new parent exists
502
+ if (typeof removeDependencies === 'string') {
503
+ if (name === removeDependencies || !entries[removeDependencies]) {
504
+ return 0;
505
+ }
506
+ names.add(removeDependencies);
507
+ }
508
+ function del(name, iteration) {
509
+ if (entries[name] === void 0 ||
510
+ iteration > maxIteration ||
511
+ names.has(name)) {
512
+ // Missing or loop is too deep
513
+ return false;
514
+ }
515
+ names.add(name);
516
+ if (removeDependencies === true ||
517
+ (!iteration && typeof removeDependencies === 'string')) {
518
+ // Find icons that have this icon as parent
519
+ for (const key in entries) {
520
+ const item = entries[key];
521
+ switch (item.type) {
522
+ case 'icon':
523
+ break;
524
+ case 'alias':
525
+ case 'variation':
526
+ if (item.parent === name) {
527
+ if (removeDependencies === true) {
528
+ if (!del(key, iteration + 1)) {
529
+ return false;
530
+ }
531
+ break;
532
+ }
533
+ // Change parent
534
+ item.parent = removeDependencies;
535
+ }
536
+ break;
537
+ default:
538
+ assertNever(item);
539
+ }
540
+ }
541
+ }
542
+ return true;
543
+ }
544
+ if (del(name, 0)) {
545
+ if (typeof removeDependencies === 'string') {
546
+ names.delete(removeDependencies);
547
+ }
548
+ names.forEach((name) => {
549
+ delete entries[name];
550
+ });
551
+ return names.size;
552
+ }
553
+ return 0;
554
+ }
555
+ /**
556
+ * Remove icon
557
+ */
558
+ rename(oldName, newName) {
559
+ const entries = this.entries;
560
+ // Remove existing item with new name
561
+ if (entries[newName]) {
562
+ if (!this.remove(newName)) {
563
+ return false;
564
+ }
565
+ }
566
+ // Rename icon
567
+ if (!entries[oldName]) {
568
+ return false;
569
+ }
570
+ entries[newName] = entries[oldName];
571
+ delete entries[oldName];
572
+ // Find aliases
573
+ for (const key in entries) {
574
+ const item = entries[key];
575
+ switch (item.type) {
576
+ case 'icon':
577
+ break;
578
+ case 'alias':
579
+ case 'variation':
580
+ if (item.parent === oldName) {
581
+ item.parent = newName;
582
+ }
583
+ break;
584
+ default:
585
+ assertNever(item);
586
+ }
587
+ }
588
+ return true;
589
+ }
590
+ /**
591
+ * Add/update item
592
+ */
593
+ setItem(name, item) {
594
+ switch (item.type) {
595
+ case 'alias':
596
+ case 'variation': {
597
+ if (!this.entries[item.parent]) {
598
+ return false;
599
+ }
600
+ }
601
+ }
602
+ this.entries[name] = item;
603
+ return true;
604
+ }
605
+ /**
606
+ * Add/update icon
607
+ */
608
+ setIcon(name, icon) {
609
+ return this.setItem(name, {
610
+ type: 'icon',
611
+ body: icon.body,
612
+ props: (0, props_1.filterProps)(icon),
613
+ chars: new Set(),
614
+ categories: new Set(),
615
+ });
616
+ }
617
+ /**
618
+ * Add/update alias without props
619
+ */
620
+ setAlias(name, parent) {
621
+ return this.setItem(name, {
622
+ type: 'alias',
623
+ parent,
624
+ });
625
+ }
626
+ /**
627
+ * Add/update alias with props
628
+ */
629
+ setVariation(name, parent, props) {
630
+ // Copy categories
631
+ let categories;
632
+ while (!categories) {
633
+ const parentItem = this.entries[parent];
634
+ if (!parentItem) {
635
+ return false;
636
+ }
637
+ if (parentItem.type === 'alias') {
638
+ parent = parentItem.parent;
639
+ }
640
+ else {
641
+ categories = new Set(parentItem.categories);
642
+ }
643
+ }
644
+ return this.setItem(name, {
645
+ type: 'variation',
646
+ parent,
647
+ props,
648
+ chars: new Set(),
649
+ categories,
650
+ });
651
+ }
652
+ /**
653
+ * Icon from SVG. Updates old icon if it exists
654
+ */
655
+ fromSVG(name, svg) {
656
+ const props = svg.viewBox;
657
+ const body = svg.getBody();
658
+ const item = this.entries[name];
659
+ switch (item === null || item === void 0 ? void 0 : item.type) {
660
+ case 'icon':
661
+ case 'variation': {
662
+ // Copy extra properties
663
+ for (const key in props_1.extraDefaultProps) {
664
+ const prop = key;
665
+ if (item.props[prop]) {
666
+ props[prop] = item.props[prop];
667
+ }
668
+ }
669
+ // Set icon
670
+ return this.setItem(name, {
671
+ type: 'icon',
672
+ body,
673
+ props,
674
+ chars: item.chars,
675
+ categories: item.categories,
676
+ });
677
+ }
678
+ }
679
+ // Create new entry
680
+ return this.setIcon(name, {
681
+ body,
682
+ ...props,
683
+ });
684
+ }
685
+ /**
686
+ * Add or remove character for icon
687
+ */
688
+ toggleCharacter(iconName, char, add) {
689
+ const item = this.entries[iconName];
690
+ if (!item) {
691
+ return false;
692
+ }
693
+ switch (item.type) {
694
+ case 'icon':
695
+ case 'variation':
696
+ if (item.chars.has(char) !== add) {
697
+ item.chars[add ? 'add' : 'delete'](char);
698
+ return true;
699
+ }
700
+ }
701
+ return false;
702
+ }
703
+ /**
704
+ * Add or remove category for icon
705
+ */
706
+ toggleCategory(iconName, category, add) {
707
+ const item = this.entries[iconName];
708
+ const categoryItem = this._findCategory(category, add);
709
+ if (!item || !categoryItem) {
710
+ return false;
711
+ }
712
+ switch (item.type) {
713
+ case 'icon':
714
+ case 'variation':
715
+ if (item.categories.has(categoryItem) !== add) {
716
+ categoryItem.count += add ? 1 : -1;
717
+ item.categories[add ? 'add' : 'delete'](categoryItem);
718
+ return true;
719
+ }
720
+ }
721
+ return false;
722
+ }
723
+ /**
724
+ * Find icons that belong to theme
725
+ */
726
+ checkTheme(prefix) {
727
+ const themes = prefix ? this.prefixes : this.suffixes;
728
+ const keys = sortThemeKeys(Object.keys(themes));
729
+ const results = {
730
+ valid: Object.create(null),
731
+ invalid: [],
732
+ };
733
+ keys.forEach((key) => {
734
+ results.valid[key] = [];
735
+ });
736
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental
737
+ results.invalid = this._filter((name, item, icon) => {
738
+ if (item.type === 'alias' || item.props.hidden || (icon === null || icon === void 0 ? void 0 : icon.hidden)) {
739
+ return false;
740
+ }
741
+ // Check if icon belongs to theme
742
+ for (let i = 0; i < keys.length; i++) {
743
+ const search = keys[i];
744
+ if (search === '') {
745
+ // Last item: matches all icons that do not belong to other themes
746
+ results.valid[search].push(name);
747
+ return false;
748
+ }
749
+ const match = prefix ? search + '-' : '-' + search;
750
+ const length = match.length;
751
+ const test = prefix
752
+ ? name.slice(0, length)
753
+ : name.slice(0 - length);
754
+ if (test === match) {
755
+ // Icon belongs to theme
756
+ results.valid[search].push(name);
757
+ return false;
758
+ }
759
+ }
760
+ // Icon does not belong to any theme
761
+ return true;
762
+ });
763
+ return results;
764
+ }
765
+ }
766
+ exports.IconSet = IconSet;
767
+ /**
768
+ * Create blank icon set
769
+ */
770
+ function blankIconSet(prefix) {
771
+ return new IconSet({
772
+ prefix,
773
+ icons: {},
774
+ });
775
+ }
776
+ exports.blankIconSet = blankIconSet;