@iconify/tools 2.0.8 → 2.0.12

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 (49) hide show
  1. package/lib/colors/parse.d.ts +19 -3
  2. package/lib/colors/parse.js +109 -40
  3. package/lib/colors/parse.mjs +86 -39
  4. package/lib/colors/validate.js +5 -2
  5. package/lib/colors/validate.mjs +3 -1
  6. package/lib/icon-set/index.js +4 -21
  7. package/lib/icon-set/index.mjs +6 -21
  8. package/lib/icon-set/merge.js +0 -1
  9. package/lib/icon-set/merge.mjs +1 -2
  10. package/lib/icon-set/types.d.ts +3 -1
  11. package/lib/index.d.ts +2 -0
  12. package/lib/index.js +5 -1
  13. package/lib/index.mjs +4 -0
  14. package/lib/optimise/flags.js +9 -0
  15. package/lib/optimise/flags.mjs +8 -0
  16. package/lib/optimise/global-style.d.ts +5 -0
  17. package/lib/optimise/global-style.js +158 -0
  18. package/lib/optimise/global-style.mjs +129 -0
  19. package/lib/optimise/svgo.js +1 -1
  20. package/lib/optimise/svgo.mjs +0 -1
  21. package/lib/svg/analyse/error.d.ts +5 -0
  22. package/lib/svg/analyse/error.js +22 -0
  23. package/lib/svg/analyse/error.mjs +16 -0
  24. package/lib/svg/analyse/types.d.ts +89 -0
  25. package/lib/svg/analyse/types.js +2 -0
  26. package/lib/svg/analyse/types.mjs +0 -0
  27. package/lib/svg/analyse.d.ts +8 -0
  28. package/lib/svg/analyse.js +352 -0
  29. package/lib/svg/analyse.mjs +302 -0
  30. package/lib/svg/cleanup/attribs.d.ts +1 -1
  31. package/lib/svg/cleanup/attribs.js +8 -0
  32. package/lib/svg/cleanup/attribs.mjs +8 -1
  33. package/lib/svg/cleanup/bad-tags.d.ts +1 -1
  34. package/lib/svg/cleanup/bad-tags.js +0 -2
  35. package/lib/svg/cleanup/bad-tags.mjs +0 -3
  36. package/lib/svg/cleanup/inline-style.d.ts +1 -1
  37. package/lib/svg/cleanup/root-svg.d.ts +1 -1
  38. package/lib/svg/cleanup/root-svg.js +4 -2
  39. package/lib/svg/cleanup/root-svg.mjs +3 -3
  40. package/lib/svg/cleanup/svgo-style.d.ts +1 -1
  41. package/lib/svg/data/attributes.js +1 -1
  42. package/lib/svg/data/attributes.mjs +1 -1
  43. package/lib/svg/data/tags.d.ts +15 -7
  44. package/lib/svg/data/tags.js +20 -9
  45. package/lib/svg/data/tags.mjs +11 -6
  46. package/lib/svg/parse-style.d.ts +7 -7
  47. package/lib/svg/parse-style.js +27 -7
  48. package/lib/svg/parse-style.mjs +26 -7
  49. package/package.json +18 -2
@@ -1,6 +1,7 @@
1
1
  import type { Color } from '@iconify/utils/lib/colors/types';
2
2
  import type { SVG } from '../svg';
3
3
  import { ColorAttributes } from './attribs';
4
+ import type { AnalyseSVGStructureResult, ElementsTreeItem, ExtendedTagElement, AnalyseSVGStructureOptions } from '../svg/analyse/types';
4
5
  /**
5
6
  * Result
6
7
  */
@@ -19,16 +20,31 @@ export interface FindColorsResult {
19
20
  * - 'remove' to remove shape or rule
20
21
  */
21
22
  declare type ParseColorsCallbackResult = Color | string | 'remove' | 'unset';
22
- declare type ParseColorsCallback = (attr: ColorAttributes, colorString: string, parsedColor: Color | null, tagName?: string) => ParseColorsCallbackResult | Promise<ParseColorsCallbackResult>;
23
+ declare type ParseColorsCallback = (attr: ColorAttributes, colorString: string, parsedColor: Color | null, tagName?: string, item?: ExtendedTagElementWithColors) => ParseColorsCallbackResult | Promise<ParseColorsCallbackResult>;
24
+ /**
25
+ * Callback for default color
26
+ */
27
+ export declare type ParseColorOptionsDefaultColorCallback = (prop: string, item: ExtendedTagElementWithColors, treeItem: ElementsTreeItem, iconData: AnalyseSVGStructureResult) => Color;
23
28
  /**
24
29
  * Options
25
30
  */
26
- export interface ParseColorsOptions {
31
+ export interface ParseColorsOptions extends AnalyseSVGStructureOptions {
27
32
  callback?: ParseColorsCallback;
28
- defaultColor?: Color | string;
33
+ defaultColor?: Color | string | ParseColorOptionsDefaultColorCallback;
34
+ }
35
+ /**
36
+ * Extend properties for element
37
+ */
38
+ declare type ItemColors = Partial<Record<ColorAttributes, Color | string>>;
39
+ export interface ExtendedTagElementWithColors extends ExtendedTagElement {
40
+ _colors?: ItemColors;
41
+ _removed?: boolean;
29
42
  }
30
43
  /**
31
44
  * Find colors in icon
45
+ *
46
+ * Clean up icon before running this function to convert style to attributes using
47
+ * cleanupInlineStyle() or cleanupSVG(), otherwise results might be inaccurate
32
48
  */
33
49
  export declare function parseColors(svg: SVG, options?: ParseColorsOptions): Promise<FindColorsResult>;
34
50
  /**
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isEmptyColor = exports.parseColors = void 0;
4
4
  const colors_1 = require("@iconify/utils/lib/colors");
5
- const parse_1 = require("../svg/parse");
6
5
  const tags_1 = require("../svg/data/tags");
7
6
  const parse_style_1 = require("../svg/parse-style");
8
7
  const attribs_1 = require("./attribs");
9
8
  const attributes_1 = require("../svg/data/attributes");
9
+ const analyse_1 = require("../svg/analyse");
10
10
  /**
11
11
  * Properties to check
12
12
  */
@@ -14,6 +14,9 @@ const propsToCheck = Object.keys(attribs_1.defaultColorValues);
14
14
  const animatePropsToCheck = ['from', 'to', 'values'];
15
15
  /**
16
16
  * Find colors in icon
17
+ *
18
+ * Clean up icon before running this function to convert style to attributes using
19
+ * cleanupInlineStyle() or cleanupSVG(), otherwise results might be inaccurate
17
20
  */
18
21
  async function parseColors(svg, options = {}) {
19
22
  const result = {
@@ -25,6 +28,9 @@ async function parseColors(svg, options = {}) {
25
28
  const defaultColor = typeof options.defaultColor === 'string'
26
29
  ? (0, colors_1.stringToColor)(options.defaultColor)
27
30
  : options.defaultColor;
31
+ /**
32
+ * Find matching color in results
33
+ */
28
34
  function findColor(color, add = false) {
29
35
  const isString = typeof color === 'string';
30
36
  for (let i = 0; i < result.colors.length; i++) {
@@ -47,29 +53,31 @@ async function parseColors(svg, options = {}) {
47
53
  /**
48
54
  * Add color to item and to results
49
55
  */
50
- function addColorToItem(prop, color, item) {
51
- const addedColor = findColor(color, true);
56
+ function addColorToItem(prop, color, item, add = true) {
57
+ const addedColor = findColor(color, add !== false);
52
58
  if (item) {
53
- const itemColors = item.colors || {};
54
- if (!item.colors) {
55
- item.colors = itemColors;
56
- }
57
- itemColors[prop] = addedColor;
59
+ const itemColors = item._colors || (item._colors = {});
60
+ itemColors[prop] = addedColor === null ? color : addedColor;
58
61
  }
59
62
  }
60
63
  /**
61
64
  * Get element color
62
65
  */
63
- function getElementColor(prop, item) {
66
+ function getElementColor(prop, item, elements) {
64
67
  function find(prop) {
65
68
  var _a;
66
69
  let currentItem = item;
67
70
  while (currentItem) {
68
- const color = (_a = currentItem.colors) === null || _a === void 0 ? void 0 : _a[prop];
71
+ const element = elements.get(currentItem.index);
72
+ const color = (_a = element._colors) === null || _a === void 0 ? void 0 : _a[prop];
69
73
  if (color !== void 0) {
70
74
  return color;
71
75
  }
72
- currentItem = currentItem.parents[0];
76
+ currentItem = currentItem.parent;
77
+ if (currentItem === null || currentItem === void 0 ? void 0 : currentItem.usedAsMask) {
78
+ // Used as mask: color from parent item is irrelevant
79
+ return attribs_1.defaultColorValues[prop];
80
+ }
73
81
  }
74
82
  return attribs_1.defaultColorValues[prop];
75
83
  }
@@ -95,13 +103,19 @@ async function parseColors(svg, options = {}) {
95
103
  // Resolve color
96
104
  const parsedColor = (0, colors_1.stringToColor)(value);
97
105
  const defaultValue = parsedColor || value;
106
+ // Ignore url()
107
+ if ((parsedColor === null || parsedColor === void 0 ? void 0 : parsedColor.type) === 'function' && parsedColor.func === 'url') {
108
+ // Add to item, so it won't be treated as missing, but do not add to results
109
+ addColorToItem(prop, defaultValue, item, false);
110
+ return value;
111
+ }
98
112
  // Check if callback exists
99
113
  if (!options.callback) {
100
114
  addColorToItem(prop, defaultValue, item);
101
115
  return value;
102
116
  }
103
117
  // Call callback
104
- let callbackResult = options.callback(prop, value, parsedColor, item === null || item === void 0 ? void 0 : item.tagName);
118
+ let callbackResult = options.callback(prop, value, parsedColor, item === null || item === void 0 ? void 0 : item.tagName, item);
105
119
  callbackResult =
106
120
  callbackResult instanceof Promise
107
121
  ? await callbackResult
@@ -109,11 +123,7 @@ async function parseColors(svg, options = {}) {
109
123
  // Remove entry
110
124
  switch (callbackResult) {
111
125
  case 'remove': {
112
- if (item) {
113
- item.$element.remove();
114
- item.testChildren = false;
115
- }
116
- return;
126
+ return item ? callbackResult : void 0;
117
127
  }
118
128
  case 'unset':
119
129
  return;
@@ -152,19 +162,58 @@ async function parseColors(svg, options = {}) {
152
162
  result.hasGlobalStyle = true;
153
163
  }
154
164
  return newValue;
155
- }, {
156
- skipMasks: true,
157
165
  });
158
- // Parse colors in SVG
159
- await (0, parse_1.parseSVG)(svg, async (item) => {
160
- const tagName = item.tagName;
161
- if (tags_1.maskAndSymbolTags.has(tagName)) {
162
- // Ignore masks
163
- item.testChildren = false;
166
+ // Analyse SVG
167
+ const iconData = await (0, analyse_1.analyseSVGStructure)(svg, options);
168
+ const { elements, tree } = iconData;
169
+ const cheerio = svg.$svg;
170
+ const removedElements = new Set();
171
+ const parsedElements = new Set();
172
+ // Remove element
173
+ function removeElement(index, element) {
174
+ // Mark all children as removed (direct children as in DOM)
175
+ function removeChildren(element) {
176
+ element.children.forEach((item) => {
177
+ if (item.type !== 'tag') {
178
+ return;
179
+ }
180
+ const element = item;
181
+ const index = element._index;
182
+ if (index && !removedElements.has(index)) {
183
+ element._removed = true;
184
+ removedElements.add(index);
185
+ removeChildren(element);
186
+ }
187
+ });
188
+ }
189
+ // Remove element
190
+ element._removed = true;
191
+ removedElements.add(index);
192
+ removeChildren(element);
193
+ cheerio(element).remove();
194
+ }
195
+ // Parse tree item
196
+ async function parseTreeItem(item) {
197
+ const index = item.index;
198
+ if (removedElements.has(index) || parsedElements.has(index)) {
199
+ return;
200
+ }
201
+ parsedElements.add(index);
202
+ const element = elements.get(index);
203
+ if (element._removed) {
164
204
  return;
165
205
  }
166
- const $element = item.$element;
167
- const attribs = item.element.attribs;
206
+ const { tagName, attribs } = element;
207
+ // Copy colors from parent item
208
+ if (item.parent) {
209
+ const parentIndex = item.parent.index;
210
+ const parentElement = elements.get(parentIndex);
211
+ if (parentElement._colors) {
212
+ element._colors = {
213
+ ...parentElement._colors,
214
+ };
215
+ }
216
+ }
168
217
  // Check common properties
169
218
  for (let i = 0; i < propsToCheck.length; i++) {
170
219
  const prop = propsToCheck[i];
@@ -174,13 +223,24 @@ async function parseColors(svg, options = {}) {
174
223
  }
175
224
  const value = attribs[prop];
176
225
  if (value !== void 0) {
177
- const newValue = await checkColor(prop, value, item);
226
+ const newValue = await checkColor(prop, value, element);
178
227
  if (newValue !== value) {
179
228
  if (newValue === void 0) {
180
- $element.removeAttr(prop);
229
+ // Unset
230
+ cheerio(element).removeAttr(prop);
231
+ if (element._colors) {
232
+ delete element._colors[prop];
233
+ }
234
+ }
235
+ else if (newValue === 'remove') {
236
+ // Remove element
237
+ removeElement(index, element);
238
+ return;
181
239
  }
182
240
  else {
183
- $element.attr(prop, newValue);
241
+ // Change attribute
242
+ // Value in element._colors is changed in checkColor()
243
+ cheerio(element).attr(prop, newValue);
184
244
  }
185
245
  }
186
246
  }
@@ -216,7 +276,7 @@ async function parseColors(svg, options = {}) {
216
276
  }
217
277
  // Merge values back
218
278
  if (updatedValues) {
219
- $element.attr(elementProp, splitValues.join(';'));
279
+ cheerio(element).attr(elementProp, splitValues.join(';'));
220
280
  }
221
281
  }
222
282
  }
@@ -236,20 +296,20 @@ async function parseColors(svg, options = {}) {
236
296
  });
237
297
  // Check colors
238
298
  if (requiredProps) {
239
- const itemColors = item.colors || {};
240
- if (!item.colors) {
241
- item.colors = itemColors;
242
- }
299
+ const itemColors = element._colors || (element._colors = {});
243
300
  for (let i = 0; i < requiredProps.length; i++) {
244
301
  const prop = requiredProps[i];
245
- const color = getElementColor(prop, item);
302
+ const color = getElementColor(prop, item, elements);
246
303
  if (color === attribs_1.defaultBlackColor) {
247
304
  // Default black color: change it
248
305
  if (defaultColor) {
306
+ const defaultColorValue = typeof defaultColor === 'function'
307
+ ? defaultColor(prop, element, item, iconData)
308
+ : defaultColor;
249
309
  // Add color to results and change attribute
250
- findColor(defaultColor, true);
251
- $element.attr(prop, (0, colors_1.colorToString)(defaultColor));
252
- itemColors[prop] = defaultColor;
310
+ findColor(defaultColorValue, true);
311
+ cheerio(element).attr(prop, (0, colors_1.colorToString)(defaultColorValue));
312
+ itemColors[prop] = defaultColorValue;
253
313
  }
254
314
  else {
255
315
  result.hasUnsetColor = true;
@@ -258,7 +318,16 @@ async function parseColors(svg, options = {}) {
258
318
  }
259
319
  }
260
320
  }
261
- });
321
+ // Parse child elements
322
+ for (let i = 0; i < item.children.length; i++) {
323
+ const childItem = item.children[i];
324
+ if (!childItem.usedAsMask) {
325
+ await parseTreeItem(childItem);
326
+ }
327
+ }
328
+ }
329
+ // Parse tree, starting with <svg>
330
+ await parseTreeItem(tree);
262
331
  return result;
263
332
  }
264
333
  exports.parseColors = parseColors;
@@ -4,8 +4,7 @@ import {
4
4
  stringToColor,
5
5
  colorToString
6
6
  } from "@iconify/utils/lib/colors";
7
- import { parseSVG } from "../svg/parse.mjs";
8
- import { animateTags, maskAndSymbolTags, shapeTags } from "../svg/data/tags.mjs";
7
+ import { animateTags, shapeTags } from "../svg/data/tags.mjs";
9
8
  import { parseSVGStyle } from "../svg/parse-style.mjs";
10
9
  import {
11
10
  defaultBlackColor,
@@ -14,6 +13,7 @@ import {
14
13
  specialColorAttributes
15
14
  } from "./attribs.mjs";
16
15
  import { tagSpecificPresentationalAttributes } from "../svg/data/attributes.mjs";
16
+ import { analyseSVGStructure } from "../svg/analyse.mjs";
17
17
  var propsToCheck = Object.keys(defaultColorValues);
18
18
  var animatePropsToCheck = ["from", "to", "values"];
19
19
  async function parseColors(svg, options = {}) {
@@ -40,26 +40,27 @@ async function parseColors(svg, options = {}) {
40
40
  }
41
41
  return null;
42
42
  }
43
- function addColorToItem(prop, color, item) {
44
- const addedColor = findColor(color, true);
43
+ function addColorToItem(prop, color, item, add = true) {
44
+ const addedColor = findColor(color, add !== false);
45
45
  if (item) {
46
- const itemColors = item.colors || {};
47
- if (!item.colors) {
48
- item.colors = itemColors;
49
- }
50
- itemColors[prop] = addedColor;
46
+ const itemColors = item._colors || (item._colors = {});
47
+ itemColors[prop] = addedColor === null ? color : addedColor;
51
48
  }
52
49
  }
53
- function getElementColor(prop, item) {
50
+ function getElementColor(prop, item, elements2) {
54
51
  function find(prop2) {
55
52
  var _a;
56
53
  let currentItem = item;
57
54
  while (currentItem) {
58
- const color = (_a = currentItem.colors) == null ? void 0 : _a[prop2];
55
+ const element = elements2.get(currentItem.index);
56
+ const color = (_a = element._colors) == null ? void 0 : _a[prop2];
59
57
  if (color !== void 0) {
60
58
  return color;
61
59
  }
62
- currentItem = currentItem.parents[0];
60
+ currentItem = currentItem.parent;
61
+ if (currentItem == null ? void 0 : currentItem.usedAsMask) {
62
+ return defaultColorValues[prop2];
63
+ }
63
64
  }
64
65
  return defaultColorValues[prop2];
65
66
  }
@@ -77,19 +78,19 @@ async function parseColors(svg, options = {}) {
77
78
  }
78
79
  const parsedColor = stringToColor(value);
79
80
  const defaultValue = parsedColor || value;
81
+ if ((parsedColor == null ? void 0 : parsedColor.type) === "function" && parsedColor.func === "url") {
82
+ addColorToItem(prop, defaultValue, item, false);
83
+ return value;
84
+ }
80
85
  if (!options.callback) {
81
86
  addColorToItem(prop, defaultValue, item);
82
87
  return value;
83
88
  }
84
- let callbackResult = options.callback(prop, value, parsedColor, item == null ? void 0 : item.tagName);
89
+ let callbackResult = options.callback(prop, value, parsedColor, item == null ? void 0 : item.tagName, item);
85
90
  callbackResult = callbackResult instanceof Promise ? await callbackResult : callbackResult;
86
91
  switch (callbackResult) {
87
92
  case "remove": {
88
- if (item) {
89
- item.$element.remove();
90
- item.testChildren = false;
91
- }
92
- return;
93
+ return item ? callbackResult : void 0;
93
94
  }
94
95
  case "unset":
95
96
  return;
@@ -122,17 +123,52 @@ async function parseColors(svg, options = {}) {
122
123
  result.hasGlobalStyle = true;
123
124
  }
124
125
  return newValue;
125
- }, {
126
- skipMasks: true
127
126
  });
128
- await parseSVG(svg, async (item) => {
129
- const tagName = item.tagName;
130
- if (maskAndSymbolTags.has(tagName)) {
131
- item.testChildren = false;
127
+ const iconData = await analyseSVGStructure(svg, options);
128
+ const { elements, tree } = iconData;
129
+ const cheerio = svg.$svg;
130
+ const removedElements = new Set();
131
+ const parsedElements = new Set();
132
+ function removeElement(index, element) {
133
+ function removeChildren(element2) {
134
+ element2.children.forEach((item) => {
135
+ if (item.type !== "tag") {
136
+ return;
137
+ }
138
+ const element3 = item;
139
+ const index2 = element3._index;
140
+ if (index2 && !removedElements.has(index2)) {
141
+ element3._removed = true;
142
+ removedElements.add(index2);
143
+ removeChildren(element3);
144
+ }
145
+ });
146
+ }
147
+ element._removed = true;
148
+ removedElements.add(index);
149
+ removeChildren(element);
150
+ cheerio(element).remove();
151
+ }
152
+ async function parseTreeItem(item) {
153
+ const index = item.index;
154
+ if (removedElements.has(index) || parsedElements.has(index)) {
132
155
  return;
133
156
  }
134
- const $element = item.$element;
135
- const attribs = item.element.attribs;
157
+ parsedElements.add(index);
158
+ const element = elements.get(index);
159
+ if (element._removed) {
160
+ return;
161
+ }
162
+ const { tagName, attribs } = element;
163
+ if (item.parent) {
164
+ const parentIndex = item.parent.index;
165
+ const parentElement = elements.get(parentIndex);
166
+ if (parentElement._colors) {
167
+ element._colors = {
168
+ ...parentElement._colors
169
+ };
170
+ }
171
+ }
136
172
  for (let i = 0; i < propsToCheck.length; i++) {
137
173
  const prop = propsToCheck[i];
138
174
  if (prop === "fill" && animateTags.has(tagName)) {
@@ -140,12 +176,18 @@ async function parseColors(svg, options = {}) {
140
176
  }
141
177
  const value = attribs[prop];
142
178
  if (value !== void 0) {
143
- const newValue = await checkColor(prop, value, item);
179
+ const newValue = await checkColor(prop, value, element);
144
180
  if (newValue !== value) {
145
181
  if (newValue === void 0) {
146
- $element.removeAttr(prop);
182
+ cheerio(element).removeAttr(prop);
183
+ if (element._colors) {
184
+ delete element._colors[prop];
185
+ }
186
+ } else if (newValue === "remove") {
187
+ removeElement(index, element);
188
+ return;
147
189
  } else {
148
- $element.attr(prop, newValue);
190
+ cheerio(element).attr(prop, newValue);
149
191
  }
150
192
  }
151
193
  }
@@ -172,7 +214,7 @@ async function parseColors(svg, options = {}) {
172
214
  }
173
215
  }
174
216
  if (updatedValues) {
175
- $element.attr(elementProp, splitValues.join(";"));
217
+ cheerio(element).attr(elementProp, splitValues.join(";"));
176
218
  }
177
219
  }
178
220
  }
@@ -189,18 +231,16 @@ async function parseColors(svg, options = {}) {
189
231
  }
190
232
  });
191
233
  if (requiredProps) {
192
- const itemColors = item.colors || {};
193
- if (!item.colors) {
194
- item.colors = itemColors;
195
- }
234
+ const itemColors = element._colors || (element._colors = {});
196
235
  for (let i = 0; i < requiredProps.length; i++) {
197
236
  const prop = requiredProps[i];
198
- const color = getElementColor(prop, item);
237
+ const color = getElementColor(prop, item, elements);
199
238
  if (color === defaultBlackColor) {
200
239
  if (defaultColor) {
201
- findColor(defaultColor, true);
202
- $element.attr(prop, colorToString(defaultColor));
203
- itemColors[prop] = defaultColor;
240
+ const defaultColorValue = typeof defaultColor === "function" ? defaultColor(prop, element, item, iconData) : defaultColor;
241
+ findColor(defaultColorValue, true);
242
+ cheerio(element).attr(prop, colorToString(defaultColorValue));
243
+ itemColors[prop] = defaultColorValue;
204
244
  } else {
205
245
  result.hasUnsetColor = true;
206
246
  }
@@ -208,7 +248,14 @@ async function parseColors(svg, options = {}) {
208
248
  }
209
249
  }
210
250
  }
211
- });
251
+ for (let i = 0; i < item.children.length; i++) {
252
+ const childItem = item.children[i];
253
+ if (!childItem.usedAsMask) {
254
+ await parseTreeItem(childItem);
255
+ }
256
+ }
257
+ }
258
+ await parseTreeItem(tree);
212
259
  return result;
213
260
  }
214
261
  function isEmptyColor(color) {
@@ -35,9 +35,12 @@ async function validateColors(svg, expectMonotone, options) {
35
35
  throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
36
36
  }
37
37
  return;
38
- // Do not allow other colors
39
38
  default:
40
- throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
39
+ // Allow url()
40
+ if (color.type !== 'function' || color.func !== 'url') {
41
+ // Do not allow other colors
42
+ throw new Error('Unexpected color: ' + (0, colors_1.colorToString)(color));
43
+ }
41
44
  }
42
45
  });
43
46
  return palette;
@@ -23,7 +23,9 @@ async function validateColors(svg, expectMonotone, options) {
23
23
  }
24
24
  return;
25
25
  default:
26
- throw new Error("Unexpected color: " + colorToString(color));
26
+ if (color.type !== "function" || color.func !== "url") {
27
+ throw new Error("Unexpected color: " + colorToString(color));
28
+ }
27
29
  }
28
30
  });
29
31
  return palette;
@@ -71,7 +71,6 @@ class IconSet {
71
71
  parent,
72
72
  props,
73
73
  chars,
74
- categories: new Set(),
75
74
  };
76
75
  entries[name] = entry;
77
76
  }
@@ -111,7 +110,6 @@ class IconSet {
111
110
  const icon = entries[iconName];
112
111
  switch (icon === null || icon === void 0 ? void 0 : icon.type) {
113
112
  case 'icon':
114
- case 'variation':
115
113
  icon.categories.add(item);
116
114
  }
117
115
  });
@@ -342,6 +340,7 @@ class IconSet {
342
340
  .forEach((item) => {
343
341
  const names = this.listCategory(item);
344
342
  if (names) {
343
+ names.sort((a, b) => a.localeCompare(b));
345
344
  categories[item.title] = names;
346
345
  }
347
346
  });
@@ -460,8 +459,8 @@ class IconSet {
460
459
  return null;
461
460
  }
462
461
  // Find icons
463
- const icons = this._filter((_key, item, icon) => {
464
- if (item.type === 'alias' || item.props.hidden || (icon === null || icon === void 0 ? void 0 : icon.hidden)) {
462
+ const icons = this._filter((_key, item) => {
463
+ if (item.type !== 'icon' || item.props.hidden) {
465
464
  return false;
466
465
  }
467
466
  return item.categories.has(categoryItem);
@@ -619,26 +618,11 @@ class IconSet {
619
618
  * Add/update alias with props
620
619
  */
621
620
  setVariation(name, parent, props) {
622
- // Copy categories
623
- let categories;
624
- while (!categories) {
625
- const parentItem = this.entries[parent];
626
- if (!parentItem) {
627
- return false;
628
- }
629
- if (parentItem.type === 'alias') {
630
- parent = parentItem.parent;
631
- }
632
- else {
633
- categories = new Set(parentItem.categories);
634
- }
635
- }
636
621
  return this.setItem(name, {
637
622
  type: 'variation',
638
623
  parent,
639
624
  props,
640
625
  chars: new Set(),
641
- categories,
642
626
  });
643
627
  }
644
628
  /**
@@ -664,7 +648,7 @@ class IconSet {
664
648
  body,
665
649
  props,
666
650
  chars: item.chars,
667
- categories: item.categories,
651
+ categories: item.type === 'icon' ? item.categories : new Set(),
668
652
  });
669
653
  }
670
654
  }
@@ -699,7 +683,6 @@ class IconSet {
699
683
  }
700
684
  switch (item.type) {
701
685
  case 'icon':
702
- case 'variation':
703
686
  if (item.categories.has(categoryItem) !== add) {
704
687
  categoryItem.count += add ? 1 : -1;
705
688
  item.categories[add ? 'add' : 'delete'](categoryItem);