@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.
- package/.editorconfig +13 -0
- package/.eslintignore +2 -0
- package/lib/colors/attribs.d.ts +16 -0
- package/lib/colors/attribs.js +26 -0
- package/lib/colors/attribs.mjs +28 -0
- package/lib/colors/parse.d.ts +37 -0
- package/lib/colors/parse.js +261 -0
- package/lib/colors/parse.mjs +212 -0
- package/lib/css/parse.d.ts +4 -0
- package/lib/css/parse.js +23 -0
- package/lib/css/parse.mjs +20 -0
- package/lib/css/parser/error.d.ts +11 -0
- package/lib/css/parser/error.js +27 -0
- package/lib/css/parser/error.mjs +23 -0
- package/lib/css/parser/export.d.ts +5 -0
- package/lib/css/parser/export.js +69 -0
- package/lib/css/parser/export.mjs +46 -0
- package/lib/css/parser/strings.d.ts +13 -0
- package/lib/css/parser/strings.js +93 -0
- package/lib/css/parser/strings.mjs +74 -0
- package/lib/css/parser/text.d.ts +17 -0
- package/lib/css/parser/text.js +174 -0
- package/lib/css/parser/text.mjs +133 -0
- package/lib/css/parser/tokens.d.ts +6 -0
- package/lib/css/parser/tokens.js +200 -0
- package/lib/css/parser/tokens.mjs +186 -0
- package/lib/css/parser/tree.d.ts +5 -0
- package/lib/css/parser/tree.js +44 -0
- package/lib/css/parser/tree.mjs +40 -0
- package/lib/css/parser/types.d.ts +51 -0
- package/lib/css/parser/types.js +2 -0
- package/lib/css/parser/types.mjs +0 -0
- package/lib/icon-set/index.d.ts +134 -0
- package/lib/icon-set/index.js +776 -0
- package/lib/icon-set/index.mjs +617 -0
- package/lib/icon-set/match.d.ts +6 -0
- package/lib/icon-set/match.js +66 -0
- package/lib/icon-set/match.mjs +55 -0
- package/lib/icon-set/merge.d.ts +5 -0
- package/lib/icon-set/merge.js +91 -0
- package/lib/icon-set/merge.mjs +75 -0
- package/lib/icon-set/props.d.ts +10 -0
- package/lib/icon-set/props.js +33 -0
- package/lib/icon-set/props.mjs +25 -0
- package/lib/icon-set/types.d.ts +68 -0
- package/lib/icon-set/types.js +2 -0
- package/lib/icon-set/types.mjs +0 -0
- package/lib/import/directory.d.ts +35 -0
- package/lib/import/directory.js +59 -0
- package/lib/import/directory.mjs +47 -0
- package/lib/misc/keyword.d.ts +4 -0
- package/lib/misc/keyword.js +31 -0
- package/lib/misc/keyword.mjs +17 -0
- package/lib/misc/scan.d.ts +24 -0
- package/lib/misc/scan.js +48 -0
- package/lib/misc/scan.mjs +43 -0
- package/lib/optimise/flags.d.ts +5 -0
- package/lib/optimise/flags.js +303 -0
- package/lib/optimise/flags.mjs +241 -0
- package/lib/optimise/scale.d.ts +5 -0
- package/lib/optimise/scale.js +42 -0
- package/lib/optimise/scale.mjs +22 -0
- package/lib/optimise/svgo.d.ts +27 -0
- package/lib/optimise/svgo.js +88 -0
- package/lib/optimise/svgo.mjs +75 -0
- package/lib/svg/cleanup/attribs.d.ts +5 -0
- package/lib/svg/cleanup/attribs.js +43 -0
- package/lib/svg/cleanup/attribs.mjs +36 -0
- package/lib/svg/cleanup/bad-tags.d.ts +5 -0
- package/lib/svg/cleanup/bad-tags.js +69 -0
- package/lib/svg/cleanup/bad-tags.mjs +68 -0
- package/lib/svg/cleanup/inline-style.d.ts +5 -0
- package/lib/svg/cleanup/inline-style.js +77 -0
- package/lib/svg/cleanup/inline-style.mjs +65 -0
- package/lib/svg/cleanup/root-svg.d.ts +5 -0
- package/lib/svg/cleanup/root-svg.js +106 -0
- package/lib/svg/cleanup/root-svg.mjs +88 -0
- package/lib/svg/cleanup/svgo-style.d.ts +5 -0
- package/lib/svg/cleanup/svgo-style.js +35 -0
- package/lib/svg/cleanup/svgo-style.mjs +29 -0
- package/lib/svg/cleanup.d.ts +5 -0
- package/lib/svg/cleanup.js +24 -0
- package/lib/svg/cleanup.mjs +16 -0
- package/lib/svg/data/attributes.d.ts +71 -0
- package/lib/svg/data/attributes.js +403 -0
- package/lib/svg/data/attributes.mjs +352 -0
- package/lib/svg/data/tags.d.ts +89 -0
- package/lib/svg/data/tags.js +185 -0
- package/lib/svg/data/tags.mjs +136 -0
- package/lib/svg/index.d.ts +33 -0
- package/lib/svg/index.js +122 -0
- package/lib/svg/index.mjs +85 -0
- package/lib/svg/parse-style.d.ts +40 -0
- package/lib/svg/parse-style.js +131 -0
- package/lib/svg/parse-style.mjs +109 -0
- package/lib/svg/parse.d.ts +30 -0
- package/lib/svg/parse.js +49 -0
- package/lib/svg/parse.mjs +40 -0
- package/package.json +167 -13
- package/README.md +0 -576
- package/license.txt +0 -21
- package/sample/parse.js +0 -74
- package/sample/source/icon-close.svg +0 -15
- package/sample/source/icon-confirm.svg +0 -14
- package/sample/source/icon-search.svg +0 -16
- package/src/collection.js +0 -641
- package/src/colors/change_palette.js +0 -227
- package/src/colors/get_palette.js +0 -143
- package/src/colors/opacify.js +0 -195
- package/src/export/component.js +0 -482
- package/src/export/dir.js +0 -109
- package/src/export/json.js +0 -329
- package/src/export/phantomjs.js +0 -76
- package/src/export/phantomjs_script.js +0 -125
- package/src/export/png.js +0 -193
- package/src/export/svg.js +0 -55
- package/src/export/templates/component.md +0 -79
- package/src/export/templates/info.md +0 -3
- package/src/export/templates/sample-react-1.md +0 -21
- package/src/export/templates/sample-react-2.md +0 -15
- package/src/export/templates/sample-react.md +0 -11
- package/src/export/templates/sample-svelte.md +0 -11
- package/src/export/templates/sample-svelte1.md +0 -22
- package/src/export/templates/sample-svelte2.md +0 -13
- package/src/export/templates/sample-vue-0.md +0 -30
- package/src/export/templates/sample-vue-1.md +0 -25
- package/src/export/templates/sample-vue-2.md +0 -27
- package/src/export/templates/sample-vue.md +0 -28
- package/src/helpers.js +0 -43
- package/src/import/dir.js +0 -234
- package/src/import/font.js +0 -402
- package/src/import/json.js +0 -200
- package/src/import/svg.js +0 -60
- package/src/import/web_icons.js +0 -248
- package/src/modules.js +0 -50
- package/src/optimize/crop.js +0 -554
- package/src/optimize/crop_script.js +0 -525
- package/src/optimize/flags.js +0 -430
- package/src/optimize/scale.js +0 -72
- package/src/optimize/svgo.js +0 -161
- package/src/optimize/tags.js +0 -522
- package/src/shapes/convert.js +0 -264
- package/src/shapes/index.js +0 -135
- package/src/shapes/length.js +0 -707
- package/src/shapes/length_script.js +0 -105
- package/src/shapes/options.js +0 -60
- package/src/svg.js +0 -162
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runSVGO = exports.shapeModifiyingSVGOPlugins = exports.defaultSVGOPlugins = void 0;
|
|
4
|
+
const svgo_1 = require("svgo");
|
|
5
|
+
exports.defaultSVGOPlugins = [
|
|
6
|
+
'cleanupAttrs',
|
|
7
|
+
'mergeStyles',
|
|
8
|
+
'inlineStyles',
|
|
9
|
+
'removeComments',
|
|
10
|
+
'removeUselessDefs',
|
|
11
|
+
'removeEditorsNSData',
|
|
12
|
+
'removeEmptyAttrs',
|
|
13
|
+
'removeEmptyContainers',
|
|
14
|
+
'convertStyleToAttrs',
|
|
15
|
+
'convertColors',
|
|
16
|
+
'convertTransform',
|
|
17
|
+
'removeUnknownsAndDefaults',
|
|
18
|
+
'removeNonInheritableGroupAttrs',
|
|
19
|
+
'removeUselessStrokeAndFill',
|
|
20
|
+
'removeUnusedNS',
|
|
21
|
+
'cleanupNumericValues',
|
|
22
|
+
'cleanupListOfValues',
|
|
23
|
+
'moveElemsAttrsToGroup',
|
|
24
|
+
'moveGroupAttrsToElems',
|
|
25
|
+
'collapseGroups',
|
|
26
|
+
'sortDefsChildren',
|
|
27
|
+
'sortAttrs',
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Plugins that modify shapes. Added to plugins list, unless 'keepShapes' option is enabled
|
|
31
|
+
*/
|
|
32
|
+
exports.shapeModifiyingSVGOPlugins = [
|
|
33
|
+
'removeHiddenElems',
|
|
34
|
+
'convertShapeToPath',
|
|
35
|
+
'convertEllipseToCircle',
|
|
36
|
+
{
|
|
37
|
+
name: 'convertPathData',
|
|
38
|
+
params: {
|
|
39
|
+
noSpaceAfterFlags: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'mergePaths',
|
|
44
|
+
params: {
|
|
45
|
+
noSpaceAfterFlags: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
'removeOffCanvasPaths',
|
|
49
|
+
'reusePaths',
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Run SVGO on icon
|
|
53
|
+
*/
|
|
54
|
+
async function runSVGO(svg, options = {}) {
|
|
55
|
+
// Options
|
|
56
|
+
const multipass = options.multipass !== false;
|
|
57
|
+
// Plugins list
|
|
58
|
+
let plugins;
|
|
59
|
+
if (options.plugins) {
|
|
60
|
+
plugins = options.plugins;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
plugins = exports.defaultSVGOPlugins.concat(options.keepShapes ? [] : exports.shapeModifiyingSVGOPlugins, options.cleanupIDs !== false
|
|
64
|
+
? [
|
|
65
|
+
{
|
|
66
|
+
name: 'cleanupIDs',
|
|
67
|
+
params: {
|
|
68
|
+
prefix: typeof options.cleanupIDs === 'string'
|
|
69
|
+
? options.cleanupIDs
|
|
70
|
+
: 'svg-',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
: []);
|
|
75
|
+
}
|
|
76
|
+
// Run SVGO
|
|
77
|
+
const pluginOptions = {
|
|
78
|
+
plugins,
|
|
79
|
+
multipass,
|
|
80
|
+
};
|
|
81
|
+
// Load data (changing type because SVGO types do not include error ?????)
|
|
82
|
+
const result = (0, svgo_1.optimize)(svg.toString(), pluginOptions);
|
|
83
|
+
if (typeof result.error === 'string') {
|
|
84
|
+
throw new Error(result.error);
|
|
85
|
+
}
|
|
86
|
+
svg.load(result.data);
|
|
87
|
+
}
|
|
88
|
+
exports.runSVGO = runSVGO;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/optimise/svgo.ts
|
|
2
|
+
import { optimize } from "svgo";
|
|
3
|
+
var defaultSVGOPlugins = [
|
|
4
|
+
"cleanupAttrs",
|
|
5
|
+
"mergeStyles",
|
|
6
|
+
"inlineStyles",
|
|
7
|
+
"removeComments",
|
|
8
|
+
"removeUselessDefs",
|
|
9
|
+
"removeEditorsNSData",
|
|
10
|
+
"removeEmptyAttrs",
|
|
11
|
+
"removeEmptyContainers",
|
|
12
|
+
"convertStyleToAttrs",
|
|
13
|
+
"convertColors",
|
|
14
|
+
"convertTransform",
|
|
15
|
+
"removeUnknownsAndDefaults",
|
|
16
|
+
"removeNonInheritableGroupAttrs",
|
|
17
|
+
"removeUselessStrokeAndFill",
|
|
18
|
+
"removeUnusedNS",
|
|
19
|
+
"cleanupNumericValues",
|
|
20
|
+
"cleanupListOfValues",
|
|
21
|
+
"moveElemsAttrsToGroup",
|
|
22
|
+
"moveGroupAttrsToElems",
|
|
23
|
+
"collapseGroups",
|
|
24
|
+
"sortDefsChildren",
|
|
25
|
+
"sortAttrs"
|
|
26
|
+
];
|
|
27
|
+
var shapeModifiyingSVGOPlugins = [
|
|
28
|
+
"removeHiddenElems",
|
|
29
|
+
"convertShapeToPath",
|
|
30
|
+
"convertEllipseToCircle",
|
|
31
|
+
{
|
|
32
|
+
name: "convertPathData",
|
|
33
|
+
params: {
|
|
34
|
+
noSpaceAfterFlags: true
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "mergePaths",
|
|
39
|
+
params: {
|
|
40
|
+
noSpaceAfterFlags: true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"removeOffCanvasPaths",
|
|
44
|
+
"reusePaths"
|
|
45
|
+
];
|
|
46
|
+
async function runSVGO(svg, options = {}) {
|
|
47
|
+
const multipass = options.multipass !== false;
|
|
48
|
+
let plugins;
|
|
49
|
+
if (options.plugins) {
|
|
50
|
+
plugins = options.plugins;
|
|
51
|
+
} else {
|
|
52
|
+
plugins = defaultSVGOPlugins.concat(options.keepShapes ? [] : shapeModifiyingSVGOPlugins, options.cleanupIDs !== false ? [
|
|
53
|
+
{
|
|
54
|
+
name: "cleanupIDs",
|
|
55
|
+
params: {
|
|
56
|
+
prefix: typeof options.cleanupIDs === "string" ? options.cleanupIDs : "svg-"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
] : []);
|
|
60
|
+
}
|
|
61
|
+
const pluginOptions = {
|
|
62
|
+
plugins,
|
|
63
|
+
multipass
|
|
64
|
+
};
|
|
65
|
+
const result = optimize(svg.toString(), pluginOptions);
|
|
66
|
+
if (typeof result.error === "string") {
|
|
67
|
+
throw new Error(result.error);
|
|
68
|
+
}
|
|
69
|
+
svg.load(result.data);
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
defaultSVGOPlugins,
|
|
73
|
+
runSVGO,
|
|
74
|
+
shapeModifiyingSVGOPlugins
|
|
75
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeBadAttributes = void 0;
|
|
4
|
+
const attributes_1 = require("../data/attributes");
|
|
5
|
+
const parse_1 = require("../parse");
|
|
6
|
+
/**
|
|
7
|
+
* Remove useless attributes
|
|
8
|
+
*/
|
|
9
|
+
async function removeBadAttributes(svg) {
|
|
10
|
+
await (0, parse_1.parseSVG)(svg, (item) => {
|
|
11
|
+
const attribs = item.element.attribs;
|
|
12
|
+
const $element = item.$element;
|
|
13
|
+
// Common tags
|
|
14
|
+
Object.keys(attribs).forEach((attr) => {
|
|
15
|
+
// Bad attributes, events
|
|
16
|
+
if (attr.slice(0, 2) === 'on' ||
|
|
17
|
+
attributes_1.badAttributes.has(attr) ||
|
|
18
|
+
attributes_1.badSoftwareAttributes.has(attr) ||
|
|
19
|
+
attributes_1.badAttributePrefixes.has(attr.split('-').shift())) {
|
|
20
|
+
$element.removeAttr(attr);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Check for namespace
|
|
24
|
+
const nsParts = attr.split(':');
|
|
25
|
+
if (nsParts.length > 1) {
|
|
26
|
+
const namespace = nsParts.shift();
|
|
27
|
+
const newAttr = nsParts.join(':');
|
|
28
|
+
switch (namespace) {
|
|
29
|
+
case 'xlink': {
|
|
30
|
+
// Deprecated: use without namespace
|
|
31
|
+
if (attribs[newAttr] === void 0) {
|
|
32
|
+
$element.attr(newAttr, attribs[attr]);
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Remove all namespace attributes
|
|
38
|
+
$element.removeAttr(attr);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
exports.removeBadAttributes = removeBadAttributes;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/svg/cleanup/attribs.ts
|
|
2
|
+
import {
|
|
3
|
+
badAttributes,
|
|
4
|
+
badAttributePrefixes,
|
|
5
|
+
badSoftwareAttributes
|
|
6
|
+
} from "../data/attributes.mjs";
|
|
7
|
+
import { parseSVG } from "../parse.mjs";
|
|
8
|
+
async function removeBadAttributes(svg) {
|
|
9
|
+
await parseSVG(svg, (item) => {
|
|
10
|
+
const attribs = item.element.attribs;
|
|
11
|
+
const $element = item.$element;
|
|
12
|
+
Object.keys(attribs).forEach((attr) => {
|
|
13
|
+
if (attr.slice(0, 2) === "on" || badAttributes.has(attr) || badSoftwareAttributes.has(attr) || badAttributePrefixes.has(attr.split("-").shift())) {
|
|
14
|
+
$element.removeAttr(attr);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const nsParts = attr.split(":");
|
|
18
|
+
if (nsParts.length > 1) {
|
|
19
|
+
const namespace = nsParts.shift();
|
|
20
|
+
const newAttr = nsParts.join(":");
|
|
21
|
+
switch (namespace) {
|
|
22
|
+
case "xlink": {
|
|
23
|
+
if (attribs[newAttr] === void 0) {
|
|
24
|
+
$element.attr(newAttr, attribs[attr]);
|
|
25
|
+
}
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
$element.removeAttr(attr);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
removeBadAttributes
|
|
36
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkBadTags = void 0;
|
|
4
|
+
const parse_1 = require("../parse");
|
|
5
|
+
const tags_1 = require("../data/tags");
|
|
6
|
+
// List of required parent tags
|
|
7
|
+
const requiredParentTags = new Map();
|
|
8
|
+
// <feFunc*> must be children of <feComponentTransfer>
|
|
9
|
+
requiredParentTags.set(new Set(['feComponentTransfer']), tags_1.feComponentTransferChildTag);
|
|
10
|
+
// <feMergeNode> must be children of <feMerge>
|
|
11
|
+
requiredParentTags.set(new Set(['feMerge']), tags_1.feMergeChildTags);
|
|
12
|
+
// Children of <fe*Lightning>
|
|
13
|
+
requiredParentTags.set(tags_1.feLightningTags, tags_1.feLightningChildTags);
|
|
14
|
+
// Filter tags must be children of <filter>
|
|
15
|
+
requiredParentTags.set(tags_1.filterTag, tags_1.filterChildTags);
|
|
16
|
+
// Tags that must be inside <defs>: gradients, <pattern>, <marker>
|
|
17
|
+
requiredParentTags.set(tags_1.defsTag, tags_1.tagsInsideDefs);
|
|
18
|
+
// <stop> must be inside gradient
|
|
19
|
+
requiredParentTags.set(tags_1.gradientTags, tags_1.gradientChildTags);
|
|
20
|
+
// Animations must be inside shapes or filters
|
|
21
|
+
requiredParentTags.set(tags_1.tagsBeforeAnimation, tags_1.animateTags);
|
|
22
|
+
// <mpath> must be inside <animateMotion>
|
|
23
|
+
requiredParentTags.set(new Set(['animateMotion']), tags_1.animateMotionChildTags);
|
|
24
|
+
/**
|
|
25
|
+
* Test for bag tags
|
|
26
|
+
*/
|
|
27
|
+
async function checkBadTags(svg) {
|
|
28
|
+
await (0, parse_1.parseSVG)(svg, (item) => {
|
|
29
|
+
var _a;
|
|
30
|
+
const tagName = item.tagName;
|
|
31
|
+
const $element = item.$element;
|
|
32
|
+
// SVG as root
|
|
33
|
+
if (tagName === 'svg') {
|
|
34
|
+
if (item.parents.length) {
|
|
35
|
+
// Technically code is correct, but it badly complicates parsing, so not supported
|
|
36
|
+
throw new Error(`Unexpected element: <${tagName}>`);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Unsupported: quietly remove it
|
|
41
|
+
if (tags_1.unsupportedTags.has(tagName)) {
|
|
42
|
+
$element.remove();
|
|
43
|
+
item.testChildren = false;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Bad or unknown element
|
|
47
|
+
if (tags_1.badTags.has(tagName) || !tags_1.allValidTags.has(tagName)) {
|
|
48
|
+
const parts = tagName.split(':');
|
|
49
|
+
if (parts.length > 1) {
|
|
50
|
+
// Custom tag, most likely Inkscape junk
|
|
51
|
+
$element.remove();
|
|
52
|
+
item.testChildren = false;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`Unexpected element: <${tagName}>`);
|
|
56
|
+
}
|
|
57
|
+
// Check for valid parent tag
|
|
58
|
+
const parentTagName = (_a = item.parents[0]) === null || _a === void 0 ? void 0 : _a.tagName;
|
|
59
|
+
for (const [parents, children] of requiredParentTags) {
|
|
60
|
+
if (children.has(tagName)) {
|
|
61
|
+
if (!parents.has(parentTagName)) {
|
|
62
|
+
throw new Error(`Element <${tagName}> has wrong parent element`);
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
exports.checkBadTags = checkBadTags;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/svg/cleanup/bad-tags.ts
|
|
2
|
+
import { parseSVG } from "../parse.mjs";
|
|
3
|
+
import {
|
|
4
|
+
allValidTags,
|
|
5
|
+
animateMotionChildTags,
|
|
6
|
+
animateTags,
|
|
7
|
+
badTags,
|
|
8
|
+
defsTag,
|
|
9
|
+
feComponentTransferChildTag,
|
|
10
|
+
feLightningChildTags,
|
|
11
|
+
feLightningTags,
|
|
12
|
+
feMergeChildTags,
|
|
13
|
+
filterChildTags,
|
|
14
|
+
filterTag,
|
|
15
|
+
gradientChildTags,
|
|
16
|
+
gradientTags,
|
|
17
|
+
tagsBeforeAnimation,
|
|
18
|
+
tagsInsideDefs,
|
|
19
|
+
unsupportedTags
|
|
20
|
+
} from "../data/tags.mjs";
|
|
21
|
+
var requiredParentTags = new Map();
|
|
22
|
+
requiredParentTags.set(new Set(["feComponentTransfer"]), feComponentTransferChildTag);
|
|
23
|
+
requiredParentTags.set(new Set(["feMerge"]), feMergeChildTags);
|
|
24
|
+
requiredParentTags.set(feLightningTags, feLightningChildTags);
|
|
25
|
+
requiredParentTags.set(filterTag, filterChildTags);
|
|
26
|
+
requiredParentTags.set(defsTag, tagsInsideDefs);
|
|
27
|
+
requiredParentTags.set(gradientTags, gradientChildTags);
|
|
28
|
+
requiredParentTags.set(tagsBeforeAnimation, animateTags);
|
|
29
|
+
requiredParentTags.set(new Set(["animateMotion"]), animateMotionChildTags);
|
|
30
|
+
async function checkBadTags(svg) {
|
|
31
|
+
await parseSVG(svg, (item) => {
|
|
32
|
+
var _a;
|
|
33
|
+
const tagName = item.tagName;
|
|
34
|
+
const $element = item.$element;
|
|
35
|
+
if (tagName === "svg") {
|
|
36
|
+
if (item.parents.length) {
|
|
37
|
+
throw new Error(`Unexpected element: <${tagName}>`);
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (unsupportedTags.has(tagName)) {
|
|
42
|
+
$element.remove();
|
|
43
|
+
item.testChildren = false;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (badTags.has(tagName) || !allValidTags.has(tagName)) {
|
|
47
|
+
const parts = tagName.split(":");
|
|
48
|
+
if (parts.length > 1) {
|
|
49
|
+
$element.remove();
|
|
50
|
+
item.testChildren = false;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Unexpected element: <${tagName}>`);
|
|
54
|
+
}
|
|
55
|
+
const parentTagName = (_a = item.parents[0]) == null ? void 0 : _a.tagName;
|
|
56
|
+
for (const [parents, children] of requiredParentTags) {
|
|
57
|
+
if (children.has(tagName)) {
|
|
58
|
+
if (!parents.has(parentTagName)) {
|
|
59
|
+
throw new Error(`Element <${tagName}> has wrong parent element`);
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
checkBadTags
|
|
68
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanupInlineStyle = void 0;
|
|
4
|
+
const parse_1 = require("../../css/parse");
|
|
5
|
+
const attributes_1 = require("../data/attributes");
|
|
6
|
+
const parse_2 = require("../parse");
|
|
7
|
+
/**
|
|
8
|
+
* Expand inline style
|
|
9
|
+
*/
|
|
10
|
+
async function cleanupInlineStyle(svg) {
|
|
11
|
+
await (0, parse_2.parseSVG)(svg, (item) => {
|
|
12
|
+
const $element = item.$element;
|
|
13
|
+
const attribs = item.element.attribs;
|
|
14
|
+
const tagName = item.tagName;
|
|
15
|
+
// Expand style
|
|
16
|
+
if (attribs.style) {
|
|
17
|
+
const parsedStyle = (0, parse_1.parseInlineStyle)(attribs.style);
|
|
18
|
+
if (parsedStyle === null) {
|
|
19
|
+
// Ignore style
|
|
20
|
+
$element.removeAttr('style');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const newStyle = Object.create(null);
|
|
24
|
+
const checkRule = (prop, value) => {
|
|
25
|
+
var _a, _b, _c;
|
|
26
|
+
function warn() {
|
|
27
|
+
console.warn(`Removing unexpected style on "${tagName}": ${prop}`);
|
|
28
|
+
}
|
|
29
|
+
// Check for bad attributes that should be removed
|
|
30
|
+
if (attributes_1.badAttributes.has(prop) ||
|
|
31
|
+
((_a = attributes_1.tagSpecificNonPresentationalAttributes[tagName]) === null || _a === void 0 ? void 0 : _a.has(prop))) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Valid attributes
|
|
35
|
+
if (((_b = attributes_1.tagSpecificAnimatedAttributes[tagName]) === null || _b === void 0 ? void 0 : _b.has(prop)) ||
|
|
36
|
+
((_c = attributes_1.tagSpecificPresentationalAttributes[tagName]) === null || _c === void 0 ? void 0 : _c.has(prop))) {
|
|
37
|
+
$element.attr(prop, value);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Attributes inside <clipPath>
|
|
41
|
+
if (attributes_1.insideClipPathAttributes.has(prop)) {
|
|
42
|
+
if (item.parents.find((item) => item.tagName === 'clipPath')) {
|
|
43
|
+
$element.attr(prop, value);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Bad software stuff
|
|
48
|
+
if (attributes_1.badSoftwareAttributes.has(prop) ||
|
|
49
|
+
attributes_1.badAttributePrefixes.has(prop.split('-').shift())) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Vendor specific junk
|
|
53
|
+
if (prop.slice(0, 1) === '-') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Unknown
|
|
57
|
+
warn();
|
|
58
|
+
};
|
|
59
|
+
// Check all properties
|
|
60
|
+
for (const prop in parsedStyle) {
|
|
61
|
+
checkRule(prop, parsedStyle[prop]);
|
|
62
|
+
}
|
|
63
|
+
// Update style
|
|
64
|
+
const newStyleStr = Object.keys(newStyle)
|
|
65
|
+
.map((key) => key + ':' + newStyle[key] + ';')
|
|
66
|
+
.join('');
|
|
67
|
+
if (newStyleStr.length) {
|
|
68
|
+
$element.attr('style', newStyleStr);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
$element.removeAttr('style');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
exports.cleanupInlineStyle = cleanupInlineStyle;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/svg/cleanup/inline-style.ts
|
|
2
|
+
import { parseInlineStyle } from "../../css/parse.mjs";
|
|
3
|
+
import {
|
|
4
|
+
badAttributes,
|
|
5
|
+
badAttributePrefixes,
|
|
6
|
+
badSoftwareAttributes,
|
|
7
|
+
insideClipPathAttributes,
|
|
8
|
+
tagSpecificAnimatedAttributes,
|
|
9
|
+
tagSpecificNonPresentationalAttributes,
|
|
10
|
+
tagSpecificPresentationalAttributes
|
|
11
|
+
} from "../data/attributes.mjs";
|
|
12
|
+
import { parseSVG } from "../parse.mjs";
|
|
13
|
+
async function cleanupInlineStyle(svg) {
|
|
14
|
+
await parseSVG(svg, (item) => {
|
|
15
|
+
const $element = item.$element;
|
|
16
|
+
const attribs = item.element.attribs;
|
|
17
|
+
const tagName = item.tagName;
|
|
18
|
+
if (attribs.style) {
|
|
19
|
+
const parsedStyle = parseInlineStyle(attribs.style);
|
|
20
|
+
if (parsedStyle === null) {
|
|
21
|
+
$element.removeAttr("style");
|
|
22
|
+
} else {
|
|
23
|
+
const newStyle = Object.create(null);
|
|
24
|
+
const checkRule = (prop, value) => {
|
|
25
|
+
var _a, _b, _c;
|
|
26
|
+
function warn() {
|
|
27
|
+
console.warn(`Removing unexpected style on "${tagName}": ${prop}`);
|
|
28
|
+
}
|
|
29
|
+
if (badAttributes.has(prop) || ((_a = tagSpecificNonPresentationalAttributes[tagName]) == null ? void 0 : _a.has(prop))) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (((_b = tagSpecificAnimatedAttributes[tagName]) == null ? void 0 : _b.has(prop)) || ((_c = tagSpecificPresentationalAttributes[tagName]) == null ? void 0 : _c.has(prop))) {
|
|
33
|
+
$element.attr(prop, value);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (insideClipPathAttributes.has(prop)) {
|
|
37
|
+
if (item.parents.find((item2) => item2.tagName === "clipPath")) {
|
|
38
|
+
$element.attr(prop, value);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (badSoftwareAttributes.has(prop) || badAttributePrefixes.has(prop.split("-").shift())) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (prop.slice(0, 1) === "-") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
warn();
|
|
49
|
+
};
|
|
50
|
+
for (const prop in parsedStyle) {
|
|
51
|
+
checkRule(prop, parsedStyle[prop]);
|
|
52
|
+
}
|
|
53
|
+
const newStyleStr = Object.keys(newStyle).map((key) => key + ":" + newStyle[key] + ";").join("");
|
|
54
|
+
if (newStyleStr.length) {
|
|
55
|
+
$element.attr("style", newStyleStr);
|
|
56
|
+
} else {
|
|
57
|
+
$element.removeAttr("style");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
cleanupInlineStyle
|
|
65
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanupSVGRoot = void 0;
|
|
4
|
+
const attributes_1 = require("../data/attributes");
|
|
5
|
+
const tags_1 = require("../data/tags");
|
|
6
|
+
/**
|
|
7
|
+
* Clean up SVG
|
|
8
|
+
*/
|
|
9
|
+
async function cleanupSVGRoot(svg) {
|
|
10
|
+
const cheerio = svg.$svg;
|
|
11
|
+
const $root = svg.$svg(':root');
|
|
12
|
+
const root = $root.get(0);
|
|
13
|
+
const tagName = 'svg';
|
|
14
|
+
if (root.tagName !== tagName) {
|
|
15
|
+
throw new Error(`Unexpected root tag <${root.tagName}>`);
|
|
16
|
+
}
|
|
17
|
+
const attribs = root.attribs;
|
|
18
|
+
// Check attributes
|
|
19
|
+
const moveToChildren = {};
|
|
20
|
+
Object.keys(attribs).forEach((attr) => {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
const value = attribs[attr];
|
|
23
|
+
// Bad attributes, irrelevant common attributes, namespaces
|
|
24
|
+
if (attributes_1.commonAttributes.has(attr) ||
|
|
25
|
+
attributes_1.badAttributes.has(attr) ||
|
|
26
|
+
attributes_1.junkSVGAttributes.has(attr) ||
|
|
27
|
+
attributes_1.badSoftwareAttributes.has(attr) ||
|
|
28
|
+
attributes_1.badAttributePrefixes.has(attr.split('-').shift()) ||
|
|
29
|
+
attr.split(':').length > 1) {
|
|
30
|
+
$root.removeAttr(attr);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Special handling for dimensions
|
|
34
|
+
switch (attr) {
|
|
35
|
+
case 'width':
|
|
36
|
+
case 'height':
|
|
37
|
+
// Cleanup dimensions
|
|
38
|
+
if (value.slice(-2) === 'px') {
|
|
39
|
+
// Remove 'px'
|
|
40
|
+
const num = value.replace('px', '');
|
|
41
|
+
if (parseFloat(num) + '' === num) {
|
|
42
|
+
$root.attr(attr, num);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Attributes that belong to <svg>
|
|
48
|
+
if ((_a = attributes_1.tagSpecificNonPresentationalAttributes[tagName]) === null || _a === void 0 ? void 0 : _a.has(attr)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Presentational attributes: move to child elements
|
|
52
|
+
if (((_b = attributes_1.tagSpecificPresentationalAttributes[tagName]) === null || _b === void 0 ? void 0 : _b.has(attr)) &&
|
|
53
|
+
attributes_1.tagSpecificPresentationalAttributes.g.has(attr)) {
|
|
54
|
+
moveToChildren[attr] = value;
|
|
55
|
+
$root.removeAttr(attr);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Styling: 'style' should be checked by expandInlineStyle(), remove others
|
|
59
|
+
if (attributes_1.stylingAttributes.has(attr)) {
|
|
60
|
+
switch (attr) {
|
|
61
|
+
case 'style':
|
|
62
|
+
return;
|
|
63
|
+
case 'class':
|
|
64
|
+
$root.removeAttr(attr);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`Unexpected attribute "${attr}" on <${tagName}>`);
|
|
68
|
+
}
|
|
69
|
+
// Junk from bad editors, mostly Adobe Illustrator and Inkscape
|
|
70
|
+
if (
|
|
71
|
+
// Events
|
|
72
|
+
attr.slice(0, 2) === 'on' ||
|
|
73
|
+
// aria-stuff
|
|
74
|
+
attr.slice(0, 5) === 'aria-' ||
|
|
75
|
+
// Junk
|
|
76
|
+
attr.slice(0, 6) === 'xmlns:') {
|
|
77
|
+
$root.removeAttr(attr);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.log(`Removing unexpected attribute on SVG: ${attr}`);
|
|
81
|
+
$root.removeAttr(attr);
|
|
82
|
+
});
|
|
83
|
+
if (Object.keys(moveToChildren).length) {
|
|
84
|
+
// Wrap child elements
|
|
85
|
+
const $wrapper = cheerio('<g />');
|
|
86
|
+
for (const key in moveToChildren) {
|
|
87
|
+
$wrapper.attr(key, moveToChildren[key]);
|
|
88
|
+
}
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental
|
|
90
|
+
$root.children().each((index, child) => {
|
|
91
|
+
const $child = cheerio(child);
|
|
92
|
+
if (child.type !== 'tag') {
|
|
93
|
+
$child.appendTo($wrapper);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const tagName = child.tagName;
|
|
97
|
+
if (tagName === 'style' || tags_1.maskAndSymbolTags.has(tagName)) {
|
|
98
|
+
// Do not wrap these elements
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
$child.appendTo($wrapper);
|
|
102
|
+
});
|
|
103
|
+
$wrapper.appendTo($root);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.cleanupSVGRoot = cleanupSVGRoot;
|