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.
- package/README.md +156 -118
- package/es/analyze/__tests__/colors.test.d.ts +1 -0
- package/es/analyze/__tests__/colors.test.js +44 -0
- package/es/analyze/__tests__/colors.test.js.map +1 -0
- package/es/analyze/__tests__/paths.test.d.ts +1 -0
- package/es/analyze/__tests__/paths.test.js +71 -0
- package/es/analyze/__tests__/paths.test.js.map +1 -0
- package/es/analyze/colors.d.ts +8 -0
- package/es/analyze/colors.js +55 -0
- package/es/analyze/colors.js.map +1 -0
- package/es/analyze/paths.d.ts +20 -0
- package/es/analyze/paths.js +92 -0
- package/es/analyze/paths.js.map +1 -0
- package/es/compare/__tests__/diff.test.d.ts +1 -0
- package/es/compare/__tests__/diff.test.js +64 -0
- package/es/compare/__tests__/diff.test.js.map +1 -0
- package/es/compare/diff.d.ts +18 -0
- package/es/compare/diff.js +70 -0
- package/es/compare/diff.js.map +1 -0
- package/es/convert/__tests__/base64.test.d.ts +1 -0
- package/es/convert/__tests__/base64.test.js +49 -0
- package/es/convert/__tests__/base64.test.js.map +1 -0
- package/es/convert/base64.d.ts +11 -0
- package/es/convert/base64.js +38 -0
- package/es/convert/base64.js.map +1 -0
- package/es/convert/image.d.ts +18 -0
- package/es/convert/image.js +63 -0
- package/es/convert/image.js.map +1 -0
- package/es/core/__tests__/dimensions.test.d.ts +1 -0
- package/es/core/__tests__/dimensions.test.js +40 -0
- package/es/core/__tests__/dimensions.test.js.map +1 -0
- package/es/core/__tests__/element.test.d.ts +1 -0
- package/es/core/__tests__/element.test.js +79 -0
- package/es/core/__tests__/element.test.js.map +1 -0
- package/es/core/dimensions.d.ts +8 -0
- package/es/core/dimensions.js +34 -0
- package/es/core/dimensions.js.map +1 -0
- package/es/core/element.d.ts +24 -0
- package/es/core/element.js +52 -0
- package/es/core/element.js.map +1 -0
- package/es/index.d.ts +15 -10
- package/es/index.js +21 -10
- package/es/index.js.map +1 -1
- package/es/optimize/__tests__/cleanup.test.d.ts +1 -0
- package/es/optimize/__tests__/cleanup.test.js +95 -0
- package/es/optimize/__tests__/cleanup.test.js.map +1 -0
- package/es/optimize/__tests__/path.test.d.ts +1 -0
- package/es/optimize/__tests__/path.test.js +41 -0
- package/es/optimize/__tests__/path.test.js.map +1 -0
- package/es/optimize/cleanup.d.ts +27 -0
- package/es/optimize/cleanup.js +100 -0
- package/es/optimize/cleanup.js.map +1 -0
- package/es/optimize/path.d.ts +7 -0
- package/es/optimize/path.js +58 -0
- package/es/optimize/path.js.map +1 -0
- package/es/types/index.d.ts +31 -0
- package/es/types/index.js +5 -0
- package/es/types/index.js.map +1 -0
- package/es/utils/__tests__/path-validation.test.d.ts +1 -0
- package/es/utils/__tests__/path-validation.test.js +64 -0
- package/es/utils/__tests__/path-validation.test.js.map +1 -0
- package/es/utils/__tests__/validation.test.d.ts +1 -0
- package/es/utils/__tests__/validation.test.js +42 -0
- package/es/utils/__tests__/validation.test.js.map +1 -0
- package/es/utils/dom.d.ts +23 -0
- package/es/utils/dom.js +25 -0
- package/es/utils/dom.js.map +1 -0
- package/es/utils/path-validation.d.ts +29 -0
- package/es/utils/path-validation.js +101 -0
- package/es/utils/path-validation.js.map +1 -0
- package/es/utils/validation.d.ts +11 -0
- package/es/utils/validation.js +30 -0
- package/es/utils/validation.js.map +1 -0
- package/lib/analyze/__tests__/colors.test.d.ts +1 -0
- package/lib/analyze/__tests__/colors.test.js +46 -0
- package/lib/analyze/__tests__/colors.test.js.map +1 -0
- package/lib/analyze/__tests__/paths.test.d.ts +1 -0
- package/lib/analyze/__tests__/paths.test.js +73 -0
- package/lib/analyze/__tests__/paths.test.js.map +1 -0
- package/lib/analyze/colors.d.ts +8 -0
- package/lib/analyze/colors.js +58 -0
- package/lib/analyze/colors.js.map +1 -0
- package/lib/analyze/paths.d.ts +20 -0
- package/lib/analyze/paths.js +97 -0
- package/lib/analyze/paths.js.map +1 -0
- package/lib/compare/__tests__/diff.test.d.ts +1 -0
- package/lib/compare/__tests__/diff.test.js +128 -0
- package/lib/compare/__tests__/diff.test.js.map +1 -0
- package/lib/compare/diff.d.ts +18 -0
- package/lib/compare/diff.js +134 -0
- package/lib/compare/diff.js.map +1 -0
- package/lib/convert/__tests__/base64.test.d.ts +1 -0
- package/lib/convert/__tests__/base64.test.js +51 -0
- package/lib/convert/__tests__/base64.test.js.map +1 -0
- package/lib/convert/base64.d.ts +11 -0
- package/lib/convert/base64.js +42 -0
- package/lib/convert/base64.js.map +1 -0
- package/lib/convert/image.d.ts +18 -0
- package/lib/{extra-apply/applySvg2Png.js → convert/image.js} +62 -53
- package/lib/convert/image.js.map +1 -0
- package/lib/core/__tests__/dimensions.test.d.ts +1 -0
- package/lib/core/__tests__/dimensions.test.js +42 -0
- package/lib/core/__tests__/dimensions.test.js.map +1 -0
- package/lib/core/__tests__/element.test.d.ts +1 -0
- package/lib/core/__tests__/element.test.js +81 -0
- package/lib/core/__tests__/element.test.js.map +1 -0
- package/lib/core/dimensions.d.ts +8 -0
- package/lib/core/dimensions.js +37 -0
- package/lib/core/dimensions.js.map +1 -0
- package/lib/core/element.d.ts +24 -0
- package/lib/core/element.js +58 -0
- package/lib/core/element.js.map +1 -0
- package/lib/index.d.ts +15 -10
- package/lib/index.js +48 -20
- package/lib/index.js.map +1 -1
- package/lib/optimize/__tests__/cleanup.test.d.ts +1 -0
- package/lib/optimize/__tests__/cleanup.test.js +97 -0
- package/lib/optimize/__tests__/cleanup.test.js.map +1 -0
- package/lib/optimize/__tests__/path.test.d.ts +1 -0
- package/lib/optimize/__tests__/path.test.js +43 -0
- package/lib/optimize/__tests__/path.test.js.map +1 -0
- package/lib/optimize/cleanup.d.ts +27 -0
- package/lib/optimize/cleanup.js +106 -0
- package/lib/optimize/cleanup.js.map +1 -0
- package/lib/optimize/path.d.ts +7 -0
- package/lib/optimize/path.js +63 -0
- package/lib/optimize/path.js.map +1 -0
- package/lib/types/index.d.ts +31 -0
- package/lib/types/index.js +6 -0
- package/lib/types/index.js.map +1 -0
- package/lib/utils/__tests__/path-validation.test.d.ts +1 -0
- package/lib/utils/__tests__/path-validation.test.js +69 -0
- package/lib/utils/__tests__/path-validation.test.js.map +1 -0
- package/lib/utils/__tests__/validation.test.d.ts +1 -0
- package/lib/utils/__tests__/validation.test.js +44 -0
- package/lib/utils/__tests__/validation.test.js.map +1 -0
- package/lib/utils/dom.d.ts +23 -0
- package/lib/utils/dom.js +31 -0
- package/lib/utils/dom.js.map +1 -0
- package/lib/utils/path-validation.d.ts +29 -0
- package/lib/utils/path-validation.js +109 -0
- package/lib/utils/path-validation.js.map +1 -0
- package/lib/utils/validation.d.ts +11 -0
- package/lib/utils/validation.js +35 -0
- package/lib/utils/validation.js.map +1 -0
- package/package.json +17 -4
- package/es/common.d.ts +0 -68
- package/es/common.js +0 -110
- package/es/common.js.map +0 -1
- package/es/extra-apply/applyDiffSvg.d.ts +0 -11
- package/es/extra-apply/applyDiffSvg.js +0 -63
- package/es/extra-apply/applyDiffSvg.js.map +0 -1
- package/es/extra-apply/applyRemoveNanCoordinates.d.ts +0 -6
- package/es/extra-apply/applyRemoveNanCoordinates.js +0 -75
- package/es/extra-apply/applyRemoveNanCoordinates.js.map +0 -1
- package/es/extra-apply/applySvg2Png.d.ts +0 -16
- package/es/extra-apply/applySvg2Png.js +0 -64
- package/es/extra-apply/applySvg2Png.js.map +0 -1
- package/es/utils/pixelLevelDiffPng.d.ts +0 -4
- package/es/utils/pixelLevelDiffPng.js +0 -29
- package/es/utils/pixelLevelDiffPng.js.map +0 -1
- package/es/validate.d.ts +0 -14
- package/es/validate.js +0 -44
- package/es/validate.js.map +0 -1
- package/lib/common.d.ts +0 -68
- package/lib/common.js +0 -117
- package/lib/common.js.map +0 -1
- package/lib/extra-apply/applyDiffSvg.d.ts +0 -11
- package/lib/extra-apply/applyDiffSvg.js +0 -116
- package/lib/extra-apply/applyDiffSvg.js.map +0 -1
- package/lib/extra-apply/applyRemoveNanCoordinates.d.ts +0 -6
- package/lib/extra-apply/applyRemoveNanCoordinates.js +0 -78
- package/lib/extra-apply/applyRemoveNanCoordinates.js.map +0 -1
- package/lib/extra-apply/applySvg2Png.d.ts +0 -16
- package/lib/extra-apply/applySvg2Png.js.map +0 -1
- package/lib/utils/pixelLevelDiffPng.d.ts +0 -4
- package/lib/utils/pixelLevelDiffPng.js +0 -36
- package/lib/utils/pixelLevelDiffPng.js.map +0 -1
- package/lib/validate.d.ts +0 -14
- package/lib/validate.js +0 -48
- package/lib/validate.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,176 +1,214 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<br/>
|
|
3
|
-
<img width="260" alt="
|
|
3
|
+
<img width="260" alt="SVG Toolbox Logo" src="https://github.com/user-attachments/assets/fcb0c4f5-8094-44d2-bfca-e4b5f5120f73" />
|
|
4
4
|
<br/>
|
|
5
5
|
</h1>
|
|
6
6
|
|
|
7
|
+
# SVG Toolbox
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
This module provides utility functions for working with SVG elements and files, including creating, cloning, merging, converting SVG to Base64, comparing SVG images, normalizing path data, and converting SVG to PNG format.
|
|
9
|
+
A comprehensive SVG manipulation and analysis library providing capabilities for creating, converting, optimizing, comparing, and analyzing SVG elements.
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/svg-toolbox)
|
|
12
12
|
[](https://www.npmjs.com/package/svg-toolbox)
|
|
13
|
-
[](https://www.npmjs.com/package/svg-toolbox)
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
|
+
|
|
16
17
|
```bash
|
|
17
18
|
npm install svg-toolbox
|
|
18
19
|
```
|
|
19
20
|
|
|
20
|
-
##
|
|
21
|
+
## Use Cases
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
- [Installation](#installation)
|
|
24
|
-
- [Table of Contents](#table-of-contents)
|
|
25
|
-
- [Usage](#usage)
|
|
26
|
-
- [createSVGElement](#createsvgelement)
|
|
27
|
-
- [cloneSVGElement](#clonesvgelement)
|
|
28
|
-
- [mergeSVGElements](#mergesvgelements)
|
|
29
|
-
- [convertSVGToBase64](#convertsvgtobase64)
|
|
30
|
-
- [convertBase64ToSVG](#convertbase64tosvg)
|
|
31
|
-
- [diffSvg](#diffsvg)
|
|
32
|
-
- [svg2png](#svg2png)
|
|
33
|
-
- [removeNanCoordinates](#removenancoordinates)
|
|
34
|
-
- [License](#license)
|
|
23
|
+
### 1. SVG Element Manipulation
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
When you need to create, clone, or merge SVG elements in Node.js environments:
|
|
37
26
|
|
|
38
|
-
|
|
27
|
+
- **Dynamic SVG Generation**: Create SVG elements dynamically based on data
|
|
28
|
+
- **SVG Template Reuse**: Clone existing SVG elements as templates
|
|
29
|
+
- **Combine Multiple SVGs**: Merge multiple independent SVG graphics into one
|
|
39
30
|
|
|
40
|
-
|
|
31
|
+
### 2. Format Conversion
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
const svgElement = createSVGElement(`<svg><path d="M10 20L30 40Z" /></svg>`);
|
|
44
|
-
console.log(svgElement);
|
|
45
|
-
```
|
|
46
|
-
### cloneSVGElement
|
|
33
|
+
When you need to convert SVG to other formats or perform encoding conversions:
|
|
47
34
|
|
|
48
|
-
|
|
35
|
+
- **Web Application Embedding**: Convert SVG to Base64 data URI for easy embedding in HTML/CSS
|
|
36
|
+
- **Image Export**: Convert SVG to PNG, JPG, or WebP formats for download or sharing
|
|
37
|
+
- **Cross-platform Compatibility**: Use Base64 encoding when transferring SVG data between different systems
|
|
49
38
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
39
|
+
### 3. Visual Regression Testing
|
|
40
|
+
|
|
41
|
+
When you need to compare SVG rendering results to ensure visual consistency:
|
|
42
|
+
|
|
43
|
+
- **Automated Testing**: Detect SVG rendering changes in CI/CD pipelines
|
|
44
|
+
- **Version Comparison**: Compare differences between different versions of SVG files
|
|
45
|
+
- **Quality Assurance**: Ensure SVG modifications don't introduce unexpected visual changes
|
|
46
|
+
|
|
47
|
+
### 4. SVG Optimization
|
|
48
|
+
|
|
49
|
+
When you need to clean and optimize SVG code:
|
|
50
|
+
|
|
51
|
+
- **Performance Optimization**: Remove invalid coordinates and empty attributes to reduce file size
|
|
52
|
+
- **Code Cleanup**: Remove comments and excess whitespace to improve readability
|
|
53
|
+
- **Data Repair**: Fix path data containing NaN or invalid values
|
|
54
|
+
|
|
55
|
+
### 5. SVG Analysis
|
|
56
|
+
|
|
57
|
+
When you need to gain insights into SVG content, the analysis features can help you:
|
|
58
|
+
|
|
59
|
+
#### Color Extraction Use Cases
|
|
60
|
+
- **Design System Building**: Batch analyze SVG icon libraries, extract all used colors, and establish color standards for design systems
|
|
61
|
+
- **Theme Adaptation**: Identify colors in SVG and automatically generate dark/light theme versions
|
|
62
|
+
- **Accessibility Checking**: Verify that SVG colors meet WCAG contrast requirements
|
|
63
|
+
- **Brand Consistency Verification**: Verify that SVG icons use brand standard colors
|
|
64
|
+
- **Automated Color Replacement**: Identify colors that need replacement and batch update SVG files
|
|
65
|
+
|
|
66
|
+
#### Path Analysis Use Cases
|
|
67
|
+
- **SVG Optimization Decisions**: Analyze path complexity to determine if simplification or optimization is needed
|
|
68
|
+
- **Performance Analysis**: Count path commands to evaluate SVG rendering performance
|
|
69
|
+
- **Format Conversion Preparation**: Understand path structure to prepare for conversion to other formats
|
|
70
|
+
- **Animation Creation**: Analyze path command types to determine suitable animation methods (e.g., path stroke animation)
|
|
71
|
+
- **Quality Detection**: Detect if SVG contains overly complex paths (which may cause performance issues)
|
|
72
|
+
- **Path Editing Tools**: Provide path parsing and editing capabilities for SVG editors
|
|
73
|
+
- **Learning and Teaching**: Analyze SVG path structure to help understand SVG drawing principles
|
|
74
|
+
|
|
75
|
+
## Feature Modules
|
|
76
|
+
|
|
77
|
+
### Core Functions
|
|
78
|
+
|
|
79
|
+
Provides basic SVG element manipulation capabilities:
|
|
80
|
+
|
|
81
|
+
- `createSVGElement` - Create SVG element from string
|
|
82
|
+
- `cloneSVGElement` - Deep clone SVG element
|
|
83
|
+
- `mergeSVGElements` - Merge multiple SVG elements
|
|
84
|
+
- `getSVGDimensions` - Get SVG dimensions
|
|
85
|
+
|
|
86
|
+
### Conversion Functions
|
|
87
|
+
|
|
88
|
+
Provides format conversion and encoding capabilities:
|
|
89
|
+
|
|
90
|
+
- `convertSVGToBase64` - Convert SVG to Base64 encoding
|
|
91
|
+
- `convertBase64ToSVG` - Decode Base64 to SVG
|
|
92
|
+
- `svgToImage` - Convert SVG to image formats (PNG/JPG/WebP)
|
|
93
|
+
- `svg2Png` - Convert SVG to PNG (legacy API compatibility)
|
|
94
|
+
|
|
95
|
+
### Comparison Functions
|
|
68
96
|
|
|
69
|
-
|
|
70
|
-
|
|
97
|
+
Provides image comparison and difference detection:
|
|
98
|
+
|
|
99
|
+
- `diffImages` - Compare two image files and generate diff image
|
|
100
|
+
- `pixelLevelDiff` - Pixel-level image difference comparison
|
|
101
|
+
- `diffSvg` - SVG difference comparison (legacy API compatibility)
|
|
102
|
+
|
|
103
|
+
### Optimization Functions
|
|
104
|
+
|
|
105
|
+
Provides SVG code optimization and cleanup:
|
|
106
|
+
|
|
107
|
+
- `removeNanCoordinates` - Remove NaN coordinates from paths
|
|
108
|
+
- `removeEmptyAttributes` - Remove empty attributes
|
|
109
|
+
- `removeComments` - Remove comments
|
|
110
|
+
- `normalizeWhitespace` - Normalize whitespace characters
|
|
111
|
+
- `optimizeSVG` - Comprehensive SVG code optimization
|
|
112
|
+
|
|
113
|
+
### Analysis Functions
|
|
114
|
+
|
|
115
|
+
Provides SVG content analysis:
|
|
116
|
+
|
|
117
|
+
- `extractColors` - Extract colors used in SVG
|
|
118
|
+
- `parsePathData` - Parse path data
|
|
119
|
+
- `analyzePaths` - Analyze all path elements
|
|
120
|
+
- `getPathStatistics` - Get path statistics
|
|
121
|
+
|
|
122
|
+
## Usage Examples
|
|
123
|
+
|
|
124
|
+
### Basic Operations
|
|
71
125
|
|
|
72
126
|
```typescript
|
|
73
|
-
import { mergeSVGElements } from 'svg-toolbox';
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
svgElement1.setAttribute('stroke', 'black');
|
|
84
|
-
svgElement1.setAttribute('stroke-width', '3');
|
|
85
|
-
svgElement1.setAttribute('fill', 'red');
|
|
86
|
-
|
|
87
|
-
const svgElement2 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
88
|
-
svgElement2.setAttribute('x', '10');
|
|
89
|
-
svgElement2.setAttribute('y', '10');
|
|
90
|
-
svgElement2.setAttribute('width', '100');
|
|
91
|
-
svgElement2.setAttribute('height', '100');
|
|
92
|
-
svgElement2.setAttribute('fill', 'blue');
|
|
93
|
-
|
|
94
|
-
const mergedElement = mergeSVGElements([svgElement1, svgElement2]);
|
|
95
|
-
console.log(mergedElement);
|
|
127
|
+
import { createSVGElement, cloneSVGElement, mergeSVGElements } from 'svg-toolbox';
|
|
128
|
+
|
|
129
|
+
// Create SVG element
|
|
130
|
+
const svg = createSVGElement('<svg><circle cx="50" cy="50" r="40" /></svg>');
|
|
131
|
+
|
|
132
|
+
// Clone element
|
|
133
|
+
const cloned = cloneSVGElement(svg);
|
|
134
|
+
|
|
135
|
+
// Merge multiple elements
|
|
136
|
+
const merged = mergeSVGElements([svg, cloned]);
|
|
96
137
|
```
|
|
97
138
|
|
|
98
|
-
###
|
|
99
|
-
Converts an SVG element or SVG string to a Base64-encoded string.
|
|
139
|
+
### Format Conversion
|
|
100
140
|
|
|
101
141
|
```typescript
|
|
102
|
-
import {
|
|
103
|
-
|
|
104
|
-
const svgElement = createSVGElement(`<svg><path d="M10 20L30 40Z" /></svg>`);
|
|
142
|
+
import { convertSVGToBase64, svgToImage } from 'svg-toolbox';
|
|
105
143
|
|
|
106
|
-
|
|
107
|
-
|
|
144
|
+
// Convert to Base64
|
|
145
|
+
const base64 = convertSVGToBase64('<svg>...</svg>');
|
|
108
146
|
|
|
109
|
-
|
|
110
|
-
|
|
147
|
+
// Convert to PNG
|
|
148
|
+
const pngBuffer = await svgToImage('input.svg', { scale: 2, format: 'png' });
|
|
111
149
|
|
|
112
|
-
|
|
113
|
-
|
|
150
|
+
// Convert to WebP
|
|
151
|
+
const webpBuffer = await svgToImage('input.svg', { format: 'webp', quality: 90 });
|
|
114
152
|
```
|
|
115
153
|
|
|
116
|
-
###
|
|
117
|
-
Converts a Base64-encoded string back to an SVG string.
|
|
154
|
+
### Image Comparison
|
|
118
155
|
|
|
119
156
|
```typescript
|
|
120
|
-
import {
|
|
157
|
+
import { diffImages } from 'svg-toolbox';
|
|
121
158
|
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
console.log(
|
|
159
|
+
// Compare two images and generate diff image
|
|
160
|
+
const result = await diffImages('image1.svg', 'image2.svg', 'diff.png');
|
|
161
|
+
console.log(`Number of different pixels: ${result.numDiffPixels}`);
|
|
125
162
|
```
|
|
126
163
|
|
|
127
|
-
###
|
|
128
|
-
Compares two PNG images and generates a diff image.
|
|
164
|
+
### SVG Optimization
|
|
129
165
|
|
|
130
166
|
```typescript
|
|
131
|
-
import {
|
|
167
|
+
import { optimizeSVG, removeNanCoordinates } from 'svg-toolbox';
|
|
132
168
|
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const diffFilePath = 'path/to/save/diff/image.png';
|
|
169
|
+
// Comprehensive optimization
|
|
170
|
+
const optimized = optimizeSVG('<svg><!-- comment --><path d="M 10,20 nan L 30,40" /></svg>');
|
|
136
171
|
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
const { diffPngBuffer, numDiffPixels } = await diffSvg(pathA, pathB, diffFilePath)
|
|
140
|
-
const diffPngBase64 = `data:image/png;base64,${diffPngBuffer.toString('base64')}`;
|
|
141
|
-
console.log(`Number of different pixels: ${numDiffPixels}`);
|
|
172
|
+
// Remove NaN coordinates
|
|
173
|
+
const cleaned = removeNanCoordinates('<svg><path d="M 10,20 nan L 30,40" /></svg>');
|
|
142
174
|
```
|
|
143
175
|
|
|
144
|
-
###
|
|
145
|
-
Converts an SVG file to PNG format.
|
|
176
|
+
### Content Analysis
|
|
146
177
|
|
|
147
178
|
```typescript
|
|
148
|
-
|
|
149
|
-
import { svg2Png } from 'svg-toolbox';
|
|
150
|
-
|
|
151
|
-
const svgPath = 'path/to/input/image.svg';
|
|
152
|
-
const pngPath = 'path/to/output/image.png';
|
|
153
|
-
const scale = 2; // Scaling factor
|
|
179
|
+
import { extractColors, getPathStatistics } from 'svg-toolbox';
|
|
154
180
|
|
|
155
|
-
|
|
181
|
+
// Extract colors
|
|
182
|
+
const colors = extractColors('<svg><circle fill="red" stroke="blue" /></svg>');
|
|
156
183
|
|
|
157
|
-
//
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
console.log(pngBase64);
|
|
184
|
+
// Get path statistics
|
|
185
|
+
const stats = getPathStatistics('<svg><path d="M 10,20 L 30,40 Z" /></svg>');
|
|
186
|
+
console.log(`Paths: ${stats.totalPaths}, Commands: ${stats.totalCommands}`);
|
|
161
187
|
```
|
|
162
188
|
|
|
163
|
-
|
|
164
|
-
Parses and normalizes the d attribute of all path elements in an SVG content.
|
|
189
|
+
## API Documentation
|
|
165
190
|
|
|
166
|
-
|
|
167
|
-
|
|
191
|
+
For detailed API documentation, please refer to [TypeScript type definitions](./src/types/index.ts) and source code comments.
|
|
192
|
+
|
|
193
|
+
## Development
|
|
168
194
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
195
|
+
```bash
|
|
196
|
+
# Install dependencies
|
|
197
|
+
npm install
|
|
198
|
+
|
|
199
|
+
# Run tests
|
|
200
|
+
npm test
|
|
201
|
+
|
|
202
|
+
# Build project
|
|
203
|
+
npm run build
|
|
172
204
|
|
|
205
|
+
# Watch mode testing
|
|
206
|
+
npm run test:watch
|
|
207
|
+
|
|
208
|
+
# Generate coverage report
|
|
209
|
+
npm run test:coverage
|
|
173
210
|
```
|
|
174
211
|
|
|
175
212
|
## License
|
|
213
|
+
|
|
176
214
|
MIT License
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { extractColors } from '../colors';
|
|
2
|
+
import { createSVGElement } from '../../core/element';
|
|
3
|
+
describe('Color Analysis', () => {
|
|
4
|
+
describe('extractColors', () => {
|
|
5
|
+
it('should extract fill colors', () => {
|
|
6
|
+
const svgContent = '<svg><circle fill="red" /><rect fill="blue" /></svg>';
|
|
7
|
+
const colors = extractColors(svgContent);
|
|
8
|
+
expect(colors.length).toBeGreaterThan(0);
|
|
9
|
+
expect(colors.some(c => c.fill === 'red')).toBe(true);
|
|
10
|
+
expect(colors.some(c => c.fill === 'blue')).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
it('should extract stroke colors', () => {
|
|
13
|
+
const svgContent = '<svg><path stroke="green" stroke-width="2" /></svg>';
|
|
14
|
+
const colors = extractColors(svgContent);
|
|
15
|
+
expect(colors.some(c => c.stroke === 'green')).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
it('should extract opacity values', () => {
|
|
18
|
+
const svgContent = '<svg><circle fill="red" opacity="0.5" /></svg>';
|
|
19
|
+
const colors = extractColors(svgContent);
|
|
20
|
+
const redColor = colors.find(c => c.fill === 'red');
|
|
21
|
+
expect(redColor?.opacity).toBe(0.5);
|
|
22
|
+
});
|
|
23
|
+
it('should ignore transparent and none values', () => {
|
|
24
|
+
const svgContent = '<svg><circle fill="none" stroke="transparent" /><rect fill="red" /></svg>';
|
|
25
|
+
const colors = extractColors(svgContent);
|
|
26
|
+
expect(colors.some(c => c.fill === 'none')).toBe(false);
|
|
27
|
+
expect(colors.some(c => c.stroke === 'transparent')).toBe(false);
|
|
28
|
+
expect(colors.some(c => c.fill === 'red')).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
it('should work with SVG element input', () => {
|
|
31
|
+
const svgContent = '<svg><circle fill="purple" /></svg>';
|
|
32
|
+
const element = createSVGElement(svgContent);
|
|
33
|
+
const colors = extractColors(element);
|
|
34
|
+
expect(colors.some(c => c.fill === 'purple')).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it('should handle nested elements', () => {
|
|
37
|
+
const svgContent = '<svg><g><circle fill="red" /><rect fill="blue" /></g></svg>';
|
|
38
|
+
const colors = extractColors(svgContent);
|
|
39
|
+
expect(colors.some(c => c.fill === 'red')).toBe(true);
|
|
40
|
+
expect(colors.some(c => c.fill === 'blue')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# 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,71 @@
|
|
|
1
|
+
import { parsePathData, analyzePaths, getPathStatistics } from '../paths';
|
|
2
|
+
import { createSVGElement } from '../../core/element';
|
|
3
|
+
describe('Path Analysis', () => {
|
|
4
|
+
describe('parsePathData', () => {
|
|
5
|
+
it('should parse simple path commands', () => {
|
|
6
|
+
const pathData = 'M 10,20 L 30,40 Z';
|
|
7
|
+
const commands = parsePathData(pathData);
|
|
8
|
+
expect(commands.length).toBe(3);
|
|
9
|
+
expect(commands[0].type).toBe('M');
|
|
10
|
+
expect(commands[0].params).toEqual([10, 20]);
|
|
11
|
+
expect(commands[1].type).toBe('L');
|
|
12
|
+
expect(commands[2].type).toBe('Z');
|
|
13
|
+
});
|
|
14
|
+
it('should handle lowercase commands', () => {
|
|
15
|
+
const pathData = 'm 10,20 l 30,40 z';
|
|
16
|
+
const commands = parsePathData(pathData);
|
|
17
|
+
expect(commands.length).toBe(3);
|
|
18
|
+
expect(commands[0].type).toBe('m');
|
|
19
|
+
});
|
|
20
|
+
it('should handle multiple parameters', () => {
|
|
21
|
+
const pathData = 'M 10,20 L 30,40 50,60';
|
|
22
|
+
const commands = parsePathData(pathData);
|
|
23
|
+
expect(commands[1].params.length).toBe(4);
|
|
24
|
+
});
|
|
25
|
+
it('should handle cubic bezier commands', () => {
|
|
26
|
+
const pathData = 'M 10,20 C 20,30 40,50 60,70';
|
|
27
|
+
const commands = parsePathData(pathData);
|
|
28
|
+
expect(commands.length).toBe(2);
|
|
29
|
+
expect(commands[1].type).toBe('C');
|
|
30
|
+
expect(commands[1].params.length).toBe(6);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('analyzePaths', () => {
|
|
34
|
+
it('should analyze all paths in SVG', () => {
|
|
35
|
+
const svgContent = '<svg><path id="path1" d="M 10,20 L 30,40" /><path id="path2" d="M 50,60 L 70,80" /></svg>';
|
|
36
|
+
const analysis = analyzePaths(svgContent);
|
|
37
|
+
expect(analysis.size).toBe(2);
|
|
38
|
+
expect(analysis.has('path1')).toBe(true);
|
|
39
|
+
expect(analysis.has('path2')).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('should use index as id if path has no id', () => {
|
|
42
|
+
const svgContent = '<svg><path d="M 10,20" /><path d="M 30,40" /></svg>';
|
|
43
|
+
const analysis = analyzePaths(svgContent);
|
|
44
|
+
expect(analysis.has('path-0')).toBe(true);
|
|
45
|
+
expect(analysis.has('path-1')).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it('should work with SVG element input', () => {
|
|
48
|
+
const svgContent = '<svg><path d="M 10,20 L 30,40" /></svg>';
|
|
49
|
+
const element = createSVGElement(svgContent);
|
|
50
|
+
const analysis = analyzePaths(element);
|
|
51
|
+
expect(analysis.size).toBe(1);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('getPathStatistics', () => {
|
|
55
|
+
it('should return correct statistics', () => {
|
|
56
|
+
const svgContent = '<svg><path d="M 10,20 L 30,40 Z" /><path d="M 50,60 L 70,80" /></svg>';
|
|
57
|
+
const stats = getPathStatistics(svgContent);
|
|
58
|
+
expect(stats.totalPaths).toBe(2);
|
|
59
|
+
expect(stats.totalCommands).toBeGreaterThan(0);
|
|
60
|
+
expect(stats.commandTypes['M']).toBeGreaterThan(0);
|
|
61
|
+
expect(stats.commandTypes['L']).toBeGreaterThan(0);
|
|
62
|
+
});
|
|
63
|
+
it('should count command types correctly', () => {
|
|
64
|
+
const svgContent = '<svg><path d="M 10,20 M 30,40 L 50,60 L 70,80" /></svg>';
|
|
65
|
+
const stats = getPathStatistics(svgContent);
|
|
66
|
+
expect(stats.commandTypes['M']).toBe(2);
|
|
67
|
+
expect(stats.commandTypes['L']).toBe(2);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# 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,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG color analysis utilities
|
|
3
|
+
*/
|
|
4
|
+
import { JSDOM } from 'jsdom';
|
|
5
|
+
import { serializeSVG } from '../core/element';
|
|
6
|
+
import { isValidSvgString } from '../utils/validation';
|
|
7
|
+
/**
|
|
8
|
+
* Extracts all colors used in an SVG
|
|
9
|
+
*/
|
|
10
|
+
export function extractColors(svgContent) {
|
|
11
|
+
const svgString = isValidSvgString(svgContent)
|
|
12
|
+
? svgContent
|
|
13
|
+
: serializeSVG(svgContent);
|
|
14
|
+
const dom = new JSDOM(svgString, {
|
|
15
|
+
contentType: 'image/svg+xml'
|
|
16
|
+
});
|
|
17
|
+
const document = dom.window.document;
|
|
18
|
+
const svgElement = document.querySelector('svg');
|
|
19
|
+
if (!svgElement) {
|
|
20
|
+
throw new Error('No SVG element found in the provided content.');
|
|
21
|
+
}
|
|
22
|
+
const colors = [];
|
|
23
|
+
const colorSet = new Set();
|
|
24
|
+
function extractFromElement(element) {
|
|
25
|
+
const fill = element.getAttribute('fill');
|
|
26
|
+
const stroke = element.getAttribute('stroke');
|
|
27
|
+
const opacity = element.getAttribute('opacity');
|
|
28
|
+
if (fill && fill !== 'none' && fill !== 'transparent') {
|
|
29
|
+
const colorKey = `${fill}-${opacity || '1'}`;
|
|
30
|
+
if (!colorSet.has(colorKey)) {
|
|
31
|
+
colorSet.add(colorKey);
|
|
32
|
+
colors.push({
|
|
33
|
+
fill,
|
|
34
|
+
opacity: opacity ? parseFloat(opacity) : undefined
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (stroke && stroke !== 'none' && stroke !== 'transparent') {
|
|
39
|
+
const colorKey = `stroke-${stroke}-${opacity || '1'}`;
|
|
40
|
+
if (!colorSet.has(colorKey)) {
|
|
41
|
+
colorSet.add(colorKey);
|
|
42
|
+
colors.push({
|
|
43
|
+
stroke,
|
|
44
|
+
opacity: opacity ? parseFloat(opacity) : undefined
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
Array.from(element.children).forEach(child => {
|
|
49
|
+
extractFromElement(child);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
extractFromElement(svgElement);
|
|
53
|
+
return colors;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/analyze/colors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAqB,MAAM,qBAAqB,CAAC;AAG1E;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,UAA4B;IACxD,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC;QAC5C,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IAE7B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE;QAC/B,WAAW,EAAE,eAAe;KAC7B,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;IACrC,MAAM,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,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,SAAS,kBAAkB,CAAC,OAAgB;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAEhD,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,OAAO,IAAI,GAAG,EAAE,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;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,MAAM,QAAQ,GAAG,UAAU,MAAM,IAAI,OAAO,IAAI,GAAG,EAAE,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;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,KAAK,CAAC,EAAE;YAC3C,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
|
+
};
|