@emasoft/svg-matrix 1.0.19 → 1.0.21
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/README.md +256 -759
- package/bin/svg-matrix.js +171 -2
- package/bin/svglinter.cjs +1162 -0
- package/package.json +9 -3
- package/src/animation-optimization.js +394 -0
- package/src/animation-references.js +440 -0
- package/src/arc-length.js +940 -0
- package/src/bezier-analysis.js +1626 -0
- package/src/bezier-intersections.js +1369 -0
- package/src/clip-path-resolver.js +110 -2
- package/src/convert-path-data.js +583 -0
- package/src/css-specificity.js +443 -0
- package/src/douglas-peucker.js +356 -0
- package/src/flatten-pipeline.js +109 -4
- package/src/geometry-to-path.js +126 -16
- package/src/gjk-collision.js +840 -0
- package/src/index.js +175 -2
- package/src/off-canvas-detection.js +1222 -0
- package/src/path-analysis.js +1241 -0
- package/src/path-data-plugins.js +928 -0
- package/src/path-optimization.js +825 -0
- package/src/path-simplification.js +1140 -0
- package/src/polygon-clip.js +376 -99
- package/src/svg-boolean-ops.js +898 -0
- package/src/svg-collections.js +910 -0
- package/src/svg-parser.js +175 -16
- package/src/svg-rendering-context.js +627 -0
- package/src/svg-toolbox.js +7495 -0
- package/src/svg-validation-data.js +944 -0
- package/src/transform-decomposition.js +810 -0
- package/src/transform-optimization.js +936 -0
- package/src/use-symbol-resolver.js +75 -7
|
@@ -0,0 +1,910 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG Collections - SVGO-compatible reference data
|
|
3
|
+
*
|
|
4
|
+
* This module provides comprehensive SVG element and attribute definitions,
|
|
5
|
+
* default values, and categorization data equivalent to SVGO's _collections.js
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// INHERITABLE ATTRIBUTES
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* CSS properties that inherit from parent elements in SVG
|
|
14
|
+
* Reference: SVG 1.1 spec, CSS inheritance rules
|
|
15
|
+
*/
|
|
16
|
+
export const inheritableAttrs = new Set([
|
|
17
|
+
'clip-rule',
|
|
18
|
+
'color',
|
|
19
|
+
'color-interpolation',
|
|
20
|
+
'color-interpolation-filters',
|
|
21
|
+
'color-profile',
|
|
22
|
+
'color-rendering',
|
|
23
|
+
'cursor',
|
|
24
|
+
'direction',
|
|
25
|
+
'dominant-baseline',
|
|
26
|
+
'fill',
|
|
27
|
+
'fill-opacity',
|
|
28
|
+
'fill-rule',
|
|
29
|
+
'font',
|
|
30
|
+
'font-family',
|
|
31
|
+
'font-size',
|
|
32
|
+
'font-size-adjust',
|
|
33
|
+
'font-stretch',
|
|
34
|
+
'font-style',
|
|
35
|
+
'font-variant',
|
|
36
|
+
'font-weight',
|
|
37
|
+
'glyph-orientation-horizontal',
|
|
38
|
+
'glyph-orientation-vertical',
|
|
39
|
+
'image-rendering',
|
|
40
|
+
'letter-spacing',
|
|
41
|
+
'marker',
|
|
42
|
+
'marker-end',
|
|
43
|
+
'marker-mid',
|
|
44
|
+
'marker-start',
|
|
45
|
+
'paint-order',
|
|
46
|
+
'pointer-events',
|
|
47
|
+
'shape-rendering',
|
|
48
|
+
'stroke',
|
|
49
|
+
'stroke-dasharray',
|
|
50
|
+
'stroke-dashoffset',
|
|
51
|
+
'stroke-linecap',
|
|
52
|
+
'stroke-linejoin',
|
|
53
|
+
'stroke-miterlimit',
|
|
54
|
+
'stroke-opacity',
|
|
55
|
+
'stroke-width',
|
|
56
|
+
'text-anchor',
|
|
57
|
+
'text-rendering',
|
|
58
|
+
'visibility',
|
|
59
|
+
'word-spacing',
|
|
60
|
+
'writing-mode',
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Presentation attributes that do NOT inherit
|
|
65
|
+
*/
|
|
66
|
+
export const nonInheritableAttrs = new Set([
|
|
67
|
+
'clip-path',
|
|
68
|
+
'display',
|
|
69
|
+
'filter',
|
|
70
|
+
'mask',
|
|
71
|
+
'opacity',
|
|
72
|
+
'text-decoration',
|
|
73
|
+
'transform',
|
|
74
|
+
'unicode-bidi',
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// REFERENCE PROPERTIES
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Attributes that can contain url() references to other elements
|
|
83
|
+
*/
|
|
84
|
+
export const referencesProps = new Set([
|
|
85
|
+
'clip-path',
|
|
86
|
+
'color-profile',
|
|
87
|
+
'fill',
|
|
88
|
+
'filter',
|
|
89
|
+
'href',
|
|
90
|
+
'marker-end',
|
|
91
|
+
'marker-mid',
|
|
92
|
+
'marker-start',
|
|
93
|
+
'mask',
|
|
94
|
+
'stroke',
|
|
95
|
+
'style',
|
|
96
|
+
'xlink:href',
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// ELEMENT GROUPS
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
export const elemsGroups = {
|
|
104
|
+
animation: new Set([
|
|
105
|
+
'animate', 'animateColor', 'animateMotion', 'animateTransform', 'set'
|
|
106
|
+
]),
|
|
107
|
+
descriptive: new Set([
|
|
108
|
+
'desc', 'metadata', 'title'
|
|
109
|
+
]),
|
|
110
|
+
shape: new Set([
|
|
111
|
+
'circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect'
|
|
112
|
+
]),
|
|
113
|
+
structural: new Set([
|
|
114
|
+
'defs', 'g', 'svg', 'symbol', 'use'
|
|
115
|
+
]),
|
|
116
|
+
paintServer: new Set([
|
|
117
|
+
'hatch', 'linearGradient', 'meshGradient', 'pattern', 'radialGradient', 'solidColor'
|
|
118
|
+
]),
|
|
119
|
+
nonRendering: new Set([
|
|
120
|
+
'clipPath', 'filter', 'linearGradient', 'marker', 'mask', 'pattern',
|
|
121
|
+
'radialGradient', 'solidColor', 'symbol'
|
|
122
|
+
]),
|
|
123
|
+
container: new Set([
|
|
124
|
+
'a', 'defs', 'g', 'marker', 'mask', 'pattern', 'svg', 'switch', 'symbol'
|
|
125
|
+
]),
|
|
126
|
+
textContent: new Set([
|
|
127
|
+
'altGlyph', 'altGlyphDef', 'altGlyphItem', 'glyph', 'glyphRef',
|
|
128
|
+
'text', 'textPath', 'tref', 'tspan'
|
|
129
|
+
]),
|
|
130
|
+
filterPrimitive: new Set([
|
|
131
|
+
'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite',
|
|
132
|
+
'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap',
|
|
133
|
+
'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR',
|
|
134
|
+
'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology',
|
|
135
|
+
'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence'
|
|
136
|
+
]),
|
|
137
|
+
lightSource: new Set([
|
|
138
|
+
'feDistantLight', 'fePointLight', 'feSpotLight'
|
|
139
|
+
]),
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// ============================================================================
|
|
143
|
+
// EDITOR NAMESPACES
|
|
144
|
+
// ============================================================================
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Namespaces used by various SVG editors that can be safely removed
|
|
148
|
+
*/
|
|
149
|
+
export const editorNamespaces = new Set([
|
|
150
|
+
'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
|
|
151
|
+
'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
|
|
152
|
+
'http://www.inkscape.org/namespaces/inkscape',
|
|
153
|
+
'http://www.bohemiancoding.com/sketch/ns',
|
|
154
|
+
'http://ns.adobe.com/AdobeIllustrator/10.0/',
|
|
155
|
+
'http://ns.adobe.com/Graphs/1.0/',
|
|
156
|
+
'http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/',
|
|
157
|
+
'http://ns.adobe.com/Variables/1.0/',
|
|
158
|
+
'http://ns.adobe.com/SaveForWeb/1.0/',
|
|
159
|
+
'http://ns.adobe.com/Extensibility/1.0/',
|
|
160
|
+
'http://ns.adobe.com/Flows/1.0/',
|
|
161
|
+
'http://ns.adobe.com/ImageReplacement/1.0/',
|
|
162
|
+
'http://ns.adobe.com/GenericCustomNamespace/1.0/',
|
|
163
|
+
'http://ns.adobe.com/XPath/1.0/',
|
|
164
|
+
'http://schemas.microsoft.com/visio/2003/SVGExtensions/',
|
|
165
|
+
'http://taptrix.com/vectorillustrator/svg_extensions',
|
|
166
|
+
'http://www.figma.com/figma/ns',
|
|
167
|
+
'http://purl.org/dc/elements/1.1/',
|
|
168
|
+
'http://creativecommons.org/ns#',
|
|
169
|
+
'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
|
170
|
+
'http://www.serif.com/',
|
|
171
|
+
'http://www.vector.evaxdesign.sk',
|
|
172
|
+
]);
|
|
173
|
+
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// NAMED COLORS
|
|
176
|
+
// ============================================================================
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* SVG named colors to hex values
|
|
180
|
+
* Note: CSS color names are case-insensitive per spec.
|
|
181
|
+
* All keys are lowercase. When looking up colors, normalize input with .toLowerCase()
|
|
182
|
+
*/
|
|
183
|
+
export const colorsNames = {
|
|
184
|
+
'aliceblue': '#f0f8ff',
|
|
185
|
+
'antiquewhite': '#faebd7',
|
|
186
|
+
'aqua': '#0ff',
|
|
187
|
+
'aquamarine': '#7fffd4',
|
|
188
|
+
'azure': '#f0ffff',
|
|
189
|
+
'beige': '#f5f5dc',
|
|
190
|
+
'bisque': '#ffe4c4',
|
|
191
|
+
'black': '#000',
|
|
192
|
+
'blanchedalmond': '#ffebcd',
|
|
193
|
+
'blue': '#00f',
|
|
194
|
+
'blueviolet': '#8a2be2',
|
|
195
|
+
'brown': '#a52a2a',
|
|
196
|
+
'burlywood': '#deb887',
|
|
197
|
+
'cadetblue': '#5f9ea0',
|
|
198
|
+
'chartreuse': '#7fff00',
|
|
199
|
+
'chocolate': '#d2691e',
|
|
200
|
+
'coral': '#ff7f50',
|
|
201
|
+
'cornflowerblue': '#6495ed',
|
|
202
|
+
'cornsilk': '#fff8dc',
|
|
203
|
+
'crimson': '#dc143c',
|
|
204
|
+
'cyan': '#0ff',
|
|
205
|
+
'darkblue': '#00008b',
|
|
206
|
+
'darkcyan': '#008b8b',
|
|
207
|
+
'darkgoldenrod': '#b8860b',
|
|
208
|
+
'darkgray': '#a9a9a9',
|
|
209
|
+
'darkgreen': '#006400',
|
|
210
|
+
'darkgrey': '#a9a9a9',
|
|
211
|
+
'darkkhaki': '#bdb76b',
|
|
212
|
+
'darkmagenta': '#8b008b',
|
|
213
|
+
'darkolivegreen': '#556b2f',
|
|
214
|
+
'darkorange': '#ff8c00',
|
|
215
|
+
'darkorchid': '#9932cc',
|
|
216
|
+
'darkred': '#8b0000',
|
|
217
|
+
'darksalmon': '#e9967a',
|
|
218
|
+
'darkseagreen': '#8fbc8f',
|
|
219
|
+
'darkslateblue': '#483d8b',
|
|
220
|
+
'darkslategray': '#2f4f4f',
|
|
221
|
+
'darkslategrey': '#2f4f4f',
|
|
222
|
+
'darkturquoise': '#00ced1',
|
|
223
|
+
'darkviolet': '#9400d3',
|
|
224
|
+
'deeppink': '#ff1493',
|
|
225
|
+
'deepskyblue': '#00bfff',
|
|
226
|
+
'dimgray': '#696969',
|
|
227
|
+
'dimgrey': '#696969',
|
|
228
|
+
'dodgerblue': '#1e90ff',
|
|
229
|
+
'firebrick': '#b22222',
|
|
230
|
+
'floralwhite': '#fffaf0',
|
|
231
|
+
'forestgreen': '#228b22',
|
|
232
|
+
'fuchsia': '#f0f',
|
|
233
|
+
'gainsboro': '#dcdcdc',
|
|
234
|
+
'ghostwhite': '#f8f8ff',
|
|
235
|
+
'gold': '#ffd700',
|
|
236
|
+
'goldenrod': '#daa520',
|
|
237
|
+
'gray': '#808080',
|
|
238
|
+
'green': '#008000',
|
|
239
|
+
'greenyellow': '#adff2f',
|
|
240
|
+
'grey': '#808080',
|
|
241
|
+
'honeydew': '#f0fff0',
|
|
242
|
+
'hotpink': '#ff69b4',
|
|
243
|
+
'indianred': '#cd5c5c',
|
|
244
|
+
'indigo': '#4b0082',
|
|
245
|
+
'ivory': '#fffff0',
|
|
246
|
+
'khaki': '#f0e68c',
|
|
247
|
+
'lavender': '#e6e6fa',
|
|
248
|
+
'lavenderblush': '#fff0f5',
|
|
249
|
+
'lawngreen': '#7cfc00',
|
|
250
|
+
'lemonchiffon': '#fffacd',
|
|
251
|
+
'lightblue': '#add8e6',
|
|
252
|
+
'lightcoral': '#f08080',
|
|
253
|
+
'lightcyan': '#e0ffff',
|
|
254
|
+
'lightgoldenrodyellow': '#fafad2',
|
|
255
|
+
'lightgray': '#d3d3d3',
|
|
256
|
+
'lightgreen': '#90ee90',
|
|
257
|
+
'lightgrey': '#d3d3d3',
|
|
258
|
+
'lightpink': '#ffb6c1',
|
|
259
|
+
'lightsalmon': '#ffa07a',
|
|
260
|
+
'lightseagreen': '#20b2aa',
|
|
261
|
+
'lightskyblue': '#87cefa',
|
|
262
|
+
'lightslategray': '#789',
|
|
263
|
+
'lightslategrey': '#789',
|
|
264
|
+
'lightsteelblue': '#b0c4de',
|
|
265
|
+
'lightyellow': '#ffffe0',
|
|
266
|
+
'lime': '#0f0',
|
|
267
|
+
'limegreen': '#32cd32',
|
|
268
|
+
'linen': '#faf0e6',
|
|
269
|
+
'magenta': '#f0f',
|
|
270
|
+
'maroon': '#800000',
|
|
271
|
+
'mediumaquamarine': '#66cdaa',
|
|
272
|
+
'mediumblue': '#0000cd',
|
|
273
|
+
'mediumorchid': '#ba55d3',
|
|
274
|
+
'mediumpurple': '#9370db',
|
|
275
|
+
'mediumseagreen': '#3cb371',
|
|
276
|
+
'mediumslateblue': '#7b68ee',
|
|
277
|
+
'mediumspringgreen': '#00fa9a',
|
|
278
|
+
'mediumturquoise': '#48d1cc',
|
|
279
|
+
'mediumvioletred': '#c71585',
|
|
280
|
+
'midnightblue': '#191970',
|
|
281
|
+
'mintcream': '#f5fffa',
|
|
282
|
+
'mistyrose': '#ffe4e1',
|
|
283
|
+
'moccasin': '#ffe4b5',
|
|
284
|
+
'navajowhite': '#ffdead',
|
|
285
|
+
'navy': '#000080',
|
|
286
|
+
'oldlace': '#fdf5e6',
|
|
287
|
+
'olive': '#808000',
|
|
288
|
+
'olivedrab': '#6b8e23',
|
|
289
|
+
'orange': '#ffa500',
|
|
290
|
+
'orangered': '#ff4500',
|
|
291
|
+
'orchid': '#da70d6',
|
|
292
|
+
'palegoldenrod': '#eee8aa',
|
|
293
|
+
'palegreen': '#98fb98',
|
|
294
|
+
'paleturquoise': '#afeeee',
|
|
295
|
+
'palevioletred': '#db7093',
|
|
296
|
+
'papayawhip': '#ffefd5',
|
|
297
|
+
'peachpuff': '#ffdab9',
|
|
298
|
+
'peru': '#cd853f',
|
|
299
|
+
'pink': '#ffc0cb',
|
|
300
|
+
'plum': '#dda0dd',
|
|
301
|
+
'powderblue': '#b0e0e6',
|
|
302
|
+
'purple': '#800080',
|
|
303
|
+
'rebeccapurple': '#639',
|
|
304
|
+
'red': '#f00',
|
|
305
|
+
'rosybrown': '#bc8f8f',
|
|
306
|
+
'royalblue': '#4169e1',
|
|
307
|
+
'saddlebrown': '#8b4513',
|
|
308
|
+
'salmon': '#fa8072',
|
|
309
|
+
'sandybrown': '#f4a460',
|
|
310
|
+
'seagreen': '#2e8b57',
|
|
311
|
+
'seashell': '#fff5ee',
|
|
312
|
+
'sienna': '#a0522d',
|
|
313
|
+
'silver': '#c0c0c0',
|
|
314
|
+
'skyblue': '#87ceeb',
|
|
315
|
+
'slateblue': '#6a5acd',
|
|
316
|
+
'slategray': '#708090',
|
|
317
|
+
'slategrey': '#708090',
|
|
318
|
+
'snow': '#fffafa',
|
|
319
|
+
'springgreen': '#00ff7f',
|
|
320
|
+
'steelblue': '#4682b4',
|
|
321
|
+
'tan': '#d2b48c',
|
|
322
|
+
'teal': '#008080',
|
|
323
|
+
'thistle': '#d8bfd8',
|
|
324
|
+
'tomato': '#ff6347',
|
|
325
|
+
'turquoise': '#40e0d0',
|
|
326
|
+
'violet': '#ee82ee',
|
|
327
|
+
'wheat': '#f5deb3',
|
|
328
|
+
'white': '#fff',
|
|
329
|
+
'whitesmoke': '#f5f5f5',
|
|
330
|
+
'yellow': '#ff0',
|
|
331
|
+
'yellowgreen': '#9acd32',
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Hex values that have shorter color names
|
|
336
|
+
*/
|
|
337
|
+
export const colorsShortNames = {
|
|
338
|
+
'#f0ffff': 'azure',
|
|
339
|
+
'#f5f5dc': 'beige',
|
|
340
|
+
'#ffe4c4': 'bisque',
|
|
341
|
+
'#a52a2a': 'brown',
|
|
342
|
+
'#ff7f50': 'coral',
|
|
343
|
+
'#ffd700': 'gold',
|
|
344
|
+
'#808080': 'gray',
|
|
345
|
+
'#008000': 'green',
|
|
346
|
+
'#4b0082': 'indigo',
|
|
347
|
+
'#fffff0': 'ivory',
|
|
348
|
+
'#f0e68c': 'khaki',
|
|
349
|
+
'#faf0e6': 'linen',
|
|
350
|
+
'#800000': 'maroon',
|
|
351
|
+
'#000080': 'navy',
|
|
352
|
+
'#808000': 'olive',
|
|
353
|
+
'#ffa500': 'orange',
|
|
354
|
+
'#da70d6': 'orchid',
|
|
355
|
+
'#cd853f': 'peru',
|
|
356
|
+
'#ffc0cb': 'pink',
|
|
357
|
+
'#dda0dd': 'plum',
|
|
358
|
+
'#800080': 'purple',
|
|
359
|
+
'#f00': 'red',
|
|
360
|
+
'#fa8072': 'salmon',
|
|
361
|
+
'#a0522d': 'sienna',
|
|
362
|
+
'#c0c0c0': 'silver',
|
|
363
|
+
'#fffafa': 'snow',
|
|
364
|
+
'#d2b48c': 'tan',
|
|
365
|
+
'#008080': 'teal',
|
|
366
|
+
'#ff6347': 'tomato',
|
|
367
|
+
'#ee82ee': 'violet',
|
|
368
|
+
'#f5deb3': 'wheat',
|
|
369
|
+
'#fff': 'white',
|
|
370
|
+
'#ff0': 'yellow',
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
// ============================================================================
|
|
374
|
+
// COLOR PROPERTIES
|
|
375
|
+
// ============================================================================
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Attributes that accept color values
|
|
379
|
+
*/
|
|
380
|
+
export const colorsProps = new Set([
|
|
381
|
+
'color',
|
|
382
|
+
'fill',
|
|
383
|
+
'flood-color',
|
|
384
|
+
'lighting-color',
|
|
385
|
+
'stop-color',
|
|
386
|
+
'stroke',
|
|
387
|
+
]);
|
|
388
|
+
|
|
389
|
+
// ============================================================================
|
|
390
|
+
// ALL SVG ELEMENTS
|
|
391
|
+
// ============================================================================
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Complete list of known SVG elements
|
|
395
|
+
*/
|
|
396
|
+
export const knownElements = new Set([
|
|
397
|
+
// Structural elements
|
|
398
|
+
'svg', 'g', 'defs', 'symbol', 'use',
|
|
399
|
+
// Shape elements
|
|
400
|
+
'path', 'rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon',
|
|
401
|
+
// Text elements
|
|
402
|
+
'text', 'tspan', 'tref', 'textPath', 'altGlyph', 'altGlyphDef',
|
|
403
|
+
'altGlyphItem', 'glyph', 'glyphRef',
|
|
404
|
+
// Gradient elements
|
|
405
|
+
'linearGradient', 'radialGradient', 'meshGradient', 'stop',
|
|
406
|
+
// Container elements
|
|
407
|
+
'a', 'marker', 'mask', 'pattern', 'clipPath', 'switch',
|
|
408
|
+
// Filter elements
|
|
409
|
+
'filter', 'feBlend', 'feColorMatrix', 'feComponentTransfer',
|
|
410
|
+
'feComposite', 'feConvolveMatrix', 'feDiffuseLighting',
|
|
411
|
+
'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood',
|
|
412
|
+
'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur',
|
|
413
|
+
'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset',
|
|
414
|
+
'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile',
|
|
415
|
+
'feTurbulence',
|
|
416
|
+
// Descriptive elements
|
|
417
|
+
'title', 'desc', 'metadata',
|
|
418
|
+
// Animation elements
|
|
419
|
+
'animate', 'animateColor', 'animateMotion', 'animateTransform', 'set', 'mpath',
|
|
420
|
+
// Other elements
|
|
421
|
+
'image', 'foreignObject', 'view', 'style', 'script',
|
|
422
|
+
'solidColor', 'hatch', 'hatchpath',
|
|
423
|
+
]);
|
|
424
|
+
|
|
425
|
+
// ============================================================================
|
|
426
|
+
// DEFAULT VALUES
|
|
427
|
+
// ============================================================================
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* General presentation attribute default values
|
|
431
|
+
*/
|
|
432
|
+
export const presentationDefaults = {
|
|
433
|
+
// Fill defaults
|
|
434
|
+
'fill': '#000',
|
|
435
|
+
'fill-opacity': '1',
|
|
436
|
+
'fill-rule': 'nonzero',
|
|
437
|
+
|
|
438
|
+
// Stroke defaults
|
|
439
|
+
'stroke': 'none',
|
|
440
|
+
'stroke-width': '1',
|
|
441
|
+
'stroke-opacity': '1',
|
|
442
|
+
'stroke-linecap': 'butt',
|
|
443
|
+
'stroke-linejoin': 'miter',
|
|
444
|
+
'stroke-miterlimit': '4',
|
|
445
|
+
'stroke-dasharray': 'none',
|
|
446
|
+
'stroke-dashoffset': '0',
|
|
447
|
+
|
|
448
|
+
// Opacity/visibility defaults
|
|
449
|
+
'opacity': '1',
|
|
450
|
+
'visibility': 'visible',
|
|
451
|
+
'display': 'inline',
|
|
452
|
+
|
|
453
|
+
// Clip/mask defaults
|
|
454
|
+
'clip': 'auto',
|
|
455
|
+
'clip-path': 'none',
|
|
456
|
+
'clip-rule': 'nonzero',
|
|
457
|
+
'mask': 'none',
|
|
458
|
+
|
|
459
|
+
// Marker defaults
|
|
460
|
+
'marker-start': 'none',
|
|
461
|
+
'marker-mid': 'none',
|
|
462
|
+
'marker-end': 'none',
|
|
463
|
+
|
|
464
|
+
// Color defaults
|
|
465
|
+
'stop-color': '#000',
|
|
466
|
+
'stop-opacity': '1',
|
|
467
|
+
'flood-color': '#000',
|
|
468
|
+
'flood-opacity': '1',
|
|
469
|
+
'lighting-color': '#fff',
|
|
470
|
+
|
|
471
|
+
// Rendering defaults
|
|
472
|
+
'color-interpolation': 'sRGB',
|
|
473
|
+
'color-interpolation-filters': 'linearRGB',
|
|
474
|
+
'color-rendering': 'auto',
|
|
475
|
+
'shape-rendering': 'auto',
|
|
476
|
+
'text-rendering': 'auto',
|
|
477
|
+
'image-rendering': 'auto',
|
|
478
|
+
|
|
479
|
+
// Paint defaults
|
|
480
|
+
'paint-order': 'normal',
|
|
481
|
+
'vector-effect': 'none',
|
|
482
|
+
|
|
483
|
+
// Text defaults
|
|
484
|
+
'text-anchor': 'start',
|
|
485
|
+
'text-overflow': 'clip',
|
|
486
|
+
'text-decoration': 'none',
|
|
487
|
+
'dominant-baseline': 'auto',
|
|
488
|
+
'alignment-baseline': 'baseline',
|
|
489
|
+
'baseline-shift': 'baseline',
|
|
490
|
+
'writing-mode': 'lr-tb',
|
|
491
|
+
'direction': 'ltr',
|
|
492
|
+
'unicode-bidi': 'normal',
|
|
493
|
+
'letter-spacing': 'normal',
|
|
494
|
+
'word-spacing': 'normal',
|
|
495
|
+
|
|
496
|
+
// Font defaults
|
|
497
|
+
'font-style': 'normal',
|
|
498
|
+
'font-variant': 'normal',
|
|
499
|
+
'font-weight': 'normal',
|
|
500
|
+
'font-stretch': 'normal',
|
|
501
|
+
'font-size': 'medium',
|
|
502
|
+
'font-size-adjust': 'none',
|
|
503
|
+
|
|
504
|
+
// Deprecated but still present
|
|
505
|
+
'glyph-orientation-vertical': 'auto',
|
|
506
|
+
'glyph-orientation-horizontal': '0deg',
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Element-specific default values
|
|
511
|
+
*/
|
|
512
|
+
export const elementDefaults = {
|
|
513
|
+
'circle': { 'cx': '0', 'cy': '0' },
|
|
514
|
+
'ellipse': { 'cx': '0', 'cy': '0' },
|
|
515
|
+
'line': { 'x1': '0', 'y1': '0', 'x2': '0', 'y2': '0' },
|
|
516
|
+
'rect': { 'x': '0', 'y': '0', 'rx': '0', 'ry': '0' },
|
|
517
|
+
'image': { 'x': '0', 'y': '0', 'preserveAspectRatio': 'xMidYMid meet' },
|
|
518
|
+
'svg': { 'x': '0', 'y': '0', 'preserveAspectRatio': 'xMidYMid meet' },
|
|
519
|
+
'symbol': { 'preserveAspectRatio': 'xMidYMid meet' },
|
|
520
|
+
'marker': {
|
|
521
|
+
'markerUnits': 'strokeWidth',
|
|
522
|
+
'refX': '0', 'refY': '0',
|
|
523
|
+
'markerWidth': '3', 'markerHeight': '3'
|
|
524
|
+
},
|
|
525
|
+
'linearGradient': {
|
|
526
|
+
'x1': '0', 'y1': '0', 'x2': '100%', 'y2': '0',
|
|
527
|
+
'spreadMethod': 'pad'
|
|
528
|
+
},
|
|
529
|
+
'radialGradient': {
|
|
530
|
+
'cx': '50%', 'cy': '50%', 'r': '50%',
|
|
531
|
+
// Note: fx and fy default to cx and cy values respectively per SVG spec,
|
|
532
|
+
// but this cannot be expressed in static defaults. Omitted to avoid incorrect values.
|
|
533
|
+
'spreadMethod': 'pad'
|
|
534
|
+
},
|
|
535
|
+
'pattern': {
|
|
536
|
+
'x': '0', 'y': '0',
|
|
537
|
+
'patternUnits': 'objectBoundingBox',
|
|
538
|
+
'patternContentUnits': 'userSpaceOnUse'
|
|
539
|
+
},
|
|
540
|
+
'clipPath': { 'clipPathUnits': 'userSpaceOnUse' },
|
|
541
|
+
'mask': {
|
|
542
|
+
'maskUnits': 'objectBoundingBox',
|
|
543
|
+
'maskContentUnits': 'userSpaceOnUse',
|
|
544
|
+
'x': '-10%', 'y': '-10%', 'width': '120%', 'height': '120%'
|
|
545
|
+
},
|
|
546
|
+
'filter': {
|
|
547
|
+
'primitiveUnits': 'objectBoundingBox',
|
|
548
|
+
'x': '-10%', 'y': '-10%', 'width': '120%', 'height': '120%'
|
|
549
|
+
},
|
|
550
|
+
'feBlend': { 'mode': 'normal' },
|
|
551
|
+
'feColorMatrix': { 'type': 'matrix' },
|
|
552
|
+
'feComposite': { 'operator': 'over', 'k1': '0', 'k2': '0', 'k3': '0', 'k4': '0' },
|
|
553
|
+
'feConvolveMatrix': { 'order': '3', 'bias': '0', 'edgeMode': 'duplicate', 'preserveAlpha': 'false' },
|
|
554
|
+
'feDisplacementMap': { 'scale': '0', 'xChannelSelector': 'A', 'yChannelSelector': 'A' },
|
|
555
|
+
'feDistantLight': { 'azimuth': '0', 'elevation': '0' },
|
|
556
|
+
'fePointLight': { 'x': '0', 'y': '0', 'z': '0' },
|
|
557
|
+
'feSpotLight': {
|
|
558
|
+
'x': '0', 'y': '0', 'z': '0',
|
|
559
|
+
'pointsAtX': '0', 'pointsAtY': '0', 'pointsAtZ': '0',
|
|
560
|
+
'specularExponent': '1'
|
|
561
|
+
},
|
|
562
|
+
'feTurbulence': {
|
|
563
|
+
'baseFrequency': '0', 'numOctaves': '1', 'seed': '0',
|
|
564
|
+
'stitchTiles': 'noStitch', 'type': 'turbulence'
|
|
565
|
+
},
|
|
566
|
+
'feFuncR': { 'type': 'identity', 'slope': '1', 'intercept': '0', 'amplitude': '1', 'exponent': '1', 'offset': '0' },
|
|
567
|
+
'feFuncG': { 'type': 'identity', 'slope': '1', 'intercept': '0', 'amplitude': '1', 'exponent': '1', 'offset': '0' },
|
|
568
|
+
'feFuncB': { 'type': 'identity', 'slope': '1', 'intercept': '0', 'amplitude': '1', 'exponent': '1', 'offset': '0' },
|
|
569
|
+
'feFuncA': { 'type': 'identity', 'slope': '1', 'intercept': '0', 'amplitude': '1', 'exponent': '1', 'offset': '0' },
|
|
570
|
+
'a': { 'target': '_self' },
|
|
571
|
+
'textPath': { 'startOffset': '0' },
|
|
572
|
+
'animate': { 'begin': '0s' },
|
|
573
|
+
'animateMotion': { 'rotate': '0' },
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
// ============================================================================
|
|
577
|
+
// ELEMENT-SPECIFIC SETS (P4 Edge Cases)
|
|
578
|
+
// ============================================================================
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Text-related elements that can contain text content
|
|
582
|
+
*/
|
|
583
|
+
export const textElems = new Set([
|
|
584
|
+
'altGlyph', 'textPath', 'tref', 'tspan', 'text', 'title', 'desc'
|
|
585
|
+
]);
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Elements that can contain path data
|
|
589
|
+
*/
|
|
590
|
+
export const pathElems = new Set([
|
|
591
|
+
'glyph', 'missing-glyph', 'path'
|
|
592
|
+
]);
|
|
593
|
+
|
|
594
|
+
// ============================================================================
|
|
595
|
+
// ATTRIBUTE GROUPS (P4-4: 15 SVGO-compatible attribute groups)
|
|
596
|
+
// ============================================================================
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Complete attribute groups matching SVGO's _collections.js
|
|
600
|
+
*/
|
|
601
|
+
export const attrsGroups = {
|
|
602
|
+
animationAddition: new Set([
|
|
603
|
+
'additive', 'accumulate'
|
|
604
|
+
]),
|
|
605
|
+
animationAttributeTarget: new Set([
|
|
606
|
+
'attributeType', 'attributeName'
|
|
607
|
+
]),
|
|
608
|
+
animationEvent: new Set([
|
|
609
|
+
'onbegin', 'onend', 'onrepeat', 'onload'
|
|
610
|
+
]),
|
|
611
|
+
animationTiming: new Set([
|
|
612
|
+
'begin', 'dur', 'end', 'min', 'max', 'restart', 'repeatCount', 'repeatDur', 'fill'
|
|
613
|
+
]),
|
|
614
|
+
animationValue: new Set([
|
|
615
|
+
'calcMode', 'values', 'keyTimes', 'keySplines', 'from', 'to', 'by'
|
|
616
|
+
]),
|
|
617
|
+
conditionalProcessing: new Set([
|
|
618
|
+
'requiredFeatures', 'requiredExtensions', 'systemLanguage'
|
|
619
|
+
]),
|
|
620
|
+
core: new Set([
|
|
621
|
+
'id', 'tabindex', 'xml:base', 'xml:lang', 'xml:space', 'lang'
|
|
622
|
+
]),
|
|
623
|
+
graphicalEvent: new Set([
|
|
624
|
+
'onfocusin', 'onfocusout', 'onactivate', 'onclick', 'onmousedown',
|
|
625
|
+
'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onload'
|
|
626
|
+
]),
|
|
627
|
+
presentation: new Set([
|
|
628
|
+
'alignment-baseline', 'baseline-shift', 'clip', 'clip-path', 'clip-rule',
|
|
629
|
+
'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile',
|
|
630
|
+
'color-rendering', 'cursor', 'direction', 'display', 'dominant-baseline',
|
|
631
|
+
'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter',
|
|
632
|
+
'flood-color', 'flood-opacity', 'font', 'font-family', 'font-size',
|
|
633
|
+
'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight',
|
|
634
|
+
'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering',
|
|
635
|
+
'kerning', 'letter-spacing', 'lighting-color', 'marker', 'marker-end',
|
|
636
|
+
'marker-mid', 'marker-start', 'mask', 'opacity', 'overflow', 'paint-order',
|
|
637
|
+
'pointer-events', 'shape-rendering', 'stop-color', 'stop-opacity', 'stroke',
|
|
638
|
+
'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin',
|
|
639
|
+
'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor',
|
|
640
|
+
'text-decoration', 'text-rendering', 'transform', 'transform-origin',
|
|
641
|
+
'unicode-bidi', 'vector-effect', 'visibility', 'word-spacing', 'writing-mode'
|
|
642
|
+
]),
|
|
643
|
+
xlink: new Set([
|
|
644
|
+
'xlink:href', 'xlink:show', 'xlink:actuate', 'xlink:type', 'xlink:role',
|
|
645
|
+
'xlink:arcrole', 'xlink:title'
|
|
646
|
+
]),
|
|
647
|
+
documentEvent: new Set([
|
|
648
|
+
'onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onzoom'
|
|
649
|
+
]),
|
|
650
|
+
documentElementEvent: new Set([
|
|
651
|
+
'oncopy', 'oncut', 'onpaste'
|
|
652
|
+
]),
|
|
653
|
+
globalEvent: new Set([
|
|
654
|
+
'oncancel', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose',
|
|
655
|
+
'oncuechange', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave',
|
|
656
|
+
'ondragover', 'ondragstart', 'ondrop', 'ondurationchange', 'onemptied', 'onended',
|
|
657
|
+
'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress', 'onkeyup',
|
|
658
|
+
'onload', 'onloadeddata', 'onloadedmetadata', 'onloadstart', 'onmousedown',
|
|
659
|
+
'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover',
|
|
660
|
+
'onmouseup', 'onmousewheel', 'onpause', 'onplay', 'onplaying', 'onprogress',
|
|
661
|
+
'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked', 'onseeking',
|
|
662
|
+
'onselect', 'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate',
|
|
663
|
+
'ontoggle', 'onvolumechange', 'onwaiting'
|
|
664
|
+
]),
|
|
665
|
+
filterPrimitive: new Set([
|
|
666
|
+
'x', 'y', 'width', 'height', 'result'
|
|
667
|
+
]),
|
|
668
|
+
transferFunction: new Set([
|
|
669
|
+
'type', 'tableValues', 'slope', 'intercept', 'amplitude', 'exponent', 'offset'
|
|
670
|
+
]),
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
// ============================================================================
|
|
674
|
+
// DEPRECATED ATTRIBUTES (P4-5)
|
|
675
|
+
// ============================================================================
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Deprecated attributes per group - used for warnings or removal
|
|
679
|
+
*/
|
|
680
|
+
export const attrsGroupsDeprecated = {
|
|
681
|
+
presentation: new Set([
|
|
682
|
+
'enable-background', 'glyph-orientation-horizontal', 'glyph-orientation-vertical',
|
|
683
|
+
'kerning', 'clip'
|
|
684
|
+
]),
|
|
685
|
+
xlink: new Set([
|
|
686
|
+
'xlink:type', 'xlink:role', 'xlink:arcrole', 'xlink:title', 'xlink:show', 'xlink:actuate'
|
|
687
|
+
]),
|
|
688
|
+
core: new Set([
|
|
689
|
+
'xml:base', 'xml:lang', 'xml:space'
|
|
690
|
+
]),
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// ============================================================================
|
|
694
|
+
// PARENT-CHILD VALIDATION (P4-1: allowedChildrenPerElement)
|
|
695
|
+
// ============================================================================
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Defines which child elements are allowed for each SVG element
|
|
699
|
+
* Used for validation and removing invalid children
|
|
700
|
+
*/
|
|
701
|
+
export const allowedChildrenPerElement = {
|
|
702
|
+
'svg': new Set([
|
|
703
|
+
'a', 'altGlyphDef', 'animate', 'animateColor', 'animateMotion', 'animateTransform',
|
|
704
|
+
'circle', 'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face',
|
|
705
|
+
'foreignObject', 'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata',
|
|
706
|
+
'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script',
|
|
707
|
+
'set', 'style', 'svg', 'switch', 'symbol', 'text', 'title', 'use', 'view'
|
|
708
|
+
]),
|
|
709
|
+
'g': new Set([
|
|
710
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
711
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
712
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
713
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
714
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use'
|
|
715
|
+
]),
|
|
716
|
+
'defs': new Set([
|
|
717
|
+
'a', 'altGlyphDef', 'animate', 'animateColor', 'animateMotion', 'animateTransform',
|
|
718
|
+
'circle', 'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face',
|
|
719
|
+
'foreignObject', 'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata',
|
|
720
|
+
'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script',
|
|
721
|
+
'set', 'style', 'svg', 'switch', 'symbol', 'text', 'title', 'use', 'view'
|
|
722
|
+
]),
|
|
723
|
+
'symbol': new Set([
|
|
724
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
725
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
726
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
727
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
728
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use'
|
|
729
|
+
]),
|
|
730
|
+
'marker': new Set([
|
|
731
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
732
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
733
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
734
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
735
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use'
|
|
736
|
+
]),
|
|
737
|
+
'clipPath': new Set([
|
|
738
|
+
'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle', 'desc',
|
|
739
|
+
'ellipse', 'line', 'metadata', 'path', 'polygon', 'polyline', 'rect', 'set', 'text',
|
|
740
|
+
'title', 'use'
|
|
741
|
+
]),
|
|
742
|
+
'mask': new Set([
|
|
743
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
744
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
745
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
746
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
747
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use'
|
|
748
|
+
]),
|
|
749
|
+
'pattern': new Set([
|
|
750
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
751
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
752
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
753
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
754
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use'
|
|
755
|
+
]),
|
|
756
|
+
'a': new Set([
|
|
757
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
758
|
+
'clipPath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'font-face', 'foreignObject',
|
|
759
|
+
'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'path',
|
|
760
|
+
'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'script', 'set', 'style',
|
|
761
|
+
'svg', 'switch', 'symbol', 'text', 'title', 'use', 'view'
|
|
762
|
+
]),
|
|
763
|
+
'switch': new Set([
|
|
764
|
+
'a', 'animate', 'animateColor', 'animateMotion', 'animateTransform', 'circle',
|
|
765
|
+
'desc', 'ellipse', 'foreignObject', 'g', 'image', 'line', 'metadata', 'path',
|
|
766
|
+
'polygon', 'polyline', 'rect', 'set', 'svg', 'switch', 'text', 'title', 'use'
|
|
767
|
+
]),
|
|
768
|
+
'text': new Set([
|
|
769
|
+
'a', 'altGlyph', 'animate', 'animateColor', 'animateMotion', 'animateTransform',
|
|
770
|
+
'desc', 'metadata', 'set', 'textPath', 'title', 'tref', 'tspan'
|
|
771
|
+
]),
|
|
772
|
+
'textPath': new Set([
|
|
773
|
+
'a', 'altGlyph', 'animate', 'animateColor', 'desc', 'metadata', 'set', 'title', 'tref', 'tspan'
|
|
774
|
+
]),
|
|
775
|
+
'tspan': new Set([
|
|
776
|
+
'a', 'altGlyph', 'animate', 'animateColor', 'desc', 'metadata', 'set', 'title', 'tref', 'tspan'
|
|
777
|
+
]),
|
|
778
|
+
'linearGradient': new Set([
|
|
779
|
+
'animate', 'animateTransform', 'desc', 'metadata', 'set', 'stop', 'title'
|
|
780
|
+
]),
|
|
781
|
+
'radialGradient': new Set([
|
|
782
|
+
'animate', 'animateTransform', 'desc', 'metadata', 'set', 'stop', 'title'
|
|
783
|
+
]),
|
|
784
|
+
'filter': new Set([
|
|
785
|
+
'animate', 'animateTransform', 'desc', 'feBlend', 'feColorMatrix', 'feComponentTransfer',
|
|
786
|
+
'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap',
|
|
787
|
+
'feDropShadow', 'feFlood', 'feGaussianBlur', 'feImage', 'feMerge', 'feMorphology',
|
|
788
|
+
'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence', 'metadata', 'set', 'title'
|
|
789
|
+
]),
|
|
790
|
+
'feBlend': new Set(['animate', 'set']),
|
|
791
|
+
'feColorMatrix': new Set(['animate', 'set']),
|
|
792
|
+
'feComponentTransfer': new Set(['feFuncA', 'feFuncB', 'feFuncG', 'feFuncR']),
|
|
793
|
+
'feComposite': new Set(['animate', 'set']),
|
|
794
|
+
'feConvolveMatrix': new Set(['animate', 'set']),
|
|
795
|
+
'feDiffuseLighting': new Set(['animate', 'feDistantLight', 'fePointLight', 'feSpotLight', 'set']),
|
|
796
|
+
'feDisplacementMap': new Set(['animate', 'set']),
|
|
797
|
+
'feDropShadow': new Set(['animate', 'set']),
|
|
798
|
+
'feFlood': new Set(['animate', 'set']),
|
|
799
|
+
'feFuncA': new Set(['animate', 'set']),
|
|
800
|
+
'feFuncB': new Set(['animate', 'set']),
|
|
801
|
+
'feFuncG': new Set(['animate', 'set']),
|
|
802
|
+
'feFuncR': new Set(['animate', 'set']),
|
|
803
|
+
'feGaussianBlur': new Set(['animate', 'set']),
|
|
804
|
+
'feImage': new Set(['animate', 'set']),
|
|
805
|
+
'feMerge': new Set(['feMergeNode']),
|
|
806
|
+
'feMergeNode': new Set(['animate', 'set']),
|
|
807
|
+
'feMorphology': new Set(['animate', 'set']),
|
|
808
|
+
'feOffset': new Set(['animate', 'set']),
|
|
809
|
+
'feSpecularLighting': new Set(['animate', 'feDistantLight', 'fePointLight', 'feSpotLight', 'set']),
|
|
810
|
+
'feTile': new Set(['animate', 'set']),
|
|
811
|
+
'feTurbulence': new Set(['animate', 'set']),
|
|
812
|
+
'animate': new Set(['desc', 'metadata', 'title']),
|
|
813
|
+
'animateColor': new Set(['desc', 'metadata', 'title']),
|
|
814
|
+
'animateMotion': new Set(['desc', 'metadata', 'mpath', 'title']),
|
|
815
|
+
'animateTransform': new Set(['desc', 'metadata', 'title']),
|
|
816
|
+
'set': new Set(['desc', 'metadata', 'title']),
|
|
817
|
+
// Shape elements cannot have children (except animation)
|
|
818
|
+
'circle': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
819
|
+
'ellipse': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
820
|
+
'line': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
821
|
+
'path': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
822
|
+
'polygon': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
823
|
+
'polyline': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
824
|
+
'rect': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
825
|
+
'image': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
826
|
+
'use': new Set(['animate', 'animateColor', 'animateMotion', 'animateTransform', 'desc', 'metadata', 'set', 'title']),
|
|
827
|
+
// Descriptive elements have no children
|
|
828
|
+
'title': new Set([]),
|
|
829
|
+
'desc': new Set([]),
|
|
830
|
+
'metadata': new Set([]), // Can have any XML content, but SVG-wise empty
|
|
831
|
+
// Light source elements
|
|
832
|
+
'feDistantLight': new Set(['animate', 'set']),
|
|
833
|
+
'fePointLight': new Set(['animate', 'set']),
|
|
834
|
+
'feSpotLight': new Set(['animate', 'set']),
|
|
835
|
+
// Stop element
|
|
836
|
+
'stop': new Set(['animate', 'set']),
|
|
837
|
+
// Other elements
|
|
838
|
+
'foreignObject': new Set([]), // Can contain any non-SVG content
|
|
839
|
+
'style': new Set([]),
|
|
840
|
+
'script': new Set([]),
|
|
841
|
+
'view': new Set(['desc', 'metadata', 'title']),
|
|
842
|
+
'mpath': new Set(['desc', 'metadata', 'title']),
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
// ============================================================================
|
|
846
|
+
// CSS PSEUDO-CLASSES (P4 Edge Case: inlineStyles support)
|
|
847
|
+
// ============================================================================
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* CSS pseudo-classes that cannot be evaluated server-side
|
|
851
|
+
* (must be preserved in stylesheets)
|
|
852
|
+
*/
|
|
853
|
+
export const pseudoClasses = {
|
|
854
|
+
// User action pseudo-classes - cannot be evaluated
|
|
855
|
+
userAction: new Set([
|
|
856
|
+
':hover', ':active', ':focus', ':focus-within', ':focus-visible'
|
|
857
|
+
]),
|
|
858
|
+
// Tree-structural pseudo-classes - can sometimes be evaluated
|
|
859
|
+
treeStructural: new Set([
|
|
860
|
+
':root', ':empty', ':first-child', ':last-child', ':only-child',
|
|
861
|
+
':first-of-type', ':last-of-type', ':only-of-type',
|
|
862
|
+
':nth-child', ':nth-last-child', ':nth-of-type', ':nth-last-of-type'
|
|
863
|
+
]),
|
|
864
|
+
// Link pseudo-classes
|
|
865
|
+
link: new Set([
|
|
866
|
+
':link', ':visited', ':any-link', ':local-link', ':target'
|
|
867
|
+
]),
|
|
868
|
+
// Input pseudo-classes
|
|
869
|
+
input: new Set([
|
|
870
|
+
':enabled', ':disabled', ':read-only', ':read-write', ':placeholder-shown',
|
|
871
|
+
':default', ':checked', ':indeterminate', ':valid', ':invalid', ':in-range',
|
|
872
|
+
':out-of-range', ':required', ':optional'
|
|
873
|
+
]),
|
|
874
|
+
// Linguistic pseudo-classes
|
|
875
|
+
linguistic: new Set([
|
|
876
|
+
':lang', ':dir'
|
|
877
|
+
]),
|
|
878
|
+
// Negation and matching
|
|
879
|
+
functional: new Set([
|
|
880
|
+
':not', ':is', ':where', ':has'
|
|
881
|
+
]),
|
|
882
|
+
// All pseudo-classes that prevent inlining
|
|
883
|
+
preventInlining: new Set([
|
|
884
|
+
':hover', ':active', ':focus', ':focus-within', ':focus-visible',
|
|
885
|
+
':visited', ':target', ':lang', ':dir', ':not', ':is', ':where', ':has'
|
|
886
|
+
])
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// ============================================================================
|
|
890
|
+
// EXPANDED EDITOR NAMESPACES
|
|
891
|
+
// ============================================================================
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Additional editor namespaces beyond the base set
|
|
895
|
+
*/
|
|
896
|
+
export const additionalEditorNamespaces = new Set([
|
|
897
|
+
// CorelDraw
|
|
898
|
+
'http://www.corel.com/coreldraw/svg',
|
|
899
|
+
// Gravit Designer
|
|
900
|
+
'http://gravit.io/ns',
|
|
901
|
+
// Affinity
|
|
902
|
+
'http://serif.com/affinity',
|
|
903
|
+
// Canva
|
|
904
|
+
'http://canva.com/ns',
|
|
905
|
+
]);
|
|
906
|
+
|
|
907
|
+
// Merge additional namespaces into main set at initialization (avoid post-export mutation)
|
|
908
|
+
for (const ns of additionalEditorNamespaces) {
|
|
909
|
+
editorNamespaces.add(ns);
|
|
910
|
+
}
|