@emasoft/svg-matrix 1.0.22 → 1.0.23

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/bin/svgm.js CHANGED
@@ -79,65 +79,95 @@ function logError(msg) {
79
79
  }
80
80
 
81
81
  // ============================================================================
82
- // AVAILABLE OPTIMIZATIONS (like SVGO plugins)
82
+ // AVAILABLE OPTIMIZATIONS (matching SVGO plugins)
83
83
  // ============================================================================
84
84
  const OPTIMIZATIONS = [
85
+ // Cleanup plugins
86
+ { name: 'cleanupAttributes', description: 'Remove useless attributes' },
85
87
  { name: 'cleanupIds', description: 'Remove unused and minify used IDs' },
86
- { name: 'cleanupNumericValues', description: 'Round numeric values, remove default values' },
88
+ { name: 'cleanupNumericValues', description: 'Round numeric values, remove default px units' },
87
89
  { name: 'cleanupListOfValues', description: 'Round list of numeric values' },
88
- { name: 'cleanupAttributes', description: 'Remove unnecessary attributes' },
90
+ { name: 'cleanupEnableBackground', description: 'Remove or fix enable-background attribute' },
91
+ // Remove plugins
89
92
  { name: 'removeDoctype', description: 'Remove DOCTYPE declaration' },
90
93
  { name: 'removeXMLProcInst', description: 'Remove XML processing instructions' },
91
94
  { name: 'removeComments', description: 'Remove comments' },
92
95
  { name: 'removeMetadata', description: 'Remove <metadata> elements' },
93
- { name: 'removeTitle', description: 'Remove <title> elements' },
96
+ { name: 'removeTitle', description: 'Remove <title> elements (not in default)' },
94
97
  { name: 'removeDesc', description: 'Remove <desc> elements' },
95
- { name: 'removeEditorsNSData', description: 'Remove editor namespaces and data' },
98
+ { name: 'removeEditorsNSData', description: 'Remove editor namespaces, elements, and attributes' },
96
99
  { name: 'removeEmptyAttrs', description: 'Remove empty attributes' },
97
- { name: 'removeEmptyContainers', description: 'Remove empty containers' },
100
+ { name: 'removeEmptyContainers', description: 'Remove empty container elements' },
98
101
  { name: 'removeEmptyText', description: 'Remove empty text elements' },
99
102
  { name: 'removeHiddenElements', description: 'Remove hidden elements' },
100
103
  { name: 'removeUselessDefs', description: 'Remove unused <defs> content' },
101
- { name: 'removeUnknownsAndDefaults', description: 'Remove unknown elements and default attributes' },
102
- { name: 'convertShapesToPath', description: 'Convert shapes to paths' },
103
- { name: 'convertPathData', description: 'Optimize path data' },
104
- { name: 'convertTransform', description: 'Collapse multiple transforms' },
104
+ { name: 'removeUnknownsAndDefaults', description: 'Remove unknown elements and default attribute values' },
105
+ { name: 'removeNonInheritableGroupAttrs', description: 'Remove non-inheritable presentation attributes from groups' },
106
+ // Convert plugins
107
+ { name: 'convertShapesToPath', description: 'Convert basic shapes to paths' },
108
+ { name: 'convertPathData', description: 'Optimize path data: convert, remove useless, etc.' },
109
+ { name: 'convertTransform', description: 'Collapse multiple transforms into one, convert matrices' },
105
110
  { name: 'convertColors', description: 'Convert color values to shorter form' },
106
- { name: 'convertStyleToAttrs', description: 'Convert style to attributes' },
107
- { name: 'convertEllipseToCircle', description: 'Convert ellipse to circle when rx=ry' },
111
+ { name: 'convertStyleToAttrs', description: 'Convert style to presentation attributes (not in default)' },
112
+ { name: 'convertEllipseToCircle', description: 'Convert ellipse to circle when rx equals ry' },
113
+ // Structure plugins
108
114
  { name: 'collapseGroups', description: 'Collapse useless groups' },
109
115
  { name: 'mergePaths', description: 'Merge multiple paths into one' },
110
- { name: 'moveGroupAttrsToElems', description: 'Move group attributes to elements' },
111
- { name: 'moveElemsAttrsToGroup', description: 'Move common element attributes to group' },
112
- { name: 'minifyStyles', description: 'Minify <style> content' },
113
- { name: 'inlineStyles', description: 'Inline styles from <style>' },
114
- { name: 'sortAttrs', description: 'Sort attributes for better compression' },
115
- { name: 'sortDefsChildren', description: 'Sort <defs> children for better compression' },
116
+ { name: 'moveGroupAttrsToElems', description: 'Move group attributes to contained elements' },
117
+ { name: 'moveElemsAttrsToGroup', description: 'Move common element attributes to parent group' },
118
+ // Style plugins
119
+ { name: 'minifyStyles', description: 'Minify <style> elements content' },
120
+ { name: 'inlineStyles', description: 'Inline styles from <style> to element style attributes' },
121
+ // Sort plugins
122
+ { name: 'sortAttrs', description: 'Sort attributes for better gzip compression' },
123
+ { name: 'sortDefsChildren', description: 'Sort children of <defs> for better gzip compression' },
116
124
  ];
117
125
 
118
- // Default optimization pipeline (matches SVGO defaults)
126
+ // ============================================================================
127
+ // DEFAULT PIPELINE - Matches SVGO preset-default exactly (34 plugins)
128
+ // Order matters! This is the exact order from SVGO's preset-default.js
129
+ // ============================================================================
119
130
  const DEFAULT_PIPELINE = [
131
+ // 1-6: Initial cleanup (matching SVGO preset-default order)
120
132
  'removeDoctype',
121
133
  'removeXMLProcInst',
122
134
  'removeComments',
135
+ // removeDeprecatedAttrs - not implemented (rarely needed)
123
136
  'removeMetadata',
124
137
  'removeEditorsNSData',
138
+ // 7-11: Style processing
125
139
  'cleanupAttributes',
140
+ // mergeStyles - not implemented
141
+ 'inlineStyles',
142
+ 'minifyStyles',
143
+ 'cleanupIds',
144
+ // 12-18: Remove unnecessary elements
145
+ 'removeUselessDefs',
126
146
  'cleanupNumericValues',
127
147
  'convertColors',
128
148
  'removeUnknownsAndDefaults',
129
- 'removeEmptyAttrs',
130
- 'removeEmptyContainers',
131
- 'removeEmptyText',
149
+ 'removeNonInheritableGroupAttrs',
150
+ // removeUselessStrokeAndFill - not implemented
151
+ 'cleanupEnableBackground',
132
152
  'removeHiddenElements',
133
- 'removeUselessDefs',
134
- 'convertShapesToPath',
153
+ 'removeEmptyText',
154
+ // 19-27: Convert and optimize
155
+ // NOTE: convertShapesToPath removed - SVGO only converts when it saves bytes
156
+ // Our version converts all shapes which often increases size
157
+ 'convertEllipseToCircle',
158
+ 'moveElemsAttrsToGroup',
159
+ 'moveGroupAttrsToElems',
160
+ 'collapseGroups',
135
161
  'convertPathData',
136
162
  'convertTransform',
137
- 'collapseGroups',
163
+ // 28-34: Final cleanup
164
+ 'removeEmptyAttrs',
165
+ 'removeEmptyContainers',
138
166
  'mergePaths',
167
+ // removeUnusedNS - not implemented
139
168
  'sortAttrs',
140
- 'cleanupIds',
169
+ 'sortDefsChildren',
170
+ 'removeDesc',
141
171
  ];
142
172
 
143
173
  // ============================================================================
@@ -215,9 +245,11 @@ async function optimizeSvg(content, options = {}) {
215
245
 
216
246
  let result = serializeSVG(doc);
217
247
 
218
- // Pretty print if requested
248
+ // Pretty print if requested, otherwise minify (SVGO default behavior)
219
249
  if (options.pretty) {
220
250
  result = prettifyXml(result, options.indent);
251
+ } else {
252
+ result = minifyXml(result);
221
253
  }
222
254
 
223
255
  // Handle EOL
@@ -233,6 +265,22 @@ async function optimizeSvg(content, options = {}) {
233
265
  return result;
234
266
  }
235
267
 
268
+ /**
269
+ * Minify XML output (matching SVGO behavior)
270
+ * - Remove XML declaration
271
+ * - Remove whitespace between tags
272
+ * - Collapse multiple spaces
273
+ */
274
+ function minifyXml(xml) {
275
+ return xml
276
+ // Remove XML declaration (SVGO removes it by default)
277
+ .replace(/<\?xml[^?]*\?>\s*/gi, '')
278
+ // Remove newlines and collapse whitespace between tags
279
+ .replace(/>\s+</g, '><')
280
+ // Remove leading/trailing whitespace
281
+ .trim();
282
+ }
283
+
236
284
  function prettifyXml(xml, indent = 2) {
237
285
  // Simple XML prettifier
238
286
  const indentStr = ' '.repeat(indent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emasoft/svg-matrix",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "Arbitrary-precision matrix, vector and affine transformation library for JavaScript using decimal.js",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * SVG path conversion, and 2D/3D affine transformations using Decimal.js.
6
6
  *
7
7
  * @module @emasoft/svg-matrix
8
- * @version 1.0.22
8
+ * @version 1.0.23
9
9
  * @license MIT
10
10
  *
11
11
  * @example
@@ -86,7 +86,7 @@ Decimal.set({ precision: 80 });
86
86
  * Library version
87
87
  * @constant {string}
88
88
  */
89
- export const VERSION = '1.0.22';
89
+ export const VERSION = '1.0.23';
90
90
 
91
91
  /**
92
92
  * Default precision for path output (decimal places)