@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.
- package/lib/colors/parse.d.ts +19 -3
- package/lib/colors/parse.js +109 -40
- package/lib/colors/parse.mjs +86 -39
- package/lib/colors/validate.js +5 -2
- package/lib/colors/validate.mjs +3 -1
- package/lib/icon-set/index.js +4 -21
- package/lib/icon-set/index.mjs +6 -21
- package/lib/icon-set/merge.js +0 -1
- package/lib/icon-set/merge.mjs +1 -2
- package/lib/icon-set/types.d.ts +3 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -1
- package/lib/index.mjs +4 -0
- package/lib/optimise/flags.js +9 -0
- package/lib/optimise/flags.mjs +8 -0
- package/lib/optimise/global-style.d.ts +5 -0
- package/lib/optimise/global-style.js +158 -0
- package/lib/optimise/global-style.mjs +129 -0
- package/lib/optimise/svgo.js +1 -1
- package/lib/optimise/svgo.mjs +0 -1
- package/lib/svg/analyse/error.d.ts +5 -0
- package/lib/svg/analyse/error.js +22 -0
- package/lib/svg/analyse/error.mjs +16 -0
- package/lib/svg/analyse/types.d.ts +89 -0
- package/lib/svg/analyse/types.js +2 -0
- package/lib/svg/analyse/types.mjs +0 -0
- package/lib/svg/analyse.d.ts +8 -0
- package/lib/svg/analyse.js +352 -0
- package/lib/svg/analyse.mjs +302 -0
- package/lib/svg/cleanup/attribs.d.ts +1 -1
- package/lib/svg/cleanup/attribs.js +8 -0
- package/lib/svg/cleanup/attribs.mjs +8 -1
- package/lib/svg/cleanup/bad-tags.d.ts +1 -1
- package/lib/svg/cleanup/bad-tags.js +0 -2
- package/lib/svg/cleanup/bad-tags.mjs +0 -3
- package/lib/svg/cleanup/inline-style.d.ts +1 -1
- package/lib/svg/cleanup/root-svg.d.ts +1 -1
- package/lib/svg/cleanup/root-svg.js +4 -2
- package/lib/svg/cleanup/root-svg.mjs +3 -3
- package/lib/svg/cleanup/svgo-style.d.ts +1 -1
- package/lib/svg/data/attributes.js +1 -1
- package/lib/svg/data/attributes.mjs +1 -1
- package/lib/svg/data/tags.d.ts +15 -7
- package/lib/svg/data/tags.js +20 -9
- package/lib/svg/data/tags.mjs +11 -6
- package/lib/svg/parse-style.d.ts +7 -7
- package/lib/svg/parse-style.js +27 -7
- package/lib/svg/parse-style.mjs +26 -7
- package/package.json +18 -2
package/lib/icon-set/index.mjs
CHANGED
|
@@ -46,8 +46,7 @@ var IconSet = class {
|
|
|
46
46
|
type: "variation",
|
|
47
47
|
parent,
|
|
48
48
|
props,
|
|
49
|
-
chars
|
|
50
|
-
categories: new Set()
|
|
49
|
+
chars
|
|
51
50
|
};
|
|
52
51
|
entries[name] = entry;
|
|
53
52
|
} else {
|
|
@@ -82,7 +81,6 @@ var IconSet = class {
|
|
|
82
81
|
const icon = entries[iconName];
|
|
83
82
|
switch (icon == null ? void 0 : icon.type) {
|
|
84
83
|
case "icon":
|
|
85
|
-
case "variation":
|
|
86
84
|
icon.categories.add(item);
|
|
87
85
|
}
|
|
88
86
|
});
|
|
@@ -271,6 +269,7 @@ var IconSet = class {
|
|
|
271
269
|
Array.from(this.categories).sort((a, b) => a.title.localeCompare(b.title)).forEach((item) => {
|
|
272
270
|
const names2 = this.listCategory(item);
|
|
273
271
|
if (names2) {
|
|
272
|
+
names2.sort((a, b) => a.localeCompare(b));
|
|
274
273
|
categories[item.title] = names2;
|
|
275
274
|
}
|
|
276
275
|
});
|
|
@@ -362,8 +361,8 @@ var IconSet = class {
|
|
|
362
361
|
if (!categoryItem) {
|
|
363
362
|
return null;
|
|
364
363
|
}
|
|
365
|
-
const icons = this._filter((_key, item
|
|
366
|
-
if (item.type
|
|
364
|
+
const icons = this._filter((_key, item) => {
|
|
365
|
+
if (item.type !== "icon" || item.props.hidden) {
|
|
367
366
|
return false;
|
|
368
367
|
}
|
|
369
368
|
return item.categories.has(categoryItem);
|
|
@@ -487,24 +486,11 @@ var IconSet = class {
|
|
|
487
486
|
});
|
|
488
487
|
}
|
|
489
488
|
setVariation(name, parent, props) {
|
|
490
|
-
let categories;
|
|
491
|
-
while (!categories) {
|
|
492
|
-
const parentItem = this.entries[parent];
|
|
493
|
-
if (!parentItem) {
|
|
494
|
-
return false;
|
|
495
|
-
}
|
|
496
|
-
if (parentItem.type === "alias") {
|
|
497
|
-
parent = parentItem.parent;
|
|
498
|
-
} else {
|
|
499
|
-
categories = new Set(parentItem.categories);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
489
|
return this.setItem(name, {
|
|
503
490
|
type: "variation",
|
|
504
491
|
parent,
|
|
505
492
|
props,
|
|
506
|
-
chars: new Set()
|
|
507
|
-
categories
|
|
493
|
+
chars: new Set()
|
|
508
494
|
});
|
|
509
495
|
}
|
|
510
496
|
fromSVG(name, svg) {
|
|
@@ -525,7 +511,7 @@ var IconSet = class {
|
|
|
525
511
|
body,
|
|
526
512
|
props,
|
|
527
513
|
chars: item.chars,
|
|
528
|
-
categories: item.categories
|
|
514
|
+
categories: item.type === "icon" ? item.categories : new Set()
|
|
529
515
|
});
|
|
530
516
|
}
|
|
531
517
|
}
|
|
@@ -553,7 +539,6 @@ var IconSet = class {
|
|
|
553
539
|
}
|
|
554
540
|
switch (item.type) {
|
|
555
541
|
case "icon":
|
|
556
|
-
case "variation":
|
|
557
542
|
if (item.categories.has(categoryItem) !== add) {
|
|
558
543
|
categoryItem.count += add ? 1 : -1;
|
|
559
544
|
item.categories[add ? "add" : "delete"](categoryItem);
|
package/lib/icon-set/merge.js
CHANGED
package/lib/icon-set/merge.mjs
CHANGED
package/lib/icon-set/types.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface IconWithChars {
|
|
|
25
25
|
}
|
|
26
26
|
export interface IconWithPropsData extends IconWithChars {
|
|
27
27
|
props: CommonIconProps;
|
|
28
|
+
}
|
|
29
|
+
export interface IconWithCategories {
|
|
28
30
|
categories: Set<IconCategory>;
|
|
29
31
|
}
|
|
30
32
|
export interface IconParentData {
|
|
@@ -33,7 +35,7 @@ export interface IconParentData {
|
|
|
33
35
|
/**
|
|
34
36
|
* Icon types
|
|
35
37
|
*/
|
|
36
|
-
export interface IconSetIcon extends IconWithPropsData {
|
|
38
|
+
export interface IconSetIcon extends IconWithPropsData, IconWithCategories {
|
|
37
39
|
type: 'icon';
|
|
38
40
|
body: string;
|
|
39
41
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { SVG } from './svg/index';
|
|
2
2
|
export { parseSVG } from './svg/parse';
|
|
3
3
|
export { parseSVGStyle } from './svg/parse-style';
|
|
4
|
+
export { analyseSVGStructure } from './svg/analyse';
|
|
4
5
|
export { cleanupSVG } from './svg/cleanup';
|
|
5
6
|
export { removeBadAttributes } from './svg/cleanup/attribs';
|
|
6
7
|
export { checkBadTags } from './svg/cleanup/bad-tags';
|
|
@@ -26,6 +27,7 @@ export { validateColors } from './colors/validate';
|
|
|
26
27
|
export { runSVGO } from './optimise/svgo';
|
|
27
28
|
export { deOptimisePaths } from './optimise/flags';
|
|
28
29
|
export { scaleSVG } from './optimise/scale';
|
|
30
|
+
export { cleanupGlobalStyle } from './optimise/global-style';
|
|
29
31
|
export { exportToDirectory } from './export/directory';
|
|
30
32
|
export { exportIconPackage } from './export/icon-package';
|
|
31
33
|
export { exportJSONPackage } from './export/json-package';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sendAPIQuery = exports.bumpVersion = exports.cleanupIconKeyword = exports.execAsync = exports.untar = exports.unzip = exports.compareDirectories = exports.scanDirectory = exports.prepareDirectoryForExport = exports.writeJSONFile = exports.exportJSONPackage = exports.exportIconPackage = exports.exportToDirectory = exports.scaleSVG = exports.deOptimisePaths = exports.runSVGO = exports.validateColors = exports.isEmptyColor = exports.parseColors = exports.downloadPackage = exports.getPackageVersion = exports.getNPMVersion = exports.downloadNPMPackage = exports.getGitLabRepoHash = exports.downloadGitLabRepo = exports.getGitHubRepoHash = exports.downloadGitHubRepo = exports.getGitRepoBranch = exports.getGitRepoHash = exports.downloadGitRepo = exports.importDirectory = exports.importFromFigma = exports.mergeIconSets = exports.blankIconSet = exports.IconSet = exports.convertStyleToAttrs = exports.cleanupSVGRoot = exports.cleanupInlineStyle = exports.checkBadTags = exports.removeBadAttributes = exports.cleanupSVG = exports.parseSVGStyle = exports.parseSVG = exports.SVG = void 0;
|
|
3
|
+
exports.sendAPIQuery = exports.bumpVersion = exports.cleanupIconKeyword = exports.execAsync = exports.untar = exports.unzip = exports.compareDirectories = exports.scanDirectory = exports.prepareDirectoryForExport = exports.writeJSONFile = exports.exportJSONPackage = exports.exportIconPackage = exports.exportToDirectory = exports.cleanupGlobalStyle = exports.scaleSVG = exports.deOptimisePaths = exports.runSVGO = exports.validateColors = exports.isEmptyColor = exports.parseColors = exports.downloadPackage = exports.getPackageVersion = exports.getNPMVersion = exports.downloadNPMPackage = exports.getGitLabRepoHash = exports.downloadGitLabRepo = exports.getGitHubRepoHash = exports.downloadGitHubRepo = exports.getGitRepoBranch = exports.getGitRepoHash = exports.downloadGitRepo = exports.importDirectory = exports.importFromFigma = exports.mergeIconSets = exports.blankIconSet = exports.IconSet = exports.convertStyleToAttrs = exports.cleanupSVGRoot = exports.cleanupInlineStyle = exports.checkBadTags = exports.removeBadAttributes = exports.cleanupSVG = exports.analyseSVGStructure = exports.parseSVGStyle = exports.parseSVG = exports.SVG = void 0;
|
|
4
4
|
// SVG class and functions
|
|
5
5
|
var index_1 = require("./svg/index");
|
|
6
6
|
Object.defineProperty(exports, "SVG", { enumerable: true, get: function () { return index_1.SVG; } });
|
|
@@ -8,6 +8,8 @@ var parse_1 = require("./svg/parse");
|
|
|
8
8
|
Object.defineProperty(exports, "parseSVG", { enumerable: true, get: function () { return parse_1.parseSVG; } });
|
|
9
9
|
var parse_style_1 = require("./svg/parse-style");
|
|
10
10
|
Object.defineProperty(exports, "parseSVGStyle", { enumerable: true, get: function () { return parse_style_1.parseSVGStyle; } });
|
|
11
|
+
var analyse_1 = require("./svg/analyse");
|
|
12
|
+
Object.defineProperty(exports, "analyseSVGStructure", { enumerable: true, get: function () { return analyse_1.analyseSVGStructure; } });
|
|
11
13
|
// SVG cleanup
|
|
12
14
|
var cleanup_1 = require("./svg/cleanup");
|
|
13
15
|
Object.defineProperty(exports, "cleanupSVG", { enumerable: true, get: function () { return cleanup_1.cleanupSVG; } });
|
|
@@ -66,6 +68,8 @@ var flags_1 = require("./optimise/flags");
|
|
|
66
68
|
Object.defineProperty(exports, "deOptimisePaths", { enumerable: true, get: function () { return flags_1.deOptimisePaths; } });
|
|
67
69
|
var scale_1 = require("./optimise/scale");
|
|
68
70
|
Object.defineProperty(exports, "scaleSVG", { enumerable: true, get: function () { return scale_1.scaleSVG; } });
|
|
71
|
+
var global_style_1 = require("./optimise/global-style");
|
|
72
|
+
Object.defineProperty(exports, "cleanupGlobalStyle", { enumerable: true, get: function () { return global_style_1.cleanupGlobalStyle; } });
|
|
69
73
|
// Export
|
|
70
74
|
var directory_2 = require("./export/directory");
|
|
71
75
|
Object.defineProperty(exports, "exportToDirectory", { enumerable: true, get: function () { return directory_2.exportToDirectory; } });
|
package/lib/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { SVG } from "./svg/index.mjs";
|
|
3
3
|
import { parseSVG } from "./svg/parse.mjs";
|
|
4
4
|
import { parseSVGStyle } from "./svg/parse-style.mjs";
|
|
5
|
+
import { analyseSVGStructure } from "./svg/analyse.mjs";
|
|
5
6
|
import { cleanupSVG } from "./svg/cleanup.mjs";
|
|
6
7
|
import { removeBadAttributes } from "./svg/cleanup/attribs.mjs";
|
|
7
8
|
import { checkBadTags } from "./svg/cleanup/bad-tags.mjs";
|
|
@@ -27,6 +28,7 @@ import { validateColors } from "./colors/validate.mjs";
|
|
|
27
28
|
import { runSVGO } from "./optimise/svgo.mjs";
|
|
28
29
|
import { deOptimisePaths } from "./optimise/flags.mjs";
|
|
29
30
|
import { scaleSVG } from "./optimise/scale.mjs";
|
|
31
|
+
import { cleanupGlobalStyle } from "./optimise/global-style.mjs";
|
|
30
32
|
import { exportToDirectory } from "./export/directory.mjs";
|
|
31
33
|
import { exportIconPackage } from "./export/icon-package.mjs";
|
|
32
34
|
import { exportJSONPackage } from "./export/json-package.mjs";
|
|
@@ -43,9 +45,11 @@ import { sendAPIQuery } from "./download/api/index.mjs";
|
|
|
43
45
|
export {
|
|
44
46
|
IconSet,
|
|
45
47
|
SVG,
|
|
48
|
+
analyseSVGStructure,
|
|
46
49
|
blankIconSet,
|
|
47
50
|
bumpVersion,
|
|
48
51
|
checkBadTags,
|
|
52
|
+
cleanupGlobalStyle,
|
|
49
53
|
cleanupIconKeyword,
|
|
50
54
|
cleanupInlineStyle,
|
|
51
55
|
cleanupSVG,
|
package/lib/optimise/flags.js
CHANGED
|
@@ -64,6 +64,15 @@ function cleanPath(path) {
|
|
|
64
64
|
});
|
|
65
65
|
currentArgs = [];
|
|
66
66
|
canParseCommandOrComma = true;
|
|
67
|
+
// Change command for lines after moving
|
|
68
|
+
switch (currentCommand) {
|
|
69
|
+
case 'M':
|
|
70
|
+
currentCommand = 'L';
|
|
71
|
+
break;
|
|
72
|
+
case 'm':
|
|
73
|
+
currentCommand = 'l';
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
67
76
|
}
|
|
68
77
|
};
|
|
69
78
|
const parseNumber = () => {
|
package/lib/optimise/flags.mjs
CHANGED
|
@@ -44,6 +44,14 @@ function cleanPath(path) {
|
|
|
44
44
|
});
|
|
45
45
|
currentArgs = [];
|
|
46
46
|
canParseCommandOrComma = true;
|
|
47
|
+
switch (currentCommand) {
|
|
48
|
+
case "M":
|
|
49
|
+
currentCommand = "L";
|
|
50
|
+
break;
|
|
51
|
+
case "m":
|
|
52
|
+
currentCommand = "l";
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
};
|
|
49
57
|
const parseNumber = () => {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanupGlobalStyle = void 0;
|
|
4
|
+
require("../svg/data/attributes");
|
|
5
|
+
const tags_1 = require("../svg/data/tags");
|
|
6
|
+
const parse_1 = require("../svg/parse");
|
|
7
|
+
const parse_style_1 = require("../svg/parse-style");
|
|
8
|
+
function getClassList(value) {
|
|
9
|
+
return value === null || value === void 0 ? void 0 : value.split(/\s+/);
|
|
10
|
+
}
|
|
11
|
+
const tempDataAttrbiute = 'data-gstyle-temp';
|
|
12
|
+
/**
|
|
13
|
+
* Expand global style
|
|
14
|
+
*/
|
|
15
|
+
async function cleanupGlobalStyle(svg) {
|
|
16
|
+
const backup = svg.toString();
|
|
17
|
+
let containsTempAttr = false;
|
|
18
|
+
// Find all animated classes
|
|
19
|
+
const animatedClasses = new Set();
|
|
20
|
+
await (0, parse_1.parseSVG)(svg, (item) => {
|
|
21
|
+
if (!tags_1.animateTags.has(item.tagName)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const $element = item.$element;
|
|
25
|
+
if ($element.attr('attributeName') !== 'class') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
['from', 'to', 'values'].forEach((attr) => {
|
|
29
|
+
const value = $element.attr(attr);
|
|
30
|
+
if (typeof value !== 'string') {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
value.split(';').forEach((item) => {
|
|
34
|
+
getClassList(item).forEach((className) => {
|
|
35
|
+
animatedClasses.add(className);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
// Parse style
|
|
41
|
+
try {
|
|
42
|
+
await (0, parse_style_1.parseSVGStyle)(svg, async (styleItem) => {
|
|
43
|
+
var _a;
|
|
44
|
+
const returnValue = styleItem.value;
|
|
45
|
+
if (styleItem.type !== 'global') {
|
|
46
|
+
return returnValue;
|
|
47
|
+
}
|
|
48
|
+
// Handle only simple selectors
|
|
49
|
+
if (styleItem.selectors.length !== 1 ||
|
|
50
|
+
styleItem.selectorTokens.length !== 1) {
|
|
51
|
+
return returnValue;
|
|
52
|
+
}
|
|
53
|
+
// Do not handle media queries
|
|
54
|
+
const selectorToken = styleItem.selectorTokens[0];
|
|
55
|
+
if (selectorToken.type !== 'selector') {
|
|
56
|
+
return returnValue;
|
|
57
|
+
}
|
|
58
|
+
// Simple selector and simple rule
|
|
59
|
+
const selector = styleItem.selectors[0];
|
|
60
|
+
const firstChar = selector.charAt(0);
|
|
61
|
+
let matchType;
|
|
62
|
+
if (firstChar === '.') {
|
|
63
|
+
matchType = 'class';
|
|
64
|
+
}
|
|
65
|
+
else if (firstChar === '#') {
|
|
66
|
+
matchType = 'id';
|
|
67
|
+
}
|
|
68
|
+
else if (tags_1.allValidTags.has(selector)) {
|
|
69
|
+
matchType = 'tag';
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return returnValue;
|
|
73
|
+
}
|
|
74
|
+
const valueMatch = matchType === 'tag' ? selector : selector.slice(1);
|
|
75
|
+
if (matchType === 'class' && animatedClasses.has(valueMatch)) {
|
|
76
|
+
// Class name is used in animations
|
|
77
|
+
return returnValue;
|
|
78
|
+
}
|
|
79
|
+
// Check if element is a match
|
|
80
|
+
const isMatch = (tagName, $element) => {
|
|
81
|
+
switch (matchType) {
|
|
82
|
+
case 'id':
|
|
83
|
+
return $element.attr('id') === valueMatch;
|
|
84
|
+
case 'tag':
|
|
85
|
+
return tagName === valueMatch;
|
|
86
|
+
case 'class': {
|
|
87
|
+
const className = $element.attr('class');
|
|
88
|
+
if (!className ||
|
|
89
|
+
getClassList(className).indexOf(valueMatch) === -1) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
};
|
|
96
|
+
// Parse all elements
|
|
97
|
+
await (0, parse_1.parseSVG)(svg, (svgItem) => {
|
|
98
|
+
var _a;
|
|
99
|
+
const tagName = svgItem.tagName;
|
|
100
|
+
const $element = svgItem.$element;
|
|
101
|
+
if (!isMatch(tagName, $element)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Transfer attribute
|
|
105
|
+
const addedAttributes = new Set((_a = $element.attr(tempDataAttrbiute)) === null || _a === void 0 ? void 0 : _a.split(/\s+/));
|
|
106
|
+
const prop = styleItem.prop;
|
|
107
|
+
if ($element.attr(prop) !== void 0) {
|
|
108
|
+
// Previously added attribute?
|
|
109
|
+
if (addedAttributes.has(prop)) {
|
|
110
|
+
// Two CSS rules are applied to same element: abort parsing and restore content from backup.
|
|
111
|
+
// This parse is very basic, it does not account for specificity.
|
|
112
|
+
throw new Error('Duplicate attribute');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
$element.attr(prop, styleItem.value);
|
|
116
|
+
addedAttributes.add(prop);
|
|
117
|
+
$element.attr(tempDataAttrbiute, Array.from(addedAttributes).join(' '));
|
|
118
|
+
containsTempAttr = true;
|
|
119
|
+
});
|
|
120
|
+
// Remove class attribute
|
|
121
|
+
if (matchType === 'class' &&
|
|
122
|
+
((_a = styleItem.nextTokens[0]) === null || _a === void 0 ? void 0 : _a.type) === 'close') {
|
|
123
|
+
// Can remove class
|
|
124
|
+
await (0, parse_1.parseSVG)(svg, (svgItem) => {
|
|
125
|
+
const $element = svgItem.$element;
|
|
126
|
+
if (!isMatch('', $element)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Remove class
|
|
130
|
+
const classList = getClassList($element.attr('class'));
|
|
131
|
+
if (!classList) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const filtered = classList.filter((item) => item !== valueMatch);
|
|
135
|
+
if (!filtered.length) {
|
|
136
|
+
$element.removeAttr('class');
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
$element.attr('class', filtered.join(' '));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Remove rule
|
|
144
|
+
return;
|
|
145
|
+
});
|
|
146
|
+
// Remove temporary attributes
|
|
147
|
+
if (containsTempAttr) {
|
|
148
|
+
await (0, parse_1.parseSVG)(svg, (item) => {
|
|
149
|
+
item.$element.removeAttr(tempDataAttrbiute);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
// Failed: restore from backup
|
|
155
|
+
svg.load(backup);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.cleanupGlobalStyle = cleanupGlobalStyle;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/optimise/global-style.ts
|
|
2
|
+
import "../svg/data/attributes.mjs";
|
|
3
|
+
import { allValidTags, animateTags } from "../svg/data/tags.mjs";
|
|
4
|
+
import { parseSVG } from "../svg/parse.mjs";
|
|
5
|
+
import { parseSVGStyle } from "../svg/parse-style.mjs";
|
|
6
|
+
function getClassList(value) {
|
|
7
|
+
return value == null ? void 0 : value.split(/\s+/);
|
|
8
|
+
}
|
|
9
|
+
var tempDataAttrbiute = "data-gstyle-temp";
|
|
10
|
+
async function cleanupGlobalStyle(svg) {
|
|
11
|
+
const backup = svg.toString();
|
|
12
|
+
let containsTempAttr = false;
|
|
13
|
+
const animatedClasses = new Set();
|
|
14
|
+
await parseSVG(svg, (item) => {
|
|
15
|
+
if (!animateTags.has(item.tagName)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const $element = item.$element;
|
|
19
|
+
if ($element.attr("attributeName") !== "class") {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
["from", "to", "values"].forEach((attr) => {
|
|
23
|
+
const value = $element.attr(attr);
|
|
24
|
+
if (typeof value !== "string") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
value.split(";").forEach((item2) => {
|
|
28
|
+
getClassList(item2).forEach((className) => {
|
|
29
|
+
animatedClasses.add(className);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
try {
|
|
35
|
+
await parseSVGStyle(svg, async (styleItem) => {
|
|
36
|
+
var _a;
|
|
37
|
+
const returnValue = styleItem.value;
|
|
38
|
+
if (styleItem.type !== "global") {
|
|
39
|
+
return returnValue;
|
|
40
|
+
}
|
|
41
|
+
if (styleItem.selectors.length !== 1 || styleItem.selectorTokens.length !== 1) {
|
|
42
|
+
return returnValue;
|
|
43
|
+
}
|
|
44
|
+
const selectorToken = styleItem.selectorTokens[0];
|
|
45
|
+
if (selectorToken.type !== "selector") {
|
|
46
|
+
return returnValue;
|
|
47
|
+
}
|
|
48
|
+
const selector = styleItem.selectors[0];
|
|
49
|
+
const firstChar = selector.charAt(0);
|
|
50
|
+
let matchType;
|
|
51
|
+
if (firstChar === ".") {
|
|
52
|
+
matchType = "class";
|
|
53
|
+
} else if (firstChar === "#") {
|
|
54
|
+
matchType = "id";
|
|
55
|
+
} else if (allValidTags.has(selector)) {
|
|
56
|
+
matchType = "tag";
|
|
57
|
+
} else {
|
|
58
|
+
return returnValue;
|
|
59
|
+
}
|
|
60
|
+
const valueMatch = matchType === "tag" ? selector : selector.slice(1);
|
|
61
|
+
if (matchType === "class" && animatedClasses.has(valueMatch)) {
|
|
62
|
+
return returnValue;
|
|
63
|
+
}
|
|
64
|
+
const isMatch = (tagName, $element) => {
|
|
65
|
+
switch (matchType) {
|
|
66
|
+
case "id":
|
|
67
|
+
return $element.attr("id") === valueMatch;
|
|
68
|
+
case "tag":
|
|
69
|
+
return tagName === valueMatch;
|
|
70
|
+
case "class": {
|
|
71
|
+
const className = $element.attr("class");
|
|
72
|
+
if (!className || getClassList(className).indexOf(valueMatch) === -1) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
};
|
|
79
|
+
await parseSVG(svg, (svgItem) => {
|
|
80
|
+
var _a2;
|
|
81
|
+
const tagName = svgItem.tagName;
|
|
82
|
+
const $element = svgItem.$element;
|
|
83
|
+
if (!isMatch(tagName, $element)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const addedAttributes = new Set((_a2 = $element.attr(tempDataAttrbiute)) == null ? void 0 : _a2.split(/\s+/));
|
|
87
|
+
const prop = styleItem.prop;
|
|
88
|
+
if ($element.attr(prop) !== void 0) {
|
|
89
|
+
if (addedAttributes.has(prop)) {
|
|
90
|
+
throw new Error("Duplicate attribute");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
$element.attr(prop, styleItem.value);
|
|
94
|
+
addedAttributes.add(prop);
|
|
95
|
+
$element.attr(tempDataAttrbiute, Array.from(addedAttributes).join(" "));
|
|
96
|
+
containsTempAttr = true;
|
|
97
|
+
});
|
|
98
|
+
if (matchType === "class" && ((_a = styleItem.nextTokens[0]) == null ? void 0 : _a.type) === "close") {
|
|
99
|
+
await parseSVG(svg, (svgItem) => {
|
|
100
|
+
const $element = svgItem.$element;
|
|
101
|
+
if (!isMatch("", $element)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const classList = getClassList($element.attr("class"));
|
|
105
|
+
if (!classList) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const filtered = classList.filter((item) => item !== valueMatch);
|
|
109
|
+
if (!filtered.length) {
|
|
110
|
+
$element.removeAttr("class");
|
|
111
|
+
} else {
|
|
112
|
+
$element.attr("class", filtered.join(" "));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
});
|
|
118
|
+
if (containsTempAttr) {
|
|
119
|
+
await parseSVG(svg, (item) => {
|
|
120
|
+
item.$element.removeAttr(tempDataAttrbiute);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
svg.load(backup);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
cleanupGlobalStyle
|
|
129
|
+
};
|
package/lib/optimise/svgo.js
CHANGED
package/lib/optimise/svgo.mjs
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyseTagError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Get tag for error message
|
|
6
|
+
*/
|
|
7
|
+
function analyseTagError(element) {
|
|
8
|
+
let result = '<' + element.tagName;
|
|
9
|
+
if (element._id) {
|
|
10
|
+
result += ' id="' + element._id + '"';
|
|
11
|
+
}
|
|
12
|
+
const attribs = element.attribs;
|
|
13
|
+
if (attribs['d']) {
|
|
14
|
+
const value = attribs['d'];
|
|
15
|
+
result +=
|
|
16
|
+
' d="' +
|
|
17
|
+
(value.length > 16 ? value.slice(0, 12) + '...' : value) +
|
|
18
|
+
'"';
|
|
19
|
+
}
|
|
20
|
+
return result + '>';
|
|
21
|
+
}
|
|
22
|
+
exports.analyseTagError = analyseTagError;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/svg/analyse/error.ts
|
|
2
|
+
function analyseTagError(element) {
|
|
3
|
+
let result = "<" + element.tagName;
|
|
4
|
+
if (element._id) {
|
|
5
|
+
result += ' id="' + element._id + '"';
|
|
6
|
+
}
|
|
7
|
+
const attribs = element.attribs;
|
|
8
|
+
if (attribs["d"]) {
|
|
9
|
+
const value = attribs["d"];
|
|
10
|
+
result += ' d="' + (value.length > 16 ? value.slice(0, 12) + "..." : value) + '"';
|
|
11
|
+
}
|
|
12
|
+
return result + ">";
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
analyseTagError
|
|
16
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/// <reference types="cheerio" />
|
|
2
|
+
/**
|
|
3
|
+
* Options
|
|
4
|
+
*/
|
|
5
|
+
export interface AnalyseSVGStructureOptions {
|
|
6
|
+
fixErrors?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Extended properties for element
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Link to element
|
|
13
|
+
*/
|
|
14
|
+
export interface LinkToElementWithID {
|
|
15
|
+
id: string;
|
|
16
|
+
usedAsMask: boolean;
|
|
17
|
+
usedByIndex: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* How element is used by parent elements
|
|
21
|
+
*/
|
|
22
|
+
export interface ExtendedTagElementUses {
|
|
23
|
+
_usedAsMask: boolean;
|
|
24
|
+
_usedAsPaint: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Definition: mask, clip path, symbol, etc...
|
|
28
|
+
*/
|
|
29
|
+
interface ReusableElement {
|
|
30
|
+
id: string;
|
|
31
|
+
isMask: boolean;
|
|
32
|
+
index: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Element with id
|
|
36
|
+
*
|
|
37
|
+
* Similar to ReusableElement, but not necessary a definition - any element with id. Also contains list of child elements
|
|
38
|
+
*/
|
|
39
|
+
export interface ElementWithID {
|
|
40
|
+
id: string;
|
|
41
|
+
isMask: boolean;
|
|
42
|
+
indexes: Set<number>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parent and child elements. Unlike standard tree, this tree is for elements that inherit attributes from parent element
|
|
46
|
+
*/
|
|
47
|
+
interface ExtendedTagElementRelations {
|
|
48
|
+
_parentElement?: number;
|
|
49
|
+
_childElements?: number[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Extended tag
|
|
53
|
+
*/
|
|
54
|
+
export interface ExtendedTagElement extends cheerio.TagElement, ExtendedTagElementUses, ExtendedTagElementRelations {
|
|
55
|
+
_index: number;
|
|
56
|
+
_id?: string;
|
|
57
|
+
_belongsTo?: ElementWithID[];
|
|
58
|
+
_reusableElement?: ReusableElement;
|
|
59
|
+
_linksTo?: LinkToElementWithID[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Additional stuff for <svg>
|
|
63
|
+
*/
|
|
64
|
+
export interface ExtendedRootTagElement extends ExtendedTagElement {
|
|
65
|
+
_parsed?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Tree
|
|
69
|
+
*/
|
|
70
|
+
export interface ElementsTreeItem {
|
|
71
|
+
index: number;
|
|
72
|
+
usedAsMask: boolean;
|
|
73
|
+
parent?: ElementsTreeItem;
|
|
74
|
+
children: ElementsTreeItem[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Elements map
|
|
78
|
+
*/
|
|
79
|
+
export declare type ElementsMap = Map<number, ExtendedTagElement>;
|
|
80
|
+
/**
|
|
81
|
+
* Result
|
|
82
|
+
*/
|
|
83
|
+
export interface AnalyseSVGStructureResult {
|
|
84
|
+
elements: ElementsMap;
|
|
85
|
+
ids: Record<string, number>;
|
|
86
|
+
links: LinkToElementWithID[];
|
|
87
|
+
tree: ElementsTreeItem;
|
|
88
|
+
}
|
|
89
|
+
export {};
|
|
File without changes
|