@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,136 @@
|
|
|
1
|
+
// src/svg/data/tags.ts
|
|
2
|
+
var badTags = new Set([
|
|
3
|
+
"foreignObject",
|
|
4
|
+
"script",
|
|
5
|
+
"image",
|
|
6
|
+
"feImage",
|
|
7
|
+
"animateColor",
|
|
8
|
+
"altGlyph",
|
|
9
|
+
"text",
|
|
10
|
+
"tspan",
|
|
11
|
+
"switch",
|
|
12
|
+
"textPath",
|
|
13
|
+
"font",
|
|
14
|
+
"font-face",
|
|
15
|
+
"glyph",
|
|
16
|
+
"missing-glyph",
|
|
17
|
+
"hkern",
|
|
18
|
+
"vhern",
|
|
19
|
+
"view",
|
|
20
|
+
"a"
|
|
21
|
+
]);
|
|
22
|
+
var unsupportedTags = new Set(["metadata", "desc", "title"]);
|
|
23
|
+
var styleTag = new Set(["style"]);
|
|
24
|
+
var defsTag = new Set(["defs"]);
|
|
25
|
+
var maskAndSymbolTags = new Set(["clipPath", "mask", "symbol"]);
|
|
26
|
+
var shapeTags = new Set([
|
|
27
|
+
"circle",
|
|
28
|
+
"ellipse",
|
|
29
|
+
"line",
|
|
30
|
+
"path",
|
|
31
|
+
"polygon",
|
|
32
|
+
"polyline",
|
|
33
|
+
"rect"
|
|
34
|
+
]);
|
|
35
|
+
var useTag = new Set(["use"]);
|
|
36
|
+
var groupTag = new Set(["g"]);
|
|
37
|
+
var markerTag = new Set(["marker"]);
|
|
38
|
+
var animateTags = new Set([
|
|
39
|
+
"animate",
|
|
40
|
+
"animateMotion",
|
|
41
|
+
"animateTransform",
|
|
42
|
+
"discard",
|
|
43
|
+
"set"
|
|
44
|
+
]);
|
|
45
|
+
var animateMotionChildTags = new Set(["mpath"]);
|
|
46
|
+
var gradientTags = new Set(["linearGradient", "radialGradient"]);
|
|
47
|
+
var gradientChildTags = new Set(["stop"]);
|
|
48
|
+
var patternTag = new Set(["pattern"]);
|
|
49
|
+
var filterTag = new Set(["filter"]);
|
|
50
|
+
var feLightningTags = new Set([
|
|
51
|
+
"feDiffuseLighting",
|
|
52
|
+
"feSpecularLighting"
|
|
53
|
+
]);
|
|
54
|
+
var filterChildTags = new Set([
|
|
55
|
+
"feBlend",
|
|
56
|
+
"feColorMatrix",
|
|
57
|
+
"feComponentTransfer",
|
|
58
|
+
"feComposite",
|
|
59
|
+
"feConvolveMatrix",
|
|
60
|
+
"feDisplacementMap",
|
|
61
|
+
"feDropShadow",
|
|
62
|
+
"feFlood",
|
|
63
|
+
"feGaussianBlur",
|
|
64
|
+
"feMerge",
|
|
65
|
+
"feMorphology",
|
|
66
|
+
"feOffset",
|
|
67
|
+
"feTile",
|
|
68
|
+
"feTurbulence",
|
|
69
|
+
...feLightningTags
|
|
70
|
+
]);
|
|
71
|
+
var feComponentTransferChildTag = new Set([
|
|
72
|
+
"feFuncR",
|
|
73
|
+
"feFuncG",
|
|
74
|
+
"feFuncB",
|
|
75
|
+
"feFuncA"
|
|
76
|
+
]);
|
|
77
|
+
var feLightningChildTags = new Set([
|
|
78
|
+
"feSpotLight",
|
|
79
|
+
"fePointLight",
|
|
80
|
+
"feDistantLight"
|
|
81
|
+
]);
|
|
82
|
+
var feMergeChildTags = new Set(["feMergeNode"]);
|
|
83
|
+
var tagsInsideDefs = new Set([
|
|
84
|
+
...gradientTags,
|
|
85
|
+
...patternTag,
|
|
86
|
+
...markerTag
|
|
87
|
+
]);
|
|
88
|
+
var tagsBeforeAnimation = new Set([
|
|
89
|
+
...shapeTags,
|
|
90
|
+
...filterChildTags,
|
|
91
|
+
...feComponentTransferChildTag
|
|
92
|
+
]);
|
|
93
|
+
var allValidTags = new Set([
|
|
94
|
+
...styleTag,
|
|
95
|
+
...defsTag,
|
|
96
|
+
...maskAndSymbolTags,
|
|
97
|
+
...shapeTags,
|
|
98
|
+
...useTag,
|
|
99
|
+
...groupTag,
|
|
100
|
+
...markerTag,
|
|
101
|
+
...animateTags,
|
|
102
|
+
...animateMotionChildTags,
|
|
103
|
+
...gradientTags,
|
|
104
|
+
...gradientChildTags,
|
|
105
|
+
...patternTag,
|
|
106
|
+
...filterTag,
|
|
107
|
+
...filterChildTags,
|
|
108
|
+
...feComponentTransferChildTag,
|
|
109
|
+
...feLightningChildTags,
|
|
110
|
+
...feMergeChildTags
|
|
111
|
+
]);
|
|
112
|
+
export {
|
|
113
|
+
allValidTags,
|
|
114
|
+
animateMotionChildTags,
|
|
115
|
+
animateTags,
|
|
116
|
+
badTags,
|
|
117
|
+
defsTag,
|
|
118
|
+
feComponentTransferChildTag,
|
|
119
|
+
feLightningChildTags,
|
|
120
|
+
feLightningTags,
|
|
121
|
+
feMergeChildTags,
|
|
122
|
+
filterChildTags,
|
|
123
|
+
filterTag,
|
|
124
|
+
gradientChildTags,
|
|
125
|
+
gradientTags,
|
|
126
|
+
groupTag,
|
|
127
|
+
markerTag,
|
|
128
|
+
maskAndSymbolTags,
|
|
129
|
+
patternTag,
|
|
130
|
+
shapeTags,
|
|
131
|
+
styleTag,
|
|
132
|
+
tagsBeforeAnimation,
|
|
133
|
+
tagsInsideDefs,
|
|
134
|
+
unsupportedTags,
|
|
135
|
+
useTag
|
|
136
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/// <reference types="cheerio" />
|
|
2
|
+
export interface ViewBox {
|
|
3
|
+
left: number;
|
|
4
|
+
top: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class SVG {
|
|
9
|
+
$svg: cheerio.Root;
|
|
10
|
+
viewBox: ViewBox;
|
|
11
|
+
/**
|
|
12
|
+
* Constructor
|
|
13
|
+
*/
|
|
14
|
+
constructor(content: string);
|
|
15
|
+
/**
|
|
16
|
+
* Get SVG as string
|
|
17
|
+
*/
|
|
18
|
+
toString(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Get SVG as string without whitespaces
|
|
21
|
+
*/
|
|
22
|
+
toMinifiedString(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get body
|
|
25
|
+
*/
|
|
26
|
+
getBody(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Load SVG
|
|
29
|
+
*
|
|
30
|
+
* @param {string} content
|
|
31
|
+
*/
|
|
32
|
+
load(content: string): void;
|
|
33
|
+
}
|
package/lib/svg/index.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SVG = void 0;
|
|
7
|
+
const cheerio_1 = __importDefault(require("cheerio"));
|
|
8
|
+
class SVG {
|
|
9
|
+
/**
|
|
10
|
+
* Constructor
|
|
11
|
+
*/
|
|
12
|
+
constructor(content) {
|
|
13
|
+
this.load(content);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get SVG as string
|
|
17
|
+
*/
|
|
18
|
+
toString() {
|
|
19
|
+
const $root = this.$svg(':root');
|
|
20
|
+
const box = this.viewBox;
|
|
21
|
+
// Add missing viewBox attribute
|
|
22
|
+
if ($root.attr('viewBox') === void 0) {
|
|
23
|
+
$root.attr('viewBox', box.left + ' ' + box.top + ' ' + box.width + ' ' + box.height);
|
|
24
|
+
}
|
|
25
|
+
// Add missing width/height
|
|
26
|
+
if ($root.attr('width') === void 0) {
|
|
27
|
+
$root.attr('width', box.width + '');
|
|
28
|
+
}
|
|
29
|
+
if ($root.attr('height') === void 0) {
|
|
30
|
+
$root.attr('height', box.height + '');
|
|
31
|
+
}
|
|
32
|
+
return this.$svg.html();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get SVG as string without whitespaces
|
|
36
|
+
*/
|
|
37
|
+
toMinifiedString() {
|
|
38
|
+
return this.toString().replace(/\s*\n\s*/g, '');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get body
|
|
42
|
+
*/
|
|
43
|
+
getBody() {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
45
|
+
return this.$svg('svg')
|
|
46
|
+
.html()
|
|
47
|
+
.replace(/\s*\n\s*/g, '');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load SVG
|
|
51
|
+
*
|
|
52
|
+
* @param {string} content
|
|
53
|
+
*/
|
|
54
|
+
load(content) {
|
|
55
|
+
// Remove junk
|
|
56
|
+
function remove(str1, str2, append) {
|
|
57
|
+
let start = 0;
|
|
58
|
+
while ((start = content.indexOf(str1, start)) !== -1) {
|
|
59
|
+
const end = content.indexOf(str2, start + str1.length);
|
|
60
|
+
if (end === -1) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
content =
|
|
64
|
+
content.slice(0, start) +
|
|
65
|
+
append +
|
|
66
|
+
content.slice(end + str2.length);
|
|
67
|
+
start = start + append.length;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Remove comments
|
|
71
|
+
remove('<!--', '-->', '');
|
|
72
|
+
// Remove doctype and XML declaration
|
|
73
|
+
remove('<?xml', '?>', '');
|
|
74
|
+
remove('<!DOCTYPE svg', '<svg', '<svg');
|
|
75
|
+
// Remove Adobe Illustrator junk
|
|
76
|
+
remove('xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"', '', '');
|
|
77
|
+
remove('xml:space="preserve"', '', '');
|
|
78
|
+
// Remove empty <g> elements
|
|
79
|
+
content = content.replace(/<g>\s*<\/g>/g, '');
|
|
80
|
+
// Load content
|
|
81
|
+
this.$svg = cheerio_1.default.load(content.trim(), {
|
|
82
|
+
lowerCaseAttributeNames: false,
|
|
83
|
+
xmlMode: true,
|
|
84
|
+
});
|
|
85
|
+
// Check root
|
|
86
|
+
const $root = this.$svg(':root');
|
|
87
|
+
if ($root.length > 1 || $root.get(0).tagName !== 'svg') {
|
|
88
|
+
throw new Error('Invalid SVG file: bad root tag');
|
|
89
|
+
}
|
|
90
|
+
// Get dimensions and origin
|
|
91
|
+
const viewBox = $root.attr('viewBox');
|
|
92
|
+
if (viewBox !== void 0) {
|
|
93
|
+
const list = viewBox.split(' ');
|
|
94
|
+
this.viewBox = {
|
|
95
|
+
left: parseFloat(list[0]),
|
|
96
|
+
top: parseFloat(list[1]),
|
|
97
|
+
width: parseFloat(list[2]),
|
|
98
|
+
height: parseFloat(list[3]),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const width = $root.attr('width');
|
|
103
|
+
const height = $root.attr('height');
|
|
104
|
+
if (!width || !height) {
|
|
105
|
+
throw new Error('Invalid SVG file: missing dimensions');
|
|
106
|
+
}
|
|
107
|
+
this.viewBox = {
|
|
108
|
+
left: 0,
|
|
109
|
+
top: 0,
|
|
110
|
+
width: parseFloat(width),
|
|
111
|
+
height: parseFloat(height),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
Object.keys(this.viewBox).forEach((key) => {
|
|
115
|
+
const attr = key;
|
|
116
|
+
if (isNaN(this.viewBox[attr])) {
|
|
117
|
+
throw new Error(`Invalid SVG file: invalid ${attr}`);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.SVG = SVG;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/svg/index.ts
|
|
2
|
+
import cheerio from "cheerio";
|
|
3
|
+
var SVG = class {
|
|
4
|
+
constructor(content) {
|
|
5
|
+
this.load(content);
|
|
6
|
+
}
|
|
7
|
+
toString() {
|
|
8
|
+
const $root = this.$svg(":root");
|
|
9
|
+
const box = this.viewBox;
|
|
10
|
+
if ($root.attr("viewBox") === void 0) {
|
|
11
|
+
$root.attr("viewBox", box.left + " " + box.top + " " + box.width + " " + box.height);
|
|
12
|
+
}
|
|
13
|
+
if ($root.attr("width") === void 0) {
|
|
14
|
+
$root.attr("width", box.width + "");
|
|
15
|
+
}
|
|
16
|
+
if ($root.attr("height") === void 0) {
|
|
17
|
+
$root.attr("height", box.height + "");
|
|
18
|
+
}
|
|
19
|
+
return this.$svg.html();
|
|
20
|
+
}
|
|
21
|
+
toMinifiedString() {
|
|
22
|
+
return this.toString().replace(/\s*\n\s*/g, "");
|
|
23
|
+
}
|
|
24
|
+
getBody() {
|
|
25
|
+
return this.$svg("svg").html().replace(/\s*\n\s*/g, "");
|
|
26
|
+
}
|
|
27
|
+
load(content) {
|
|
28
|
+
function remove(str1, str2, append) {
|
|
29
|
+
let start = 0;
|
|
30
|
+
while ((start = content.indexOf(str1, start)) !== -1) {
|
|
31
|
+
const end = content.indexOf(str2, start + str1.length);
|
|
32
|
+
if (end === -1) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
content = content.slice(0, start) + append + content.slice(end + str2.length);
|
|
36
|
+
start = start + append.length;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
remove("<!--", "-->", "");
|
|
40
|
+
remove("<?xml", "?>", "");
|
|
41
|
+
remove("<!DOCTYPE svg", "<svg", "<svg");
|
|
42
|
+
remove('xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"', "", "");
|
|
43
|
+
remove('xml:space="preserve"', "", "");
|
|
44
|
+
content = content.replace(/<g>\s*<\/g>/g, "");
|
|
45
|
+
this.$svg = cheerio.load(content.trim(), {
|
|
46
|
+
lowerCaseAttributeNames: false,
|
|
47
|
+
xmlMode: true
|
|
48
|
+
});
|
|
49
|
+
const $root = this.$svg(":root");
|
|
50
|
+
if ($root.length > 1 || $root.get(0).tagName !== "svg") {
|
|
51
|
+
throw new Error("Invalid SVG file: bad root tag");
|
|
52
|
+
}
|
|
53
|
+
const viewBox = $root.attr("viewBox");
|
|
54
|
+
if (viewBox !== void 0) {
|
|
55
|
+
const list = viewBox.split(" ");
|
|
56
|
+
this.viewBox = {
|
|
57
|
+
left: parseFloat(list[0]),
|
|
58
|
+
top: parseFloat(list[1]),
|
|
59
|
+
width: parseFloat(list[2]),
|
|
60
|
+
height: parseFloat(list[3])
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
const width = $root.attr("width");
|
|
64
|
+
const height = $root.attr("height");
|
|
65
|
+
if (!width || !height) {
|
|
66
|
+
throw new Error("Invalid SVG file: missing dimensions");
|
|
67
|
+
}
|
|
68
|
+
this.viewBox = {
|
|
69
|
+
left: 0,
|
|
70
|
+
top: 0,
|
|
71
|
+
width: parseFloat(width),
|
|
72
|
+
height: parseFloat(height)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
Object.keys(this.viewBox).forEach((key) => {
|
|
76
|
+
const attr = key;
|
|
77
|
+
if (isNaN(this.viewBox[attr])) {
|
|
78
|
+
throw new Error(`Invalid SVG file: invalid ${attr}`);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
export {
|
|
84
|
+
SVG
|
|
85
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SVG } from '.';
|
|
2
|
+
import { ParseSVGCallbackItem } from './parse';
|
|
3
|
+
/**
|
|
4
|
+
* Item in callback
|
|
5
|
+
*/
|
|
6
|
+
interface ParseSVGStyleCallbackItemCommon {
|
|
7
|
+
prop: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
interface ParseSVGStyleCallbackItemInline extends ParseSVGStyleCallbackItemCommon {
|
|
11
|
+
type: 'inline';
|
|
12
|
+
item: ParseSVGCallbackItem;
|
|
13
|
+
}
|
|
14
|
+
interface ParseSVGStyleCallbackItemGlobal extends ParseSVGStyleCallbackItemCommon {
|
|
15
|
+
type: 'global';
|
|
16
|
+
}
|
|
17
|
+
export declare type ParseSVGStyleCallbackItem = ParseSVGStyleCallbackItemInline | ParseSVGStyleCallbackItemGlobal;
|
|
18
|
+
/**
|
|
19
|
+
* Result: undefined to remove item, string to change/keep item
|
|
20
|
+
*/
|
|
21
|
+
export declare type ParseSVGStyleCallbackResult = string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Callback function
|
|
24
|
+
*/
|
|
25
|
+
export declare type ParseSVGStyleCallback = (item: ParseSVGStyleCallbackItem) => ParseSVGStyleCallbackResult | Promise<ParseSVGStyleCallbackResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Options
|
|
28
|
+
*/
|
|
29
|
+
interface ParseSVGStyleOptions {
|
|
30
|
+
skipMasks?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Parse styles in SVG
|
|
34
|
+
*
|
|
35
|
+
* This function finds CSS in SVG, parses it, calls callback for each rule.
|
|
36
|
+
* Callback should return new value (string) or undefined to remove rule.
|
|
37
|
+
* Callback can be asynchronous.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseSVGStyle(svg: SVG, callback: ParseSVGStyleCallback, options?: ParseSVGStyleOptions): Promise<void>;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSVGStyle = void 0;
|
|
4
|
+
const parse_1 = require("../css/parse");
|
|
5
|
+
const export_1 = require("../css/parser/export");
|
|
6
|
+
const tokens_1 = require("../css/parser/tokens");
|
|
7
|
+
const tree_1 = require("../css/parser/tree");
|
|
8
|
+
const tags_1 = require("./data/tags");
|
|
9
|
+
const parse_2 = require("./parse");
|
|
10
|
+
/**
|
|
11
|
+
* Parse styles in SVG
|
|
12
|
+
*
|
|
13
|
+
* This function finds CSS in SVG, parses it, calls callback for each rule.
|
|
14
|
+
* Callback should return new value (string) or undefined to remove rule.
|
|
15
|
+
* Callback can be asynchronous.
|
|
16
|
+
*/
|
|
17
|
+
async function parseSVGStyle(svg, callback, options = {}) {
|
|
18
|
+
return (0, parse_2.parseSVG)(svg, async (item) => {
|
|
19
|
+
const tagName = item.tagName;
|
|
20
|
+
const $element = item.$element;
|
|
21
|
+
if (tagName === 'style') {
|
|
22
|
+
// Style tag
|
|
23
|
+
const content = $element.html();
|
|
24
|
+
if (typeof content !== 'string') {
|
|
25
|
+
$element.remove();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const tokens = (0, tokens_1.getTokens)(content);
|
|
29
|
+
if (!(tokens instanceof Array)) {
|
|
30
|
+
// Invalid style
|
|
31
|
+
throw new Error('Error parsing style');
|
|
32
|
+
}
|
|
33
|
+
// Parse all tokens
|
|
34
|
+
let changed = false;
|
|
35
|
+
const newTokens = [];
|
|
36
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
37
|
+
const token = tokens[i];
|
|
38
|
+
if (token.type !== 'rule') {
|
|
39
|
+
newTokens.push(token);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const value = token.value;
|
|
43
|
+
let result = callback({
|
|
44
|
+
type: 'global',
|
|
45
|
+
prop: token.prop,
|
|
46
|
+
value,
|
|
47
|
+
});
|
|
48
|
+
if (result instanceof Promise) {
|
|
49
|
+
result = await result;
|
|
50
|
+
}
|
|
51
|
+
if (result !== void 0) {
|
|
52
|
+
if (result !== value) {
|
|
53
|
+
changed = true;
|
|
54
|
+
token.value = result;
|
|
55
|
+
}
|
|
56
|
+
newTokens.push(token);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Delete token
|
|
60
|
+
changed = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!changed) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Update style
|
|
67
|
+
const tree = (0, tree_1.tokensTree)(newTokens);
|
|
68
|
+
if (!tree.length) {
|
|
69
|
+
// Empty
|
|
70
|
+
$element.remove();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const newContent = (0, export_1.tokensToString)(tree);
|
|
74
|
+
item.$element.text(newContent);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Skip masks
|
|
78
|
+
if (options.skipMasks && tags_1.maskAndSymbolTags.has(tagName)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Parse style
|
|
82
|
+
const attribs = item.element.attribs;
|
|
83
|
+
if (attribs.style === void 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const parsedStyle = (0, parse_1.parseInlineStyle)(attribs.style);
|
|
87
|
+
if (parsedStyle === null) {
|
|
88
|
+
// Ignore style
|
|
89
|
+
$element.removeAttr('style');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const props = Object.keys(parsedStyle);
|
|
93
|
+
let changed = false;
|
|
94
|
+
for (let i = 0; i < props.length; i++) {
|
|
95
|
+
const prop = props[i];
|
|
96
|
+
const value = parsedStyle[prop];
|
|
97
|
+
let result = callback({
|
|
98
|
+
type: 'inline',
|
|
99
|
+
prop,
|
|
100
|
+
value,
|
|
101
|
+
item,
|
|
102
|
+
});
|
|
103
|
+
if (result instanceof Promise) {
|
|
104
|
+
result = await result;
|
|
105
|
+
}
|
|
106
|
+
if (result !== value) {
|
|
107
|
+
changed = true;
|
|
108
|
+
if (result === void 0) {
|
|
109
|
+
delete parsedStyle[prop];
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
parsedStyle[prop] = result;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Update style
|
|
117
|
+
if (!changed) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const newStyle = Object.keys(parsedStyle)
|
|
121
|
+
.map((key) => key + ':' + parsedStyle[key] + ';')
|
|
122
|
+
.join('');
|
|
123
|
+
if (!newStyle.length) {
|
|
124
|
+
$element.removeAttr('style');
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
$element.attr('style', newStyle);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
exports.parseSVGStyle = parseSVGStyle;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// src/svg/parse-style.ts
|
|
2
|
+
import { parseInlineStyle } from "../css/parse.mjs";
|
|
3
|
+
import { tokensToString } from "../css/parser/export.mjs";
|
|
4
|
+
import { getTokens } from "../css/parser/tokens.mjs";
|
|
5
|
+
import { tokensTree } from "../css/parser/tree.mjs";
|
|
6
|
+
import { maskAndSymbolTags } from "./data/tags.mjs";
|
|
7
|
+
import { parseSVG } from "./parse.mjs";
|
|
8
|
+
async function parseSVGStyle(svg, callback, options = {}) {
|
|
9
|
+
return parseSVG(svg, async (item) => {
|
|
10
|
+
const tagName = item.tagName;
|
|
11
|
+
const $element = item.$element;
|
|
12
|
+
if (tagName === "style") {
|
|
13
|
+
const content = $element.html();
|
|
14
|
+
if (typeof content !== "string") {
|
|
15
|
+
$element.remove();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const tokens = getTokens(content);
|
|
19
|
+
if (!(tokens instanceof Array)) {
|
|
20
|
+
throw new Error("Error parsing style");
|
|
21
|
+
}
|
|
22
|
+
let changed2 = false;
|
|
23
|
+
const newTokens = [];
|
|
24
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
25
|
+
const token = tokens[i];
|
|
26
|
+
if (token.type !== "rule") {
|
|
27
|
+
newTokens.push(token);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const value = token.value;
|
|
31
|
+
let result = callback({
|
|
32
|
+
type: "global",
|
|
33
|
+
prop: token.prop,
|
|
34
|
+
value
|
|
35
|
+
});
|
|
36
|
+
if (result instanceof Promise) {
|
|
37
|
+
result = await result;
|
|
38
|
+
}
|
|
39
|
+
if (result !== void 0) {
|
|
40
|
+
if (result !== value) {
|
|
41
|
+
changed2 = true;
|
|
42
|
+
token.value = result;
|
|
43
|
+
}
|
|
44
|
+
newTokens.push(token);
|
|
45
|
+
} else {
|
|
46
|
+
changed2 = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!changed2) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const tree = tokensTree(newTokens);
|
|
53
|
+
if (!tree.length) {
|
|
54
|
+
$element.remove();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const newContent = tokensToString(tree);
|
|
58
|
+
item.$element.text(newContent);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (options.skipMasks && maskAndSymbolTags.has(tagName)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const attribs = item.element.attribs;
|
|
65
|
+
if (attribs.style === void 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const parsedStyle = parseInlineStyle(attribs.style);
|
|
69
|
+
if (parsedStyle === null) {
|
|
70
|
+
$element.removeAttr("style");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const props = Object.keys(parsedStyle);
|
|
74
|
+
let changed = false;
|
|
75
|
+
for (let i = 0; i < props.length; i++) {
|
|
76
|
+
const prop = props[i];
|
|
77
|
+
const value = parsedStyle[prop];
|
|
78
|
+
let result = callback({
|
|
79
|
+
type: "inline",
|
|
80
|
+
prop,
|
|
81
|
+
value,
|
|
82
|
+
item
|
|
83
|
+
});
|
|
84
|
+
if (result instanceof Promise) {
|
|
85
|
+
result = await result;
|
|
86
|
+
}
|
|
87
|
+
if (result !== value) {
|
|
88
|
+
changed = true;
|
|
89
|
+
if (result === void 0) {
|
|
90
|
+
delete parsedStyle[prop];
|
|
91
|
+
} else {
|
|
92
|
+
parsedStyle[prop] = result;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!changed) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const newStyle = Object.keys(parsedStyle).map((key) => key + ":" + parsedStyle[key] + ";").join("");
|
|
100
|
+
if (!newStyle.length) {
|
|
101
|
+
$element.removeAttr("style");
|
|
102
|
+
} else {
|
|
103
|
+
$element.attr("style", newStyle);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
parseSVGStyle
|
|
109
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/// <reference types="cheerio" />
|
|
2
|
+
import type { SVG } from './';
|
|
3
|
+
/**
|
|
4
|
+
* Shortcuts for Cheerio elements
|
|
5
|
+
*/
|
|
6
|
+
export declare type CheerioElement = cheerio.TagElement;
|
|
7
|
+
export declare type WrappedCheerioElement = cheerio.Cheerio;
|
|
8
|
+
/**
|
|
9
|
+
* Item in callback
|
|
10
|
+
*/
|
|
11
|
+
export interface ParseSVGCallbackItem {
|
|
12
|
+
tagName: string;
|
|
13
|
+
element: CheerioElement;
|
|
14
|
+
$element: WrappedCheerioElement;
|
|
15
|
+
svg: SVG;
|
|
16
|
+
parents: ParseSVGCallbackItem[];
|
|
17
|
+
testChildren: boolean;
|
|
18
|
+
removeNode: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Callback function
|
|
22
|
+
*/
|
|
23
|
+
export declare type ParseSVGCallback = (item: ParseSVGCallbackItem) => void | Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Parse SVG
|
|
26
|
+
*
|
|
27
|
+
* This function finds all elements in SVG and calls callback for each element.
|
|
28
|
+
* Callback can be asynchronous.
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseSVG(svg: SVG, callback: ParseSVGCallback): Promise<void>;
|