@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,43 @@
1
+ // src/misc/scan.ts
2
+ import { promises as fs } from "fs";
3
+ async function scanDirectory(path, callback, subdirs = true) {
4
+ const results = [];
5
+ if (path.length && path.slice(-1) !== "/") {
6
+ path += "/";
7
+ }
8
+ async function scan(subdir) {
9
+ const files = await fs.readdir(path + subdir);
10
+ for (let i = 0; i < files.length; i++) {
11
+ const filename = files[i];
12
+ if (filename.slice(0, 1) === ".") {
13
+ continue;
14
+ }
15
+ const stat = await fs.lstat(path + subdir + filename);
16
+ if (stat.isDirectory()) {
17
+ if (subdirs) {
18
+ await scan(subdir + filename + "/");
19
+ }
20
+ continue;
21
+ }
22
+ if (!stat.isFile()) {
23
+ continue;
24
+ }
25
+ const parts = filename.split(".");
26
+ const ext = parts.length > 1 ? "." + parts.pop() : "";
27
+ const file = parts.join(".");
28
+ let callbackResult = callback(ext, file, subdir, path);
29
+ if (callbackResult instanceof Promise) {
30
+ callbackResult = await callbackResult;
31
+ }
32
+ if (callbackResult === void 0 || callbackResult === false || callbackResult === null) {
33
+ continue;
34
+ }
35
+ results.push(callbackResult === true ? subdir + filename : callbackResult);
36
+ }
37
+ }
38
+ await scan("");
39
+ return results;
40
+ }
41
+ export {
42
+ scanDirectory
43
+ };
@@ -0,0 +1,5 @@
1
+ import type { SVG } from '../svg';
2
+ /**
3
+ * De-optimise paths. Compressed paths are still not supported by some software.
4
+ */
5
+ export declare function deOptimisePaths(svg: SVG): Promise<void>;
@@ -0,0 +1,303 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deOptimisePaths = void 0;
4
+ const parse_1 = require("../svg/parse");
5
+ /**
6
+ * Command constants
7
+ */
8
+ const CLOSE_PATH = 1;
9
+ const MOVE_TO = 2;
10
+ const HORIZ_LINE_TO = 4;
11
+ const VERT_LINE_TO = 8;
12
+ const LINE_TO = 16;
13
+ const CURVE_TO = 32;
14
+ const SMOOTH_CURVE_TO = 64;
15
+ const QUAD_TO = 128;
16
+ const SMOOTH_QUAD_TO = 256;
17
+ const ARC = 512;
18
+ /**
19
+ * Number of arguments for each command
20
+ */
21
+ const argCount = {
22
+ [MOVE_TO]: 2,
23
+ [LINE_TO]: 2,
24
+ [HORIZ_LINE_TO]: 1,
25
+ [VERT_LINE_TO]: 1,
26
+ [CLOSE_PATH]: 0,
27
+ [QUAD_TO]: 4,
28
+ [SMOOTH_QUAD_TO]: 2,
29
+ [CURVE_TO]: 6,
30
+ [SMOOTH_CURVE_TO]: 4,
31
+ [ARC]: 7,
32
+ };
33
+ /**
34
+ * Check if character is a digit
35
+ */
36
+ const isDigit = (num) => num >= 48 && num <= 57;
37
+ /**
38
+ * Check if character is white space
39
+ */
40
+ const isWhiteSpace = (num) => num === 32 || num === 9 || num === 13 || num === 10;
41
+ /**
42
+ * Clean up path
43
+ *
44
+ * @param {string} path
45
+ * @return {string}
46
+ */
47
+ function cleanPath(path) {
48
+ const commands = [];
49
+ const length = path.length;
50
+ let currentNumber = '';
51
+ let currentNumberHasExp = false;
52
+ let currentNumberHasExpDigits = false;
53
+ let currentNumberHasDecimal = false;
54
+ let canParseCommandOrComma = true;
55
+ let currentCommand = null;
56
+ let currentCommandType = null;
57
+ let currentArgs = [];
58
+ let i = 0;
59
+ const finishCommand = () => {
60
+ if (currentCommand !== null) {
61
+ commands.push({
62
+ command: currentCommand,
63
+ params: currentArgs.slice(0),
64
+ });
65
+ currentArgs = [];
66
+ canParseCommandOrComma = true;
67
+ }
68
+ };
69
+ const parseNumber = () => {
70
+ // Number ended - validate it
71
+ if (currentNumber !== '' && currentCommandType) {
72
+ let value = Number(currentNumber);
73
+ if (isNaN(value)) {
74
+ throw new Error('Invalid number "' + currentNumber + '" at ' + i);
75
+ }
76
+ // Validate arc arguments
77
+ if (currentCommandType === ARC) {
78
+ if (currentArgs.length < 2 && value <= 0) {
79
+ throw new Error('Expected positive number, got "' + value + '" at ' + i);
80
+ }
81
+ // eslint-disable-next-line no-constant-condition
82
+ while (true) {
83
+ // Not flag
84
+ if (currentArgs.length < 3 || currentArgs.length > 4) {
85
+ break;
86
+ }
87
+ // Valid flag
88
+ if (currentNumber === '0' || currentNumber === '1') {
89
+ break;
90
+ }
91
+ // Unpack flag
92
+ const slice = currentNumber.slice(0, 1);
93
+ const newNumber = currentNumber.slice(1);
94
+ const newValue = Number(newNumber);
95
+ if (slice === '0' || slice === '1') {
96
+ // Valid flag
97
+ if (isNaN(newValue)) {
98
+ throw new Error('Invalid number "' + currentNumber + '" at ' + i);
99
+ }
100
+ currentArgs.push(slice);
101
+ currentNumber = newNumber;
102
+ value = newValue;
103
+ continue;
104
+ }
105
+ throw new Error('Expected a flag, got "' + currentNumber + '" at ' + i);
106
+ }
107
+ }
108
+ // Add current number to arguments list
109
+ currentArgs.push(currentNumber);
110
+ if (currentArgs.length === argCount[currentCommandType]) {
111
+ finishCommand();
112
+ }
113
+ currentNumber = '';
114
+ currentNumberHasExpDigits = false;
115
+ currentNumberHasExp = false;
116
+ currentNumberHasDecimal = false;
117
+ canParseCommandOrComma = true;
118
+ }
119
+ };
120
+ for (i = 0; i < length; i++) {
121
+ const char = path[i];
122
+ const num = char.charCodeAt(0);
123
+ // Test for number
124
+ if (isDigit(num)) {
125
+ currentNumber += char;
126
+ currentNumberHasExpDigits = currentNumberHasExp;
127
+ continue;
128
+ }
129
+ // Test for exponential number
130
+ if (char === 'e' || char === 'E') {
131
+ currentNumber += char;
132
+ currentNumberHasExp = true;
133
+ continue;
134
+ }
135
+ // Test for number signs
136
+ if ((char === '-' || char === '+') &&
137
+ currentNumberHasExp &&
138
+ !currentNumberHasExpDigits) {
139
+ currentNumber += char;
140
+ continue;
141
+ }
142
+ // Decimal point
143
+ if (char === '.' && !currentNumberHasExp && !currentNumberHasDecimal) {
144
+ currentNumber += char;
145
+ currentNumberHasDecimal = true;
146
+ continue;
147
+ }
148
+ // Number ended - validate it
149
+ parseNumber();
150
+ // White space
151
+ if (isWhiteSpace(num)) {
152
+ continue;
153
+ }
154
+ // Only one comma per command
155
+ if (canParseCommandOrComma && char === ',') {
156
+ canParseCommandOrComma = false;
157
+ continue;
158
+ }
159
+ // New number
160
+ if (char === '+' || char === '-' || char === '.') {
161
+ currentNumber = char;
162
+ currentNumberHasDecimal = char === '.';
163
+ continue;
164
+ }
165
+ // Expecting new command, so argument should be empty
166
+ if (currentArgs.length > 0) {
167
+ throw new Error('Unexpected command at ' + i);
168
+ }
169
+ // Test comma, reset value
170
+ if (!canParseCommandOrComma) {
171
+ throw new Error('Command cannot follow comma at ' + i + '');
172
+ }
173
+ canParseCommandOrComma = false;
174
+ // Detect next command
175
+ currentCommand = char;
176
+ switch (char) {
177
+ case 'z':
178
+ case 'Z':
179
+ // Close path
180
+ commands.push({
181
+ command: char,
182
+ params: [],
183
+ });
184
+ canParseCommandOrComma = true;
185
+ currentCommandType = null;
186
+ currentCommand = null;
187
+ break;
188
+ case 'h':
189
+ case 'H':
190
+ // Horizontal move
191
+ currentCommandType = HORIZ_LINE_TO;
192
+ break;
193
+ case 'v':
194
+ case 'V':
195
+ // Vertical move
196
+ currentCommandType = VERT_LINE_TO;
197
+ break;
198
+ case 'm':
199
+ case 'M':
200
+ // Move to
201
+ currentCommandType = MOVE_TO;
202
+ break;
203
+ case 'l':
204
+ case 'L':
205
+ // Line to
206
+ currentCommandType = LINE_TO;
207
+ break;
208
+ case 'c':
209
+ case 'C':
210
+ // Curve
211
+ currentCommandType = CURVE_TO;
212
+ break;
213
+ case 's':
214
+ case 'S':
215
+ // Smooth curve
216
+ currentCommandType = SMOOTH_CURVE_TO;
217
+ break;
218
+ case 'q':
219
+ case 'Q':
220
+ // Quadratic bezier curve
221
+ currentCommandType = QUAD_TO;
222
+ break;
223
+ case 't':
224
+ case 'T':
225
+ // Smooth quadratic bezier curve
226
+ currentCommandType = SMOOTH_QUAD_TO;
227
+ break;
228
+ case 'a':
229
+ case 'A':
230
+ // Elliptic arc
231
+ currentCommandType = ARC;
232
+ break;
233
+ default:
234
+ throw new Error('Unexpected character "' + char + '" at ' + i);
235
+ }
236
+ }
237
+ // Parse last number
238
+ parseNumber();
239
+ // Add last command
240
+ if (currentArgs.length) {
241
+ if (!currentCommandType) {
242
+ throw new Error('Empty path');
243
+ }
244
+ if (currentArgs.length !== argCount[currentCommandType]) {
245
+ throw new Error('Unexpected end of path at ' + i);
246
+ }
247
+ finishCommand();
248
+ }
249
+ // Build path
250
+ let output = '';
251
+ commands.forEach((item) => {
252
+ output += item.command;
253
+ item.params.forEach((value, index) => {
254
+ if (index > 0) {
255
+ const char = value[0];
256
+ // noinspection FallThroughInSwitchStatementJS
257
+ switch (char) {
258
+ case '-':
259
+ case '+':
260
+ // Number - no space
261
+ break;
262
+ case '.':
263
+ // Dot - no space if previous entry was command
264
+ if (index < 1) {
265
+ break;
266
+ }
267
+ // No space if previous entry had dot
268
+ if (item.params[index - 1].indexOf('.') !== -1) {
269
+ break;
270
+ }
271
+ // no-fallthrough
272
+ default:
273
+ output += ' ';
274
+ }
275
+ }
276
+ output += value;
277
+ });
278
+ });
279
+ return output;
280
+ }
281
+ /**
282
+ * De-optimise paths. Compressed paths are still not supported by some software.
283
+ */
284
+ async function deOptimisePaths(svg) {
285
+ await (0, parse_1.parseSVG)(svg, (item) => {
286
+ if (item.tagName !== 'path') {
287
+ return;
288
+ }
289
+ const d = item.element.attribs.d;
290
+ if (typeof d === 'string') {
291
+ try {
292
+ const optimised = cleanPath(d);
293
+ if (optimised !== d) {
294
+ item.$element.attr('d', optimised);
295
+ }
296
+ }
297
+ catch (err) {
298
+ //
299
+ }
300
+ }
301
+ });
302
+ }
303
+ exports.deOptimisePaths = deOptimisePaths;
@@ -0,0 +1,241 @@
1
+ // src/optimise/flags.ts
2
+ import { parseSVG } from "../svg/parse.mjs";
3
+ var CLOSE_PATH = 1;
4
+ var MOVE_TO = 2;
5
+ var HORIZ_LINE_TO = 4;
6
+ var VERT_LINE_TO = 8;
7
+ var LINE_TO = 16;
8
+ var CURVE_TO = 32;
9
+ var SMOOTH_CURVE_TO = 64;
10
+ var QUAD_TO = 128;
11
+ var SMOOTH_QUAD_TO = 256;
12
+ var ARC = 512;
13
+ var argCount = {
14
+ [MOVE_TO]: 2,
15
+ [LINE_TO]: 2,
16
+ [HORIZ_LINE_TO]: 1,
17
+ [VERT_LINE_TO]: 1,
18
+ [CLOSE_PATH]: 0,
19
+ [QUAD_TO]: 4,
20
+ [SMOOTH_QUAD_TO]: 2,
21
+ [CURVE_TO]: 6,
22
+ [SMOOTH_CURVE_TO]: 4,
23
+ [ARC]: 7
24
+ };
25
+ var isDigit = (num) => num >= 48 && num <= 57;
26
+ var isWhiteSpace = (num) => num === 32 || num === 9 || num === 13 || num === 10;
27
+ function cleanPath(path) {
28
+ const commands = [];
29
+ const length = path.length;
30
+ let currentNumber = "";
31
+ let currentNumberHasExp = false;
32
+ let currentNumberHasExpDigits = false;
33
+ let currentNumberHasDecimal = false;
34
+ let canParseCommandOrComma = true;
35
+ let currentCommand = null;
36
+ let currentCommandType = null;
37
+ let currentArgs = [];
38
+ let i = 0;
39
+ const finishCommand = () => {
40
+ if (currentCommand !== null) {
41
+ commands.push({
42
+ command: currentCommand,
43
+ params: currentArgs.slice(0)
44
+ });
45
+ currentArgs = [];
46
+ canParseCommandOrComma = true;
47
+ }
48
+ };
49
+ const parseNumber = () => {
50
+ if (currentNumber !== "" && currentCommandType) {
51
+ let value = Number(currentNumber);
52
+ if (isNaN(value)) {
53
+ throw new Error('Invalid number "' + currentNumber + '" at ' + i);
54
+ }
55
+ if (currentCommandType === ARC) {
56
+ if (currentArgs.length < 2 && value <= 0) {
57
+ throw new Error('Expected positive number, got "' + value + '" at ' + i);
58
+ }
59
+ while (true) {
60
+ if (currentArgs.length < 3 || currentArgs.length > 4) {
61
+ break;
62
+ }
63
+ if (currentNumber === "0" || currentNumber === "1") {
64
+ break;
65
+ }
66
+ const slice = currentNumber.slice(0, 1);
67
+ const newNumber = currentNumber.slice(1);
68
+ const newValue = Number(newNumber);
69
+ if (slice === "0" || slice === "1") {
70
+ if (isNaN(newValue)) {
71
+ throw new Error('Invalid number "' + currentNumber + '" at ' + i);
72
+ }
73
+ currentArgs.push(slice);
74
+ currentNumber = newNumber;
75
+ value = newValue;
76
+ continue;
77
+ }
78
+ throw new Error('Expected a flag, got "' + currentNumber + '" at ' + i);
79
+ }
80
+ }
81
+ currentArgs.push(currentNumber);
82
+ if (currentArgs.length === argCount[currentCommandType]) {
83
+ finishCommand();
84
+ }
85
+ currentNumber = "";
86
+ currentNumberHasExpDigits = false;
87
+ currentNumberHasExp = false;
88
+ currentNumberHasDecimal = false;
89
+ canParseCommandOrComma = true;
90
+ }
91
+ };
92
+ for (i = 0; i < length; i++) {
93
+ const char = path[i];
94
+ const num = char.charCodeAt(0);
95
+ if (isDigit(num)) {
96
+ currentNumber += char;
97
+ currentNumberHasExpDigits = currentNumberHasExp;
98
+ continue;
99
+ }
100
+ if (char === "e" || char === "E") {
101
+ currentNumber += char;
102
+ currentNumberHasExp = true;
103
+ continue;
104
+ }
105
+ if ((char === "-" || char === "+") && currentNumberHasExp && !currentNumberHasExpDigits) {
106
+ currentNumber += char;
107
+ continue;
108
+ }
109
+ if (char === "." && !currentNumberHasExp && !currentNumberHasDecimal) {
110
+ currentNumber += char;
111
+ currentNumberHasDecimal = true;
112
+ continue;
113
+ }
114
+ parseNumber();
115
+ if (isWhiteSpace(num)) {
116
+ continue;
117
+ }
118
+ if (canParseCommandOrComma && char === ",") {
119
+ canParseCommandOrComma = false;
120
+ continue;
121
+ }
122
+ if (char === "+" || char === "-" || char === ".") {
123
+ currentNumber = char;
124
+ currentNumberHasDecimal = char === ".";
125
+ continue;
126
+ }
127
+ if (currentArgs.length > 0) {
128
+ throw new Error("Unexpected command at " + i);
129
+ }
130
+ if (!canParseCommandOrComma) {
131
+ throw new Error("Command cannot follow comma at " + i + "");
132
+ }
133
+ canParseCommandOrComma = false;
134
+ currentCommand = char;
135
+ switch (char) {
136
+ case "z":
137
+ case "Z":
138
+ commands.push({
139
+ command: char,
140
+ params: []
141
+ });
142
+ canParseCommandOrComma = true;
143
+ currentCommandType = null;
144
+ currentCommand = null;
145
+ break;
146
+ case "h":
147
+ case "H":
148
+ currentCommandType = HORIZ_LINE_TO;
149
+ break;
150
+ case "v":
151
+ case "V":
152
+ currentCommandType = VERT_LINE_TO;
153
+ break;
154
+ case "m":
155
+ case "M":
156
+ currentCommandType = MOVE_TO;
157
+ break;
158
+ case "l":
159
+ case "L":
160
+ currentCommandType = LINE_TO;
161
+ break;
162
+ case "c":
163
+ case "C":
164
+ currentCommandType = CURVE_TO;
165
+ break;
166
+ case "s":
167
+ case "S":
168
+ currentCommandType = SMOOTH_CURVE_TO;
169
+ break;
170
+ case "q":
171
+ case "Q":
172
+ currentCommandType = QUAD_TO;
173
+ break;
174
+ case "t":
175
+ case "T":
176
+ currentCommandType = SMOOTH_QUAD_TO;
177
+ break;
178
+ case "a":
179
+ case "A":
180
+ currentCommandType = ARC;
181
+ break;
182
+ default:
183
+ throw new Error('Unexpected character "' + char + '" at ' + i);
184
+ }
185
+ }
186
+ parseNumber();
187
+ if (currentArgs.length) {
188
+ if (!currentCommandType) {
189
+ throw new Error("Empty path");
190
+ }
191
+ if (currentArgs.length !== argCount[currentCommandType]) {
192
+ throw new Error("Unexpected end of path at " + i);
193
+ }
194
+ finishCommand();
195
+ }
196
+ let output = "";
197
+ commands.forEach((item) => {
198
+ output += item.command;
199
+ item.params.forEach((value, index) => {
200
+ if (index > 0) {
201
+ const char = value[0];
202
+ switch (char) {
203
+ case "-":
204
+ case "+":
205
+ break;
206
+ case ".":
207
+ if (index < 1) {
208
+ break;
209
+ }
210
+ if (item.params[index - 1].indexOf(".") !== -1) {
211
+ break;
212
+ }
213
+ default:
214
+ output += " ";
215
+ }
216
+ }
217
+ output += value;
218
+ });
219
+ });
220
+ return output;
221
+ }
222
+ async function deOptimisePaths(svg) {
223
+ await parseSVG(svg, (item) => {
224
+ if (item.tagName !== "path") {
225
+ return;
226
+ }
227
+ const d = item.element.attribs.d;
228
+ if (typeof d === "string") {
229
+ try {
230
+ const optimised = cleanPath(d);
231
+ if (optimised !== d) {
232
+ item.$element.attr("d", optimised);
233
+ }
234
+ } catch (err) {
235
+ }
236
+ }
237
+ });
238
+ }
239
+ export {
240
+ deOptimisePaths
241
+ };
@@ -0,0 +1,5 @@
1
+ import type { SVG } from '../svg';
2
+ /**
3
+ * Scale icon
4
+ */
5
+ export declare function scaleSVG(svg: SVG, scale: number): Promise<void>;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scaleSVG = void 0;
4
+ const svgo_1 = require("./svgo");
5
+ /**
6
+ * Scale icon
7
+ */
8
+ async function scaleSVG(svg, scale) {
9
+ const viewBox = svg.viewBox;
10
+ const width = viewBox.width * scale;
11
+ const height = viewBox.height * scale;
12
+ const left = viewBox.left * scale;
13
+ const top = viewBox.top * scale;
14
+ const content = '<svg width="' +
15
+ width +
16
+ '" height="' +
17
+ height +
18
+ '" viewBox="' +
19
+ left +
20
+ ' ' +
21
+ top +
22
+ ' ' +
23
+ width +
24
+ ' ' +
25
+ height +
26
+ '">' +
27
+ '<g transform="scale(' +
28
+ scale +
29
+ ')">' +
30
+ svg.getBody() +
31
+ '</g></svg>';
32
+ svg.load(content);
33
+ await (0, svgo_1.runSVGO)(svg, {
34
+ plugins: [
35
+ 'collapseGroups',
36
+ 'convertTransform',
37
+ 'convertPathData',
38
+ 'sortAttrs',
39
+ ],
40
+ });
41
+ }
42
+ exports.scaleSVG = scaleSVG;
@@ -0,0 +1,22 @@
1
+ // src/optimise/scale.ts
2
+ import { runSVGO } from "./svgo.mjs";
3
+ async function scaleSVG(svg, scale) {
4
+ const viewBox = svg.viewBox;
5
+ const width = viewBox.width * scale;
6
+ const height = viewBox.height * scale;
7
+ const left = viewBox.left * scale;
8
+ const top = viewBox.top * scale;
9
+ const content = '<svg width="' + width + '" height="' + height + '" viewBox="' + left + " " + top + " " + width + " " + height + '"><g transform="scale(' + scale + ')">' + svg.getBody() + "</g></svg>";
10
+ svg.load(content);
11
+ await runSVGO(svg, {
12
+ plugins: [
13
+ "collapseGroups",
14
+ "convertTransform",
15
+ "convertPathData",
16
+ "sortAttrs"
17
+ ]
18
+ });
19
+ }
20
+ export {
21
+ scaleSVG
22
+ };
@@ -0,0 +1,27 @@
1
+ import type { Plugin } from 'svgo';
2
+ import type { SVG } from '../svg';
3
+ export declare const defaultSVGOPlugins: Plugin[];
4
+ /**
5
+ * Plugins that modify shapes. Added to plugins list, unless 'keepShapes' option is enabled
6
+ */
7
+ export declare const shapeModifiyingSVGOPlugins: Plugin[];
8
+ /**
9
+ * Options
10
+ */
11
+ interface SVGOCommonOptions {
12
+ multipass?: boolean;
13
+ }
14
+ interface SVGOOptionsWithPlugin extends SVGOCommonOptions {
15
+ plugins: Plugin[];
16
+ }
17
+ interface SVGOptionsWithoutPlugin extends SVGOCommonOptions {
18
+ plugins?: undefined;
19
+ keepShapes?: boolean;
20
+ cleanupIDs?: string | false;
21
+ }
22
+ declare type SVGOOptions = SVGOOptionsWithPlugin | SVGOptionsWithoutPlugin;
23
+ /**
24
+ * Run SVGO on icon
25
+ */
26
+ export declare function runSVGO(svg: SVG, options?: SVGOOptions): Promise<void>;
27
+ export {};