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,97 @@
1
+ "use strict";
2
+ /**
3
+ * SVG path analysis utilities
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parsePathData = parsePathData;
7
+ exports.analyzePaths = analyzePaths;
8
+ exports.getPathStatistics = getPathStatistics;
9
+ var jsdom_1 = require("jsdom");
10
+ var element_1 = require("../core/element");
11
+ var validation_1 = require("../utils/validation");
12
+ /**
13
+ * Maximum allowed path data length to prevent ReDoS attacks
14
+ */
15
+ var MAX_PATH_DATA_LENGTH = 100000; // 100KB should be sufficient for most SVG paths
16
+ /**
17
+ * Parses the 'd' attribute of a path element into command objects
18
+ */
19
+ function parsePathData(pathData) {
20
+ // Validate input length to prevent ReDoS attacks
21
+ if (pathData.length > MAX_PATH_DATA_LENGTH) {
22
+ throw new Error("Path data length exceeds maximum allowed length of ".concat(MAX_PATH_DATA_LENGTH, " characters"));
23
+ }
24
+ var commands = [];
25
+ // Split by path commands (M, L, H, V, C, S, Q, T, A, Z)
26
+ var commandRegex = /([MmLlHhVvCcSsQqTtAaZz])((?:\s*-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\s*,?\s*)*)/g;
27
+ var match;
28
+ var iterations = 0;
29
+ var MAX_ITERATIONS = 10000; // Prevent infinite loops
30
+ while ((match = commandRegex.exec(pathData)) !== null) {
31
+ iterations++;
32
+ if (iterations > MAX_ITERATIONS) {
33
+ throw new Error('Path parsing exceeded maximum iterations. Path data may be malformed.');
34
+ }
35
+ var type = match[1];
36
+ var paramsStr = match[2].trim();
37
+ if (type.toLowerCase() === 'z') {
38
+ commands.push({ type: type, params: [] });
39
+ }
40
+ else if (paramsStr) {
41
+ var params = paramsStr
42
+ .split(/[\s,]+/)
43
+ .filter(function (p) { return p.trim() !== ''; })
44
+ .map(Number)
45
+ .filter(function (n) { return !isNaN(n); });
46
+ commands.push({ type: type, params: params });
47
+ }
48
+ }
49
+ return commands;
50
+ }
51
+ /**
52
+ * Analyzes all paths in an SVG and returns their command structures
53
+ */
54
+ function analyzePaths(svgContent) {
55
+ var svgString = (0, validation_1.isValidSvgString)(svgContent)
56
+ ? svgContent
57
+ : (0, element_1.serializeSVG)(svgContent);
58
+ var dom = new jsdom_1.JSDOM(svgString, {
59
+ contentType: 'image/svg+xml'
60
+ });
61
+ var document = dom.window.document;
62
+ var svgElement = document.querySelector('svg');
63
+ if (!svgElement) {
64
+ throw new Error('No SVG element found in the provided content.');
65
+ }
66
+ var paths = svgElement.querySelectorAll('path');
67
+ var pathAnalysis = new Map();
68
+ Array.from(paths).forEach(function (path, index) {
69
+ var d = path.getAttribute('d');
70
+ if (d) {
71
+ var id = path.getAttribute('id') || "path-".concat(index);
72
+ pathAnalysis.set(id, parsePathData(d));
73
+ }
74
+ });
75
+ return pathAnalysis;
76
+ }
77
+ /**
78
+ * Gets statistics about paths in an SVG
79
+ */
80
+ function getPathStatistics(svgContent) {
81
+ var pathAnalysis = analyzePaths(svgContent);
82
+ var totalCommands = 0;
83
+ var commandTypes = {};
84
+ pathAnalysis.forEach(function (commands) {
85
+ totalCommands += commands.length;
86
+ commands.forEach(function (cmd) {
87
+ var type = cmd.type.toUpperCase();
88
+ commandTypes[type] = (commandTypes[type] || 0) + 1;
89
+ });
90
+ });
91
+ return {
92
+ totalPaths: pathAnalysis.size,
93
+ totalCommands: totalCommands,
94
+ commandTypes: commandTypes
95
+ };
96
+ }
97
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/analyze/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ var diff_1 = require("../diff");
43
+ var fs_1 = __importDefault(require("fs"));
44
+ var path_1 = __importDefault(require("path"));
45
+ describe('Image Diff', function () {
46
+ var fixturesDir = path_1.default.join(__dirname, '../../../test-fixtures');
47
+ var test1Path = path_1.default.join(fixturesDir, 'test1.svg');
48
+ var test2Path = path_1.default.join(fixturesDir, 'test2.svg');
49
+ var outputDir = path_1.default.join(fixturesDir, 'diff-output');
50
+ var diffImagePath = path_1.default.join(outputDir, 'diff-test1-test2.png');
51
+ beforeAll(function () {
52
+ // Ensure output directory exists
53
+ if (!fs_1.default.existsSync(outputDir)) {
54
+ fs_1.default.mkdirSync(outputDir, { recursive: true });
55
+ }
56
+ });
57
+ afterAll(function () {
58
+ // Clean up: optionally remove the diff image after tests
59
+ // Uncomment the following line if you want to clean up after tests
60
+ // if (fs.existsSync(diffImagePath)) {
61
+ // fs.unlinkSync(diffImagePath);
62
+ // }
63
+ });
64
+ it('should generate diff image between two similar but different SVGs', function () { return __awaiter(void 0, void 0, void 0, function () {
65
+ var result, savedFile;
66
+ return __generator(this, function (_a) {
67
+ switch (_a.label) {
68
+ case 0:
69
+ // Verify test fixtures exist
70
+ expect(fs_1.default.existsSync(test1Path)).toBe(true);
71
+ expect(fs_1.default.existsSync(test2Path)).toBe(true);
72
+ return [4 /*yield*/, (0, diff_1.diffImages)(test1Path, test2Path, diffImagePath, 0.1)];
73
+ case 1:
74
+ result = _a.sent();
75
+ // Verify diff image was created
76
+ expect(fs_1.default.existsSync(diffImagePath)).toBe(true);
77
+ // Verify result contains expected properties
78
+ expect(result).toHaveProperty('diffPngBuffer');
79
+ expect(result).toHaveProperty('numDiffPixels');
80
+ expect(result.diffPngBuffer).toBeInstanceOf(Buffer);
81
+ expect(typeof result.numDiffPixels).toBe('number');
82
+ // Since the SVGs are different, there should be some differences
83
+ expect(result.numDiffPixels).toBeGreaterThan(0);
84
+ savedFile = fs_1.default.readFileSync(diffImagePath);
85
+ expect(savedFile.equals(result.diffPngBuffer)).toBe(true);
86
+ // Verify file size is reasonable (not empty)
87
+ expect(savedFile.length).toBeGreaterThan(0);
88
+ console.log("Diff image saved to: ".concat(diffImagePath));
89
+ console.log("Number of different pixels: ".concat(result.numDiffPixels));
90
+ return [2 /*return*/];
91
+ }
92
+ });
93
+ }); });
94
+ it('should handle identical SVGs (no differences)', function () { return __awaiter(void 0, void 0, void 0, function () {
95
+ var identicalDiffPath, result;
96
+ return __generator(this, function (_a) {
97
+ switch (_a.label) {
98
+ case 0:
99
+ identicalDiffPath = path_1.default.join(outputDir, 'diff-identical.png');
100
+ return [4 /*yield*/, (0, diff_1.diffImages)(test1Path, test1Path, identicalDiffPath, 0.1)];
101
+ case 1:
102
+ result = _a.sent();
103
+ // Should have no differences
104
+ expect(result.numDiffPixels).toBe(0);
105
+ expect(fs_1.default.existsSync(identicalDiffPath)).toBe(true);
106
+ console.log("Identical comparison diff saved to: ".concat(identicalDiffPath));
107
+ console.log("Number of different pixels: ".concat(result.numDiffPixels));
108
+ return [2 /*return*/];
109
+ }
110
+ });
111
+ }); });
112
+ it('should generate diff without saving to file', function () { return __awaiter(void 0, void 0, void 0, function () {
113
+ var result;
114
+ return __generator(this, function (_a) {
115
+ switch (_a.label) {
116
+ case 0: return [4 /*yield*/, (0, diff_1.diffImages)(test1Path, test2Path, undefined, 0.1)];
117
+ case 1:
118
+ result = _a.sent();
119
+ // Should still return result even without file path
120
+ expect(result).toHaveProperty('diffPngBuffer');
121
+ expect(result).toHaveProperty('numDiffPixels');
122
+ expect(result.numDiffPixels).toBeGreaterThan(0);
123
+ return [2 /*return*/];
124
+ }
125
+ });
126
+ }); });
127
+ });
128
+ //# sourceMappingURL=diff.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.test.js","sourceRoot":"","sources":["../../../src/compare/__tests__/diff.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Image comparison and diff utilities
3
+ */
4
+ import { DiffResult } from '../types';
5
+ /**
6
+ * Compares two PNG images at the pixel level and generates a diff image
7
+ */
8
+ export declare function pixelLevelDiff(pngA: Buffer, pngB: Buffer, threshold?: number): DiffResult;
9
+ /**
10
+ * Compares two image files (SVG or PNG) and generates a diff image
11
+ */
12
+ export declare function diffImages(pathA: string, pathB: string, diffFilePath?: string, threshold?: number): Promise<DiffResult>;
13
+ /**
14
+ * Legacy function name for diffImages
15
+ *
16
+ * @deprecated Use diffImages instead
17
+ */
18
+ export declare function diffSvg(pathA: string, pathB: string, diffFilePath: string): Promise<DiffResult | void>;
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * Image comparison and diff utilities
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __generator = (this && this.__generator) || function (thisArg, body) {
15
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
16
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
17
+ function verb(n) { return function (v) { return step([n, v]); }; }
18
+ function step(op) {
19
+ if (f) throw new TypeError("Generator is already executing.");
20
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
21
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
22
+ if (y = 0, t) op = [op[0] & 2, t.value];
23
+ switch (op[0]) {
24
+ case 0: case 1: t = op; break;
25
+ case 4: _.label++; return { value: op[1], done: false };
26
+ case 5: _.label++; y = op[1]; op = [0]; continue;
27
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
28
+ default:
29
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
30
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
31
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
32
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
33
+ if (t[2]) _.ops.pop();
34
+ _.trys.pop(); continue;
35
+ }
36
+ op = body.call(thisArg, _);
37
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
38
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
39
+ }
40
+ };
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.pixelLevelDiff = pixelLevelDiff;
46
+ exports.diffImages = diffImages;
47
+ exports.diffSvg = diffSvg;
48
+ var fs_1 = __importDefault(require("fs"));
49
+ var path_1 = __importDefault(require("path"));
50
+ var sharp_1 = __importDefault(require("sharp"));
51
+ var pngjs_1 = require("pngjs");
52
+ var pixelmatch_1 = __importDefault(require("pixelmatch"));
53
+ var path_validation_1 = require("../utils/path-validation");
54
+ /**
55
+ * Compares two PNG images at the pixel level and generates a diff image
56
+ */
57
+ function pixelLevelDiff(pngA, pngB, threshold) {
58
+ if (threshold === void 0) { threshold = 0.1; }
59
+ var img1 = pngjs_1.PNG.sync.read(pngA);
60
+ var img2 = pngjs_1.PNG.sync.read(pngB);
61
+ var width = img1.width, height = img1.height;
62
+ if (img2.width !== width || img2.height !== height) {
63
+ throw new Error('Images must have the same dimensions');
64
+ }
65
+ var diff = new pngjs_1.PNG({ width: width, height: height });
66
+ var numDiffPixels = (0, pixelmatch_1.default)(img1.data, img2.data, diff.data, width, height, { threshold: threshold });
67
+ var diffPngBuffer = pngjs_1.PNG.sync.write(diff);
68
+ return {
69
+ diffPngBuffer: diffPngBuffer,
70
+ numDiffPixels: numDiffPixels
71
+ };
72
+ }
73
+ /**
74
+ * Compares two image files (SVG or PNG) and generates a diff image
75
+ */
76
+ function diffImages(pathA_1, pathB_1, diffFilePath_1) {
77
+ return __awaiter(this, arguments, void 0, function (pathA, pathB, diffFilePath, threshold) {
78
+ var validatedPathA, validatedPathB, pngA, pngB, result, ext, validatedWritePath;
79
+ if (threshold === void 0) { threshold = 0.1; }
80
+ return __generator(this, function (_a) {
81
+ switch (_a.label) {
82
+ case 0:
83
+ validatedPathA = (0, path_validation_1.validateReadPath)(pathA, ['.svg', '.png', '.jpg', '.jpeg', '.webp']);
84
+ validatedPathB = (0, path_validation_1.validateReadPath)(pathB, ['.svg', '.png', '.jpg', '.jpeg', '.webp']);
85
+ if (!fs_1.default.existsSync(validatedPathA)) {
86
+ throw new Error("File not found: ".concat(validatedPathA));
87
+ }
88
+ if (!fs_1.default.existsSync(validatedPathB)) {
89
+ throw new Error("File not found: ".concat(validatedPathB));
90
+ }
91
+ return [4 /*yield*/, (0, sharp_1.default)(validatedPathA).png().toBuffer()];
92
+ case 1:
93
+ pngA = _a.sent();
94
+ return [4 /*yield*/, (0, sharp_1.default)(validatedPathB).png().toBuffer()];
95
+ case 2:
96
+ pngB = _a.sent();
97
+ result = pixelLevelDiff(pngA, pngB, threshold);
98
+ if (diffFilePath) {
99
+ ext = path_1.default.extname(diffFilePath);
100
+ if (!ext) {
101
+ throw new Error('Diff file path must have a file extension');
102
+ }
103
+ validatedWritePath = (0, path_validation_1.validateWritePath)(diffFilePath, ['.png']);
104
+ fs_1.default.writeFileSync(validatedWritePath, result.diffPngBuffer);
105
+ }
106
+ return [2 /*return*/, result];
107
+ }
108
+ });
109
+ });
110
+ }
111
+ /**
112
+ * Legacy function name for diffImages
113
+ *
114
+ * @deprecated Use diffImages instead
115
+ */
116
+ function diffSvg(pathA, pathB, diffFilePath) {
117
+ return __awaiter(this, void 0, void 0, function () {
118
+ var error_1;
119
+ return __generator(this, function (_a) {
120
+ switch (_a.label) {
121
+ case 0:
122
+ _a.trys.push([0, 2, , 3]);
123
+ return [4 /*yield*/, diffImages(pathA, pathB, diffFilePath)];
124
+ case 1: return [2 /*return*/, _a.sent()];
125
+ case 2:
126
+ error_1 = _a.sent();
127
+ console.error("Error comparing images: ".concat(error_1 instanceof Error ? error_1.message : String(error_1)));
128
+ return [2 /*return*/];
129
+ case 3: return [2 /*return*/];
130
+ }
131
+ });
132
+ });
133
+ }
134
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/compare/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var base64_3 = require("../base64");
4
+ var element_1 = require("../../core/element");
5
+ describe('Base64 Conversion', function () {
6
+ var testSvg = '<svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" /></svg>';
7
+ describe('convertSVGToBase64', function () {
8
+ it('should convert SVG string to base64 data URI', function () {
9
+ var base64 = (0, base64_3.convertSVGToBase64)(testSvg);
10
+ expect(base64).toMatch(/^data:image\/svg\+xml;base64,/);
11
+ expect(base64.length).toBeGreaterThan(50);
12
+ });
13
+ it('should convert SVG element to base64 data URI', function () {
14
+ var element = (0, element_1.createSVGElement)(testSvg);
15
+ var base64 = (0, base64_3.convertSVGToBase64)(element);
16
+ expect(base64).toMatch(/^data:image\/svg\+xml;base64,/);
17
+ });
18
+ it('should produce consistent results for same input', function () {
19
+ var base64_1 = (0, base64_3.convertSVGToBase64)(testSvg);
20
+ var base64_2 = (0, base64_3.convertSVGToBase64)(testSvg);
21
+ expect(base64_1).toBe(base64_2);
22
+ });
23
+ });
24
+ describe('convertBase64ToSVG', function () {
25
+ it('should convert base64 data URI back to SVG string', function () {
26
+ var base64 = (0, base64_3.convertSVGToBase64)(testSvg);
27
+ var svgString = (0, base64_3.convertBase64ToSVG)(base64);
28
+ expect(svgString).toContain('<svg');
29
+ expect(svgString).toContain('circle');
30
+ });
31
+ it('should handle base64 string without data URI prefix', function () {
32
+ var base64 = (0, base64_3.convertSVGToBase64)(testSvg);
33
+ var base64Only = base64.split(',')[1];
34
+ var svgString = (0, base64_3.convertBase64ToSVG)(base64Only);
35
+ expect(svgString).toContain('<svg');
36
+ });
37
+ it('should throw error for invalid base64 string', function () {
38
+ expect(function () { return (0, base64_3.convertBase64ToSVG)('invalid-base64!!!'); }).toThrow('Invalid Base64 string');
39
+ });
40
+ it('should round-trip correctly', function () {
41
+ var original = testSvg;
42
+ var base64 = (0, base64_3.convertSVGToBase64)(original);
43
+ var converted = (0, base64_3.convertBase64ToSVG)(base64);
44
+ // Remove whitespace differences for comparison
45
+ var normalize = function (s) { return s.replace(/\s+/g, ' ').trim(); };
46
+ expect(normalize(converted)).toContain('<svg');
47
+ expect(normalize(converted)).toContain('circle');
48
+ });
49
+ });
50
+ });
51
+ //# sourceMappingURL=base64.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.test.js","sourceRoot":"","sources":["../../../src/convert/__tests__/base64.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Base64 encoding/decoding utilities for SVG
3
+ */
4
+ /**
5
+ * Converts an SVG element or SVG string to a Base64-encoded data URI
6
+ */
7
+ export declare function convertSVGToBase64(svgContent: Element | string): string;
8
+ /**
9
+ * Converts a Base64-encoded data URI back to an SVG string
10
+ */
11
+ export declare function convertBase64ToSVG(base64String: string): string;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * Base64 encoding/decoding utilities for SVG
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.convertSVGToBase64 = convertSVGToBase64;
7
+ exports.convertBase64ToSVG = convertBase64ToSVG;
8
+ var element_1 = require("../core/element");
9
+ /**
10
+ * Converts an SVG element or SVG string to a Base64-encoded data URI
11
+ */
12
+ function convertSVGToBase64(svgContent) {
13
+ var svgString = (0, element_1.serializeSVG)(svgContent);
14
+ return "data:image/svg+xml;base64,".concat(Buffer.from(svgString).toString('base64'));
15
+ }
16
+ /**
17
+ * Converts a Base64-encoded data URI back to an SVG string
18
+ */
19
+ function convertBase64ToSVG(base64String) {
20
+ try {
21
+ var base64Data = base64String.includes(',')
22
+ ? base64String.split(',')[1]
23
+ : base64String;
24
+ // Validate base64 string format
25
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(base64Data)) {
26
+ throw new Error('Invalid Base64 string.');
27
+ }
28
+ var svgString = Buffer.from(base64Data, 'base64').toString('utf-8');
29
+ // Basic validation that result looks like SVG
30
+ if (!svgString.includes('<svg') && !svgString.includes('<SVG')) {
31
+ throw new Error('Invalid Base64 string.');
32
+ }
33
+ return svgString;
34
+ }
35
+ catch (error) {
36
+ if (error instanceof Error && error.message === 'Invalid Base64 string.') {
37
+ throw error;
38
+ }
39
+ throw new Error('Invalid Base64 string.');
40
+ }
41
+ }
42
+ //# sourceMappingURL=base64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/convert/base64.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAQH,gDAGC;AAKD,gDAyBC;AAtCD,2CAA+C;AAE/C;;GAEG;AACH,SAAgB,kBAAkB,CAAC,UAA4B;IAC7D,IAAM,SAAS,GAAG,IAAA,sBAAY,EAAC,UAAU,CAAC,CAAC;IAC3C,OAAO,oCAA6B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAE,CAAC;AAClF,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,YAAoB;IACrD,IAAI,CAAC;QACH,IAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC5B,CAAC,CAAC,YAAY,CAAC;QAEjB,gCAAgC;QAChC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,IAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAEtE,8CAA8C;QAC9C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,wBAAwB,EAAE,CAAC;YACzE,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * SVG to image format conversion utilities
3
+ */
4
+ import { ConversionOptions } from '../types';
5
+ /**
6
+ * Converts an SVG file to PNG format
7
+ *
8
+ * @param svgPath - Path to the SVG file
9
+ * @param options - Conversion options including scale, format, and quality
10
+ * @returns Promise resolving to a Buffer containing the converted image
11
+ */
12
+ export declare function svgToImage(svgPath: string, options?: ConversionOptions): Promise<Buffer>;
13
+ /**
14
+ * Converts an SVG file to PNG format (legacy function name)
15
+ *
16
+ * @deprecated Use svgToImage instead
17
+ */
18
+ export declare function svg2Png(svgPath: string, pngPath?: string, scale?: number): Promise<void | Buffer>;