svg-toolbox 1.1.11 → 1.2.0

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.
Files changed (181) hide show
  1. package/README.md +156 -118
  2. package/es/analyze/__tests__/colors.test.d.ts +1 -0
  3. package/es/analyze/__tests__/colors.test.js +44 -0
  4. package/es/analyze/__tests__/colors.test.js.map +1 -0
  5. package/es/analyze/__tests__/paths.test.d.ts +1 -0
  6. package/es/analyze/__tests__/paths.test.js +71 -0
  7. package/es/analyze/__tests__/paths.test.js.map +1 -0
  8. package/es/analyze/colors.d.ts +8 -0
  9. package/es/analyze/colors.js +55 -0
  10. package/es/analyze/colors.js.map +1 -0
  11. package/es/analyze/paths.d.ts +20 -0
  12. package/es/analyze/paths.js +92 -0
  13. package/es/analyze/paths.js.map +1 -0
  14. package/es/compare/__tests__/diff.test.d.ts +1 -0
  15. package/es/compare/__tests__/diff.test.js +64 -0
  16. package/es/compare/__tests__/diff.test.js.map +1 -0
  17. package/es/compare/diff.d.ts +18 -0
  18. package/es/compare/diff.js +70 -0
  19. package/es/compare/diff.js.map +1 -0
  20. package/es/convert/__tests__/base64.test.d.ts +1 -0
  21. package/es/convert/__tests__/base64.test.js +49 -0
  22. package/es/convert/__tests__/base64.test.js.map +1 -0
  23. package/es/convert/base64.d.ts +11 -0
  24. package/es/convert/base64.js +38 -0
  25. package/es/convert/base64.js.map +1 -0
  26. package/es/convert/image.d.ts +18 -0
  27. package/es/convert/image.js +63 -0
  28. package/es/convert/image.js.map +1 -0
  29. package/es/core/__tests__/dimensions.test.d.ts +1 -0
  30. package/es/core/__tests__/dimensions.test.js +40 -0
  31. package/es/core/__tests__/dimensions.test.js.map +1 -0
  32. package/es/core/__tests__/element.test.d.ts +1 -0
  33. package/es/core/__tests__/element.test.js +79 -0
  34. package/es/core/__tests__/element.test.js.map +1 -0
  35. package/es/core/dimensions.d.ts +8 -0
  36. package/es/core/dimensions.js +34 -0
  37. package/es/core/dimensions.js.map +1 -0
  38. package/es/core/element.d.ts +24 -0
  39. package/es/core/element.js +52 -0
  40. package/es/core/element.js.map +1 -0
  41. package/es/index.d.ts +15 -10
  42. package/es/index.js +21 -10
  43. package/es/index.js.map +1 -1
  44. package/es/optimize/__tests__/cleanup.test.d.ts +1 -0
  45. package/es/optimize/__tests__/cleanup.test.js +95 -0
  46. package/es/optimize/__tests__/cleanup.test.js.map +1 -0
  47. package/es/optimize/__tests__/path.test.d.ts +1 -0
  48. package/es/optimize/__tests__/path.test.js +41 -0
  49. package/es/optimize/__tests__/path.test.js.map +1 -0
  50. package/es/optimize/cleanup.d.ts +27 -0
  51. package/es/optimize/cleanup.js +100 -0
  52. package/es/optimize/cleanup.js.map +1 -0
  53. package/es/optimize/path.d.ts +7 -0
  54. package/es/optimize/path.js +58 -0
  55. package/es/optimize/path.js.map +1 -0
  56. package/es/types/index.d.ts +31 -0
  57. package/es/types/index.js +5 -0
  58. package/es/types/index.js.map +1 -0
  59. package/es/utils/__tests__/path-validation.test.d.ts +1 -0
  60. package/es/utils/__tests__/path-validation.test.js +64 -0
  61. package/es/utils/__tests__/path-validation.test.js.map +1 -0
  62. package/es/utils/__tests__/validation.test.d.ts +1 -0
  63. package/es/utils/__tests__/validation.test.js +42 -0
  64. package/es/utils/__tests__/validation.test.js.map +1 -0
  65. package/es/utils/dom.d.ts +23 -0
  66. package/es/utils/dom.js +25 -0
  67. package/es/utils/dom.js.map +1 -0
  68. package/es/utils/path-validation.d.ts +29 -0
  69. package/es/utils/path-validation.js +101 -0
  70. package/es/utils/path-validation.js.map +1 -0
  71. package/es/utils/validation.d.ts +11 -0
  72. package/es/utils/validation.js +30 -0
  73. package/es/utils/validation.js.map +1 -0
  74. package/lib/analyze/__tests__/colors.test.d.ts +1 -0
  75. package/lib/analyze/__tests__/colors.test.js +46 -0
  76. package/lib/analyze/__tests__/colors.test.js.map +1 -0
  77. package/lib/analyze/__tests__/paths.test.d.ts +1 -0
  78. package/lib/analyze/__tests__/paths.test.js +73 -0
  79. package/lib/analyze/__tests__/paths.test.js.map +1 -0
  80. package/lib/analyze/colors.d.ts +8 -0
  81. package/lib/analyze/colors.js +58 -0
  82. package/lib/analyze/colors.js.map +1 -0
  83. package/lib/analyze/paths.d.ts +20 -0
  84. package/lib/analyze/paths.js +97 -0
  85. package/lib/analyze/paths.js.map +1 -0
  86. package/lib/compare/__tests__/diff.test.d.ts +1 -0
  87. package/lib/compare/__tests__/diff.test.js +128 -0
  88. package/lib/compare/__tests__/diff.test.js.map +1 -0
  89. package/lib/compare/diff.d.ts +18 -0
  90. package/lib/compare/diff.js +134 -0
  91. package/lib/compare/diff.js.map +1 -0
  92. package/lib/convert/__tests__/base64.test.d.ts +1 -0
  93. package/lib/convert/__tests__/base64.test.js +51 -0
  94. package/lib/convert/__tests__/base64.test.js.map +1 -0
  95. package/lib/convert/base64.d.ts +11 -0
  96. package/lib/convert/base64.js +42 -0
  97. package/lib/convert/base64.js.map +1 -0
  98. package/lib/convert/image.d.ts +18 -0
  99. package/lib/{extra-apply/applySvg2Png.js → convert/image.js} +62 -53
  100. package/lib/convert/image.js.map +1 -0
  101. package/lib/core/__tests__/dimensions.test.d.ts +1 -0
  102. package/lib/core/__tests__/dimensions.test.js +42 -0
  103. package/lib/core/__tests__/dimensions.test.js.map +1 -0
  104. package/lib/core/__tests__/element.test.d.ts +1 -0
  105. package/lib/core/__tests__/element.test.js +81 -0
  106. package/lib/core/__tests__/element.test.js.map +1 -0
  107. package/lib/core/dimensions.d.ts +8 -0
  108. package/lib/core/dimensions.js +37 -0
  109. package/lib/core/dimensions.js.map +1 -0
  110. package/lib/core/element.d.ts +24 -0
  111. package/lib/core/element.js +58 -0
  112. package/lib/core/element.js.map +1 -0
  113. package/lib/index.d.ts +15 -10
  114. package/lib/index.js +48 -20
  115. package/lib/index.js.map +1 -1
  116. package/lib/optimize/__tests__/cleanup.test.d.ts +1 -0
  117. package/lib/optimize/__tests__/cleanup.test.js +97 -0
  118. package/lib/optimize/__tests__/cleanup.test.js.map +1 -0
  119. package/lib/optimize/__tests__/path.test.d.ts +1 -0
  120. package/lib/optimize/__tests__/path.test.js +43 -0
  121. package/lib/optimize/__tests__/path.test.js.map +1 -0
  122. package/lib/optimize/cleanup.d.ts +27 -0
  123. package/lib/optimize/cleanup.js +106 -0
  124. package/lib/optimize/cleanup.js.map +1 -0
  125. package/lib/optimize/path.d.ts +7 -0
  126. package/lib/optimize/path.js +63 -0
  127. package/lib/optimize/path.js.map +1 -0
  128. package/lib/types/index.d.ts +31 -0
  129. package/lib/types/index.js +6 -0
  130. package/lib/types/index.js.map +1 -0
  131. package/lib/utils/__tests__/path-validation.test.d.ts +1 -0
  132. package/lib/utils/__tests__/path-validation.test.js +69 -0
  133. package/lib/utils/__tests__/path-validation.test.js.map +1 -0
  134. package/lib/utils/__tests__/validation.test.d.ts +1 -0
  135. package/lib/utils/__tests__/validation.test.js +44 -0
  136. package/lib/utils/__tests__/validation.test.js.map +1 -0
  137. package/lib/utils/dom.d.ts +23 -0
  138. package/lib/utils/dom.js +31 -0
  139. package/lib/utils/dom.js.map +1 -0
  140. package/lib/utils/path-validation.d.ts +29 -0
  141. package/lib/utils/path-validation.js +109 -0
  142. package/lib/utils/path-validation.js.map +1 -0
  143. package/lib/utils/validation.d.ts +11 -0
  144. package/lib/utils/validation.js +35 -0
  145. package/lib/utils/validation.js.map +1 -0
  146. package/package.json +17 -4
  147. package/es/common.d.ts +0 -68
  148. package/es/common.js +0 -110
  149. package/es/common.js.map +0 -1
  150. package/es/extra-apply/applyDiffSvg.d.ts +0 -11
  151. package/es/extra-apply/applyDiffSvg.js +0 -63
  152. package/es/extra-apply/applyDiffSvg.js.map +0 -1
  153. package/es/extra-apply/applyRemoveNanCoordinates.d.ts +0 -6
  154. package/es/extra-apply/applyRemoveNanCoordinates.js +0 -75
  155. package/es/extra-apply/applyRemoveNanCoordinates.js.map +0 -1
  156. package/es/extra-apply/applySvg2Png.d.ts +0 -16
  157. package/es/extra-apply/applySvg2Png.js +0 -64
  158. package/es/extra-apply/applySvg2Png.js.map +0 -1
  159. package/es/utils/pixelLevelDiffPng.d.ts +0 -4
  160. package/es/utils/pixelLevelDiffPng.js +0 -29
  161. package/es/utils/pixelLevelDiffPng.js.map +0 -1
  162. package/es/validate.d.ts +0 -14
  163. package/es/validate.js +0 -44
  164. package/es/validate.js.map +0 -1
  165. package/lib/common.d.ts +0 -68
  166. package/lib/common.js +0 -117
  167. package/lib/common.js.map +0 -1
  168. package/lib/extra-apply/applyDiffSvg.d.ts +0 -11
  169. package/lib/extra-apply/applyDiffSvg.js +0 -116
  170. package/lib/extra-apply/applyDiffSvg.js.map +0 -1
  171. package/lib/extra-apply/applyRemoveNanCoordinates.d.ts +0 -6
  172. package/lib/extra-apply/applyRemoveNanCoordinates.js +0 -78
  173. package/lib/extra-apply/applyRemoveNanCoordinates.js.map +0 -1
  174. package/lib/extra-apply/applySvg2Png.d.ts +0 -16
  175. package/lib/extra-apply/applySvg2Png.js.map +0 -1
  176. package/lib/utils/pixelLevelDiffPng.d.ts +0 -4
  177. package/lib/utils/pixelLevelDiffPng.js +0 -36
  178. package/lib/utils/pixelLevelDiffPng.js.map +0 -1
  179. package/lib/validate.d.ts +0 -14
  180. package/lib/validate.js +0 -48
  181. package/lib/validate.js.map +0 -1
@@ -0,0 +1,64 @@
1
+ import { validateFilePath, validateReadPath, validateWritePath } from '../path-validation';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ describe('Path Validation', () => {
6
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'svg-toolbox-test-'));
7
+ afterAll(() => {
8
+ fs.rmSync(tempDir, { recursive: true, force: true });
9
+ });
10
+ describe('validateFilePath', () => {
11
+ it('should normalize valid paths', () => {
12
+ const result = validateFilePath('./test.svg');
13
+ expect(path.isAbsolute(result)).toBe(true);
14
+ });
15
+ it('should reject paths with .. traversal', () => {
16
+ expect(() => validateFilePath('../etc/passwd')).toThrow('Path traversal detected');
17
+ expect(() => validateFilePath('../../secret')).toThrow('Path traversal detected');
18
+ });
19
+ it('should reject empty paths', () => {
20
+ expect(() => validateFilePath('')).toThrow('File path must be a non-empty string');
21
+ expect(() => validateFilePath(null)).toThrow('File path must be a non-empty string');
22
+ });
23
+ it('should restrict paths to base directory when provided', () => {
24
+ const baseDir = tempDir;
25
+ const validPath = path.join(baseDir, 'test.svg');
26
+ expect(() => validateFilePath(validPath, baseDir)).not.toThrow();
27
+ expect(() => validateFilePath('/etc/passwd', baseDir)).toThrow('Path is outside the allowed directory');
28
+ });
29
+ });
30
+ describe('validateReadPath', () => {
31
+ it('should validate file extensions', () => {
32
+ expect(() => validateReadPath('test.svg', ['.svg'])).not.toThrow();
33
+ expect(() => validateReadPath('test.png', ['.svg'])).toThrow('File extension .png is not allowed');
34
+ });
35
+ it('should accept multiple allowed extensions', () => {
36
+ expect(() => validateReadPath('test.svg', ['.svg', '.png'])).not.toThrow();
37
+ expect(() => validateReadPath('test.png', ['.svg', '.png'])).not.toThrow();
38
+ });
39
+ it('should be case-insensitive for extensions', () => {
40
+ expect(() => validateReadPath('test.SVG', ['.svg'])).not.toThrow();
41
+ });
42
+ });
43
+ describe('validateWritePath', () => {
44
+ it('should validate file extensions', () => {
45
+ const writePath = path.join(tempDir, 'test.png');
46
+ expect(() => validateWritePath(writePath, ['.png'])).not.toThrow();
47
+ expect(() => validateWritePath(writePath, ['.svg'])).toThrow('File extension .png is not allowed');
48
+ });
49
+ it('should create directory if it does not exist', () => {
50
+ const newDir = path.join(tempDir, 'new-dir');
51
+ const writePath = path.join(newDir, 'test.png');
52
+ expect(fs.existsSync(newDir)).toBe(false);
53
+ validateWritePath(writePath, ['.png']);
54
+ expect(fs.existsSync(newDir)).toBe(true);
55
+ });
56
+ it('should restrict writes to base directory when provided', () => {
57
+ const baseDir = tempDir;
58
+ const validPath = path.join(baseDir, 'test.png');
59
+ expect(() => validateWritePath(validPath, ['.png'], baseDir)).not.toThrow();
60
+ expect(() => validateWritePath('/tmp/test.png', ['.png'], baseDir)).toThrow('Path is outside the allowed directory');
61
+ });
62
+ });
63
+ });
64
+ //# sourceMappingURL=path-validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-validation.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/path-validation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import { isValidSvgString, isValidSvgElement } from '../validation';
2
+ import { createSVGElement } from '../../core/element';
3
+ describe('Validation', () => {
4
+ describe('isValidSvgString', () => {
5
+ it('should return true for valid SVG string', () => {
6
+ const svgString = '<svg><circle cx="50" cy="50" r="40" /></svg>';
7
+ expect(isValidSvgString(svgString)).toBe(true);
8
+ });
9
+ it('should return false for non-string input', () => {
10
+ expect(isValidSvgString(null)).toBe(false);
11
+ expect(isValidSvgString(123)).toBe(false);
12
+ expect(isValidSvgString({})).toBe(false);
13
+ });
14
+ it('should return false for invalid SVG string', () => {
15
+ expect(isValidSvgString('<div></div>')).toBe(false);
16
+ expect(isValidSvgString('not svg')).toBe(false);
17
+ expect(isValidSvgString('')).toBe(false);
18
+ });
19
+ it('should handle malformed XML', () => {
20
+ expect(isValidSvgString('<svg><unclosed></svg>')).toBe(false);
21
+ });
22
+ });
23
+ describe('isValidSvgElement', () => {
24
+ it('should return true for valid SVG element', () => {
25
+ const svgString = '<svg><circle /></svg>';
26
+ const element = createSVGElement(svgString);
27
+ expect(isValidSvgElement(element)).toBe(true);
28
+ });
29
+ it('should return false for non-element input', () => {
30
+ expect(isValidSvgElement(null)).toBe(false);
31
+ expect(isValidSvgElement('string')).toBe(false);
32
+ expect(isValidSvgElement({})).toBe(false);
33
+ });
34
+ it('should return false for non-SVG element', () => {
35
+ const { JSDOM } = require('jsdom');
36
+ const dom = new JSDOM(`<!DOCTYPE html><html><body><div></div></body></html>`);
37
+ const div = dom.window.document.querySelector('div');
38
+ expect(isValidSvgElement(div)).toBe(false);
39
+ });
40
+ });
41
+ });
42
+ //# sourceMappingURL=validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,SAAS,GAAG,8CAA8C,CAAC;YACjE,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1C,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChD,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,SAAS,GAAG,uBAAuB,CAAC;YAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC5C,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChD,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC9E,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAErD,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * DOM utility functions for SVG manipulation
3
+ */
4
+ export declare const document: Document;
5
+ export declare const DOMParser: {
6
+ new (): DOMParser;
7
+ prototype: DOMParser;
8
+ }, XMLSerializer: {
9
+ new (): XMLSerializer;
10
+ prototype: XMLSerializer;
11
+ };
12
+ /**
13
+ * Creates a new DOM parser instance
14
+ */
15
+ export declare function createDOMParser(): DOMParser;
16
+ /**
17
+ * Creates a new XML serializer instance
18
+ */
19
+ export declare function createXMLSerializer(): XMLSerializer;
20
+ /**
21
+ * Gets the SVG namespace URI
22
+ */
23
+ export declare const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * DOM utility functions for SVG manipulation
3
+ */
4
+ import { JSDOM } from 'jsdom';
5
+ // Create a singleton virtual DOM environment
6
+ const dom = new JSDOM(`<!DOCTYPE html><html><body></body></html>`);
7
+ export const { document } = dom.window;
8
+ export const { DOMParser, XMLSerializer } = dom.window;
9
+ /**
10
+ * Creates a new DOM parser instance
11
+ */
12
+ export function createDOMParser() {
13
+ return new dom.window.DOMParser();
14
+ }
15
+ /**
16
+ * Creates a new XML serializer instance
17
+ */
18
+ export function createXMLSerializer() {
19
+ return new dom.window.XMLSerializer();
20
+ }
21
+ /**
22
+ * Gets the SVG namespace URI
23
+ */
24
+ export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
25
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,6CAA6C;AAC7C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;AACvC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,4BAA4B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Path validation utilities to prevent path traversal attacks
3
+ */
4
+ /**
5
+ * Validates and normalizes a file path to prevent directory traversal attacks
6
+ *
7
+ * @param filePath - The file path to validate
8
+ * @param baseDirectory - Optional base directory to restrict paths to
9
+ * @returns Normalized absolute path
10
+ * @throws Error if path is invalid or contains traversal sequences
11
+ */
12
+ export declare function validateFilePath(filePath: string, baseDirectory?: string): string;
13
+ /**
14
+ * Validates that a file path is safe for reading
15
+ *
16
+ * @param filePath - The file path to validate
17
+ * @param allowedExtensions - Optional array of allowed file extensions (e.g., ['.svg', '.png'])
18
+ * @returns Normalized absolute path
19
+ */
20
+ export declare function validateReadPath(filePath: string, allowedExtensions?: string[]): string;
21
+ /**
22
+ * Validates that a file path is safe for writing
23
+ *
24
+ * @param filePath - The file path to validate
25
+ * @param allowedExtensions - Optional array of allowed file extensions
26
+ * @param baseDirectory - Optional base directory to restrict writes to
27
+ * @returns Normalized absolute path
28
+ */
29
+ export declare function validateWritePath(filePath: string, allowedExtensions?: string[], baseDirectory?: string): string;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Path validation utilities to prevent path traversal attacks
3
+ */
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ /**
7
+ * Maximum allowed path length to prevent buffer overflow attacks
8
+ */
9
+ const MAX_PATH_LENGTH = 4096;
10
+ /**
11
+ * Validates and normalizes a file path to prevent directory traversal attacks
12
+ *
13
+ * @param filePath - The file path to validate
14
+ * @param baseDirectory - Optional base directory to restrict paths to
15
+ * @returns Normalized absolute path
16
+ * @throws Error if path is invalid or contains traversal sequences
17
+ */
18
+ export function validateFilePath(filePath, baseDirectory) {
19
+ if (!filePath || typeof filePath !== 'string') {
20
+ throw new Error('File path must be a non-empty string');
21
+ }
22
+ // Check path length to prevent buffer overflow attacks
23
+ if (filePath.length > MAX_PATH_LENGTH) {
24
+ throw new Error(`Path length exceeds maximum allowed length of ${MAX_PATH_LENGTH} characters`);
25
+ }
26
+ // Check for null bytes which can be used in path traversal attacks
27
+ if (filePath.includes('\0')) {
28
+ throw new Error('Path contains null bytes which are not allowed');
29
+ }
30
+ // Check for path traversal sequences BEFORE normalization
31
+ // This catches attempts like ../, ..\, etc.
32
+ if (filePath.includes('..')) {
33
+ throw new Error('Path traversal detected: paths containing ".." are not allowed');
34
+ }
35
+ // Resolve to absolute path first, then normalize
36
+ // This ensures that . sequences are resolved
37
+ const absolutePath = path.isAbsolute(filePath)
38
+ ? path.resolve(filePath)
39
+ : path.resolve(process.cwd(), filePath);
40
+ // Normalize the resolved path
41
+ const normalizedPath = path.normalize(absolutePath);
42
+ // Additional safety check: ensure the normalized path doesn't contain .. after resolution
43
+ if (normalizedPath.includes('..')) {
44
+ throw new Error('Path traversal detected: paths containing ".." are not allowed');
45
+ }
46
+ // If base directory is provided, ensure the path is within it
47
+ if (baseDirectory) {
48
+ const baseDir = path.isAbsolute(baseDirectory)
49
+ ? path.resolve(path.normalize(baseDirectory))
50
+ : path.resolve(process.cwd(), baseDirectory);
51
+ const resolvedPath = path.resolve(normalizedPath);
52
+ // Use path.relative to check if path is within base directory
53
+ const relativePath = path.relative(baseDir, resolvedPath);
54
+ // If relative path starts with .. or is absolute, it's outside the base directory
55
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
56
+ throw new Error('Path is outside the allowed directory');
57
+ }
58
+ }
59
+ return normalizedPath;
60
+ }
61
+ /**
62
+ * Validates that a file path is safe for reading
63
+ *
64
+ * @param filePath - The file path to validate
65
+ * @param allowedExtensions - Optional array of allowed file extensions (e.g., ['.svg', '.png'])
66
+ * @returns Normalized absolute path
67
+ */
68
+ export function validateReadPath(filePath, allowedExtensions) {
69
+ const validatedPath = validateFilePath(filePath);
70
+ if (allowedExtensions && allowedExtensions.length > 0) {
71
+ const ext = path.extname(validatedPath).toLowerCase();
72
+ if (!allowedExtensions.includes(ext)) {
73
+ throw new Error(`File extension ${ext} is not allowed. Allowed extensions: ${allowedExtensions.join(', ')}`);
74
+ }
75
+ }
76
+ return validatedPath;
77
+ }
78
+ /**
79
+ * Validates that a file path is safe for writing
80
+ *
81
+ * @param filePath - The file path to validate
82
+ * @param allowedExtensions - Optional array of allowed file extensions
83
+ * @param baseDirectory - Optional base directory to restrict writes to
84
+ * @returns Normalized absolute path
85
+ */
86
+ export function validateWritePath(filePath, allowedExtensions, baseDirectory) {
87
+ const validatedPath = validateFilePath(filePath, baseDirectory);
88
+ if (allowedExtensions && allowedExtensions.length > 0) {
89
+ const ext = path.extname(validatedPath).toLowerCase();
90
+ if (!allowedExtensions.includes(ext)) {
91
+ throw new Error(`File extension ${ext} is not allowed. Allowed extensions: ${allowedExtensions.join(', ')}`);
92
+ }
93
+ }
94
+ // Ensure the directory exists
95
+ const dir = path.dirname(validatedPath);
96
+ if (!fs.existsSync(dir)) {
97
+ fs.mkdirSync(dir, { recursive: true });
98
+ }
99
+ return validatedPath;
100
+ }
101
+ //# sourceMappingURL=path-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../../src/utils/path-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Validation utilities for SVG content
3
+ */
4
+ /**
5
+ * Validates whether the provided content is a valid SVG string
6
+ */
7
+ export declare function isValidSvgString(content: unknown): content is string;
8
+ /**
9
+ * Validates whether the provided content is a valid SVG element
10
+ */
11
+ export declare function isValidSvgElement(content: unknown): content is Element;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Validation utilities for SVG content
3
+ */
4
+ import { JSDOM } from 'jsdom';
5
+ /**
6
+ * Validates whether the provided content is a valid SVG string
7
+ */
8
+ export function isValidSvgString(content) {
9
+ if (typeof content !== 'string') {
10
+ return false;
11
+ }
12
+ try {
13
+ const dom = new JSDOM(content);
14
+ const rootNode = new dom.window.DOMParser().parseFromString(content, 'image/svg+xml').documentElement;
15
+ return rootNode.nodeName.toLowerCase() === 'svg';
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ /**
22
+ * Validates whether the provided content is a valid SVG element
23
+ */
24
+ export function isValidSvgElement(content) {
25
+ return (content !== null &&
26
+ typeof content === 'object' &&
27
+ 'tagName' in content &&
28
+ content.tagName?.toLowerCase() === 'svg');
29
+ }
30
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,eAAe,CAAC;QACtG,OAAO,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,OAAO,KAAK,QAAQ;QAC3B,SAAS,IAAI,OAAO;QACnB,OAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,CACtD,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var colors_1 = require("../colors");
4
+ var element_1 = require("../../core/element");
5
+ describe('Color Analysis', function () {
6
+ describe('extractColors', function () {
7
+ it('should extract fill colors', function () {
8
+ var svgContent = '<svg><circle fill="red" /><rect fill="blue" /></svg>';
9
+ var colors = (0, colors_1.extractColors)(svgContent);
10
+ expect(colors.length).toBeGreaterThan(0);
11
+ expect(colors.some(function (c) { return c.fill === 'red'; })).toBe(true);
12
+ expect(colors.some(function (c) { return c.fill === 'blue'; })).toBe(true);
13
+ });
14
+ it('should extract stroke colors', function () {
15
+ var svgContent = '<svg><path stroke="green" stroke-width="2" /></svg>';
16
+ var colors = (0, colors_1.extractColors)(svgContent);
17
+ expect(colors.some(function (c) { return c.stroke === 'green'; })).toBe(true);
18
+ });
19
+ it('should extract opacity values', function () {
20
+ var svgContent = '<svg><circle fill="red" opacity="0.5" /></svg>';
21
+ var colors = (0, colors_1.extractColors)(svgContent);
22
+ var redColor = colors.find(function (c) { return c.fill === 'red'; });
23
+ expect(redColor === null || redColor === void 0 ? void 0 : redColor.opacity).toBe(0.5);
24
+ });
25
+ it('should ignore transparent and none values', function () {
26
+ var svgContent = '<svg><circle fill="none" stroke="transparent" /><rect fill="red" /></svg>';
27
+ var colors = (0, colors_1.extractColors)(svgContent);
28
+ expect(colors.some(function (c) { return c.fill === 'none'; })).toBe(false);
29
+ expect(colors.some(function (c) { return c.stroke === 'transparent'; })).toBe(false);
30
+ expect(colors.some(function (c) { return c.fill === 'red'; })).toBe(true);
31
+ });
32
+ it('should work with SVG element input', function () {
33
+ var svgContent = '<svg><circle fill="purple" /></svg>';
34
+ var element = (0, element_1.createSVGElement)(svgContent);
35
+ var colors = (0, colors_1.extractColors)(element);
36
+ expect(colors.some(function (c) { return c.fill === 'purple'; })).toBe(true);
37
+ });
38
+ it('should handle nested elements', function () {
39
+ var svgContent = '<svg><g><circle fill="red" /><rect fill="blue" /></g></svg>';
40
+ var colors = (0, colors_1.extractColors)(svgContent);
41
+ expect(colors.some(function (c) { return c.fill === 'red'; })).toBe(true);
42
+ expect(colors.some(function (c) { return c.fill === 'blue'; })).toBe(true);
43
+ });
44
+ });
45
+ });
46
+ //# sourceMappingURL=colors.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.test.js","sourceRoot":"","sources":["../../../src/analyze/__tests__/colors.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var paths_1 = require("../paths");
4
+ var element_1 = require("../../core/element");
5
+ describe('Path Analysis', function () {
6
+ describe('parsePathData', function () {
7
+ it('should parse simple path commands', function () {
8
+ var pathData = 'M 10,20 L 30,40 Z';
9
+ var commands = (0, paths_1.parsePathData)(pathData);
10
+ expect(commands.length).toBe(3);
11
+ expect(commands[0].type).toBe('M');
12
+ expect(commands[0].params).toEqual([10, 20]);
13
+ expect(commands[1].type).toBe('L');
14
+ expect(commands[2].type).toBe('Z');
15
+ });
16
+ it('should handle lowercase commands', function () {
17
+ var pathData = 'm 10,20 l 30,40 z';
18
+ var commands = (0, paths_1.parsePathData)(pathData);
19
+ expect(commands.length).toBe(3);
20
+ expect(commands[0].type).toBe('m');
21
+ });
22
+ it('should handle multiple parameters', function () {
23
+ var pathData = 'M 10,20 L 30,40 50,60';
24
+ var commands = (0, paths_1.parsePathData)(pathData);
25
+ expect(commands[1].params.length).toBe(4);
26
+ });
27
+ it('should handle cubic bezier commands', function () {
28
+ var pathData = 'M 10,20 C 20,30 40,50 60,70';
29
+ var commands = (0, paths_1.parsePathData)(pathData);
30
+ expect(commands.length).toBe(2);
31
+ expect(commands[1].type).toBe('C');
32
+ expect(commands[1].params.length).toBe(6);
33
+ });
34
+ });
35
+ describe('analyzePaths', function () {
36
+ it('should analyze all paths in SVG', function () {
37
+ var svgContent = '<svg><path id="path1" d="M 10,20 L 30,40" /><path id="path2" d="M 50,60 L 70,80" /></svg>';
38
+ var analysis = (0, paths_1.analyzePaths)(svgContent);
39
+ expect(analysis.size).toBe(2);
40
+ expect(analysis.has('path1')).toBe(true);
41
+ expect(analysis.has('path2')).toBe(true);
42
+ });
43
+ it('should use index as id if path has no id', function () {
44
+ var svgContent = '<svg><path d="M 10,20" /><path d="M 30,40" /></svg>';
45
+ var analysis = (0, paths_1.analyzePaths)(svgContent);
46
+ expect(analysis.has('path-0')).toBe(true);
47
+ expect(analysis.has('path-1')).toBe(true);
48
+ });
49
+ it('should work with SVG element input', function () {
50
+ var svgContent = '<svg><path d="M 10,20 L 30,40" /></svg>';
51
+ var element = (0, element_1.createSVGElement)(svgContent);
52
+ var analysis = (0, paths_1.analyzePaths)(element);
53
+ expect(analysis.size).toBe(1);
54
+ });
55
+ });
56
+ describe('getPathStatistics', function () {
57
+ it('should return correct statistics', function () {
58
+ var svgContent = '<svg><path d="M 10,20 L 30,40 Z" /><path d="M 50,60 L 70,80" /></svg>';
59
+ var stats = (0, paths_1.getPathStatistics)(svgContent);
60
+ expect(stats.totalPaths).toBe(2);
61
+ expect(stats.totalCommands).toBeGreaterThan(0);
62
+ expect(stats.commandTypes['M']).toBeGreaterThan(0);
63
+ expect(stats.commandTypes['L']).toBeGreaterThan(0);
64
+ });
65
+ it('should count command types correctly', function () {
66
+ var svgContent = '<svg><path d="M 10,20 M 30,40 L 50,60 L 70,80" /></svg>';
67
+ var stats = (0, paths_1.getPathStatistics)(svgContent);
68
+ expect(stats.commandTypes['M']).toBe(2);
69
+ expect(stats.commandTypes['L']).toBe(2);
70
+ });
71
+ });
72
+ });
73
+ //# sourceMappingURL=paths.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.test.js","sourceRoot":"","sources":["../../../src/analyze/__tests__/paths.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * SVG color analysis utilities
3
+ */
4
+ import { SVGColor } from '../types';
5
+ /**
6
+ * Extracts all colors used in an SVG
7
+ */
8
+ export declare function extractColors(svgContent: Element | string): SVGColor[];
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * SVG color analysis utilities
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractColors = extractColors;
7
+ var jsdom_1 = require("jsdom");
8
+ var element_1 = require("../core/element");
9
+ var validation_1 = require("../utils/validation");
10
+ /**
11
+ * Extracts all colors used in an SVG
12
+ */
13
+ function extractColors(svgContent) {
14
+ var svgString = (0, validation_1.isValidSvgString)(svgContent)
15
+ ? svgContent
16
+ : (0, element_1.serializeSVG)(svgContent);
17
+ var dom = new jsdom_1.JSDOM(svgString, {
18
+ contentType: 'image/svg+xml'
19
+ });
20
+ var document = dom.window.document;
21
+ var svgElement = document.querySelector('svg');
22
+ if (!svgElement) {
23
+ throw new Error('No SVG element found in the provided content.');
24
+ }
25
+ var colors = [];
26
+ var colorSet = new Set();
27
+ function extractFromElement(element) {
28
+ var fill = element.getAttribute('fill');
29
+ var stroke = element.getAttribute('stroke');
30
+ var opacity = element.getAttribute('opacity');
31
+ if (fill && fill !== 'none' && fill !== 'transparent') {
32
+ var colorKey = "".concat(fill, "-").concat(opacity || '1');
33
+ if (!colorSet.has(colorKey)) {
34
+ colorSet.add(colorKey);
35
+ colors.push({
36
+ fill: fill,
37
+ opacity: opacity ? parseFloat(opacity) : undefined
38
+ });
39
+ }
40
+ }
41
+ if (stroke && stroke !== 'none' && stroke !== 'transparent') {
42
+ var colorKey = "stroke-".concat(stroke, "-").concat(opacity || '1');
43
+ if (!colorSet.has(colorKey)) {
44
+ colorSet.add(colorKey);
45
+ colors.push({
46
+ stroke: stroke,
47
+ opacity: opacity ? parseFloat(opacity) : undefined
48
+ });
49
+ }
50
+ }
51
+ Array.from(element.children).forEach(function (child) {
52
+ extractFromElement(child);
53
+ });
54
+ }
55
+ extractFromElement(svgElement);
56
+ return colors;
57
+ }
58
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/analyze/colors.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAUH,sCAsDC;AA9DD,+BAA8B;AAC9B,2CAA+C;AAC/C,kDAA0E;AAG1E;;GAEG;AACH,SAAgB,aAAa,CAAC,UAA4B;IACxD,IAAM,SAAS,GAAG,IAAA,6BAAgB,EAAC,UAAU,CAAC;QAC5C,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,IAAA,sBAAY,EAAC,UAAU,CAAC,CAAC;IAE7B,IAAM,GAAG,GAAG,IAAI,aAAK,CAAC,SAAS,EAAE;QAC/B,WAAW,EAAE,eAAe;KAC7B,CAAC,CAAC;IAEH,IAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;IACrC,IAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAEjD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,IAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,SAAS,kBAAkB,CAAC,OAAgB;QAC1C,IAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAEhD,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;YACtD,IAAM,QAAQ,GAAG,UAAG,IAAI,cAAI,OAAO,IAAI,GAAG,CAAE,CAAC;YAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,MAAA;oBACJ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;iBACnD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;YAC5D,IAAM,QAAQ,GAAG,iBAAU,MAAM,cAAI,OAAO,IAAI,GAAG,CAAE,CAAC;YACtD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC;oBACV,MAAM,QAAA;oBACN,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;iBACnD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK;YACxC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE/B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * SVG path analysis utilities
3
+ */
4
+ import { PathCommand } from '../types';
5
+ /**
6
+ * Parses the 'd' attribute of a path element into command objects
7
+ */
8
+ export declare function parsePathData(pathData: string): PathCommand[];
9
+ /**
10
+ * Analyzes all paths in an SVG and returns their command structures
11
+ */
12
+ export declare function analyzePaths(svgContent: Element | string): Map<string, PathCommand[]>;
13
+ /**
14
+ * Gets statistics about paths in an SVG
15
+ */
16
+ export declare function getPathStatistics(svgContent: Element | string): {
17
+ totalPaths: number;
18
+ totalCommands: number;
19
+ commandTypes: Record<string, number>;
20
+ };