diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index e09ac4c74..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# These are supported funding model platforms - -open_collective: svgo diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 7a6e08a62..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -# Security Policy - -## Reporting a Vulnerability - -Please report security vulnerabilities to [trysound@yandex.ru](mailto:trysound@yandex.ru). diff --git a/docs/03-plugins/convert-path-data.mdx b/docs/03-plugins/convert-path-data.mdx index 23ca9e7e0..66848688f 100644 --- a/docs/03-plugins/convert-path-data.mdx +++ b/docs/03-plugins/convert-path-data.mdx @@ -30,6 +30,9 @@ svgo: transformPrecision: description: Number of decimal places to round to, using conventional rounding rules. default: 5 + smartArcRounding: + description: Round the radius of circular arcs when the effective change is under the error. The effective change is determined using the sagitta of the arc. + default: true removeUseless: description: Remove redundant path commands that don't draw anything. default: true diff --git a/docs/03-plugins/merge-text.mdx b/docs/03-plugins/merge-text.mdx new file mode 100644 index 000000000..38b19d2ae --- /dev/null +++ b/docs/03-plugins/merge-text.mdx @@ -0,0 +1,15 @@ +--- +title: Merge Text +svgo: + pluginId: mergeText +--- + +Merge adjacent `` elements and remove `` when it is the only child of a `` element. + +If the SVG contains any ` + + +@@@ + + + this is a test + + diff --git a/test/plugins/mergeText.07.svg b/test/plugins/mergeText.07.svg new file mode 100644 index 000000000..0b2284a19 --- /dev/null +++ b/test/plugins/mergeText.07.svg @@ -0,0 +1,20 @@ +Do not collapse if present. + +=== + + + + + this is a test + + + +@@@ + + + + + this is a test + + diff --git a/test/plugins/mergeText.08.svg b/test/plugins/mergeText.08.svg new file mode 100644 index 000000000..2feb9474f --- /dev/null +++ b/test/plugins/mergeText.08.svg @@ -0,0 +1,17 @@ +Don't merge elements with children. + +=== + +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 210 120"> + <text xml:space="preserve" x="45.869" y="38.606" fill="red" stroke-width=".265" font-family="Sans" font-size="6.35"> + <tspan x="45.869" y="38.606"><title>xxxPart one + + + +@@@ + + + + xxxPart one + + diff --git a/test/plugins/prefixIds.test.js b/test/plugins/prefixIds.test.js index 97f1a8fd1..8ae2b33b8 100644 --- a/test/plugins/prefixIds.test.js +++ b/test/plugins/prefixIds.test.js @@ -8,17 +8,17 @@ test('should extract prefix from path basename', () => { optimize(svg, { plugins: ['prefixIds'], }).data, - ).toEqual(``); + ).toBe(``); expect( optimize(svg, { plugins: ['prefixIds'], path: 'input.svg', }).data, - ).toEqual(``); + ).toBe(``); expect( optimize(svg, { plugins: ['prefixIds'], path: 'path/to/input.svg', }).data, - ).toEqual(``); + ).toBe(``); }); diff --git a/test/regression-extract.js b/test/regression-extract.js index 2c0e6232f..e5a594e65 100644 --- a/test/regression-extract.js +++ b/test/regression-extract.js @@ -73,7 +73,7 @@ const extractTarGz = async (url, baseDir, include) => { (async () => { try { - console.info('Download W3C SVG 1.1 Test Suite and extract SVG files'); + console.info('Downloading W3C SVG 1.1 Test Suite and extracting files'); await extractTarGz( 'https://www.w3.org/Graphics/SVG/Test/20110816/archives/W3C_SVG_11_TestSuite.tar.gz', path.join(__dirname, 'regression-fixtures', 'w3c-svg-11-test-suite'), diff --git a/test/svg2js/_index.test.js b/test/svg2js/_index.test.js index 77c9075fd..ece064284 100644 --- a/test/svg2js/_index.test.js +++ b/test/svg2js/_index.test.js @@ -22,7 +22,7 @@ describe('svg2js', function () { describe('root', function () { it('should exist', function () { - expect(root).toEqual(expect.anything()); + expect(root).toStrictEqual(expect.anything()); }); it('should be an instance of Object', function () { @@ -45,7 +45,7 @@ describe('svg2js', function () { }); it('the first node should be instruction', () => { - expect(root.children[0]).toEqual({ + expect(root.children[0]).toStrictEqual({ type: 'instruction', name: 'xml', value: 'version="1.0" encoding="utf-8"', @@ -53,7 +53,7 @@ describe('svg2js', function () { }); it('the second node should be comment', () => { - expect(root.children[1]).toEqual({ + expect(root.children[1]).toStrictEqual({ type: 'comment', value: 'Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)', @@ -61,7 +61,7 @@ describe('svg2js', function () { }); it('the third node should be doctype', () => { - expect(root.children[2]).toEqual({ + expect(root.children[2]).toStrictEqual({ type: 'doctype', name: 'svg', data: { @@ -73,7 +73,7 @@ describe('svg2js', function () { describe('name', function () { it('should have property name: "svg"', function () { - expect(root.children[3]).toEqual( + expect(root.children[3]).toStrictEqual( expect.objectContaining({ name: 'svg', }), @@ -83,7 +83,7 @@ describe('svg2js', function () { describe('children', function () { it('should exist', function () { - expect(root.children[3].children).toEqual(expect.anything()); + expect(root.children[3].children).toStrictEqual(expect.anything()); }); it('should be an instance of Array', function () { @@ -98,7 +98,7 @@ describe('svg2js', function () { describe('text nodes', function () { it('should contain preserved whitespace', function () { const textNode = root.children[3].children[1].children[0].children[1]; - expect(textNode.children[0].value).toEqual(' test '); + expect(textNode.children[0].value).toBe(' test '); }); }); }); diff --git a/test/svgo/_index.test.js b/test/svgo/_index.test.js index a9e5f06c7..9d922852d 100644 --- a/test/svgo/_index.test.js +++ b/test/svgo/_index.test.js @@ -24,24 +24,24 @@ describe('svgo', () => { plugins: [], js2svg: { pretty: true, indent: 2 }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should handle plugins order properly', async () => { const [original, expected] = await parseFixture('plugins-order.svg'); const result = optimize(original, { path: 'input.svg' }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should handle empty svg tag', async () => { const result = optimize('', { path: 'input.svg' }); - expect(result.data).toEqual(''); + expect(result.data).toBe(''); }); it('should preserve style specificity over attributes', async () => { - const [original, expected] = await parseFixture('style-specifity.svg'); + const [original, expected] = await parseFixture('style-specificity.svg'); const result = optimize(original, { path: 'input.svg', js2svg: { pretty: true }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should inline entities', async () => { const [original, expected] = await parseFixture('entities.svg'); @@ -50,7 +50,7 @@ describe('svgo', () => { plugins: [], js2svg: { pretty: true }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should preserve whitespaces between tspan tags', async () => { const [original, expected] = await parseFixture('whitespaces.svg'); @@ -58,7 +58,7 @@ describe('svgo', () => { path: 'input.svg', js2svg: { pretty: true }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should preserve "to" keyframe selector', async () => { const [original, expected] = await parseFixture('keyframe-selectors.svg'); @@ -66,14 +66,14 @@ describe('svgo', () => { path: 'input.svg', js2svg: { pretty: true }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should not trim whitespace at start and end of pre element', async () => { const [original, expected] = await parseFixture('pre-element.svg'); const result = optimize(original, { path: 'input.svg', }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); it('should not add whitespace in pre element', async () => { const [original, expected] = await parseFixture('pre-element-pretty.svg'); @@ -81,6 +81,6 @@ describe('svgo', () => { path: 'input.svg', js2svg: { pretty: true }, }); - expect(normalize(result.data)).toEqual(expected); + expect(normalize(result.data)).toStrictEqual(expected); }); }); diff --git a/test/svgo/style-specifity.svg b/test/svgo/style-specificity.svg similarity index 100% rename from test/svgo/style-specifity.svg rename to test/svgo/style-specificity.svg diff --git a/yarn.lock b/yarn.lock index 8baf0bdf7..e6b23d23c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,19 +976,19 @@ __metadata: languageName: node linkType: hard -"@types/css-tree@npm:*, @types/css-tree@npm:^2.0.0": - version: 2.0.0 - resolution: "@types/css-tree@npm:2.0.0" - checksum: 52d89f5c52c6ec5feac674a3f28f35994211f26c662cc8718f21ebabad992329e8c810da1e070aa61c49f89e92cd5ef7b460e81de52f0d0f5973618d87ebc3ae +"@types/css-tree@npm:*, @types/css-tree@npm:^2.3.4": + version: 2.3.4 + resolution: "@types/css-tree@npm:2.3.4" + checksum: b06173d3ae048b74e7030cceae01d3d6e5589f7348e8e4b907427f91baeda76807bbde8c5be4c41e22b952268b46edcba7ab96e16efedb2d0b37ce2bf90d1835 languageName: node linkType: hard -"@types/csso@npm:~5.0.3": - version: 5.0.3 - resolution: "@types/csso@npm:5.0.3" +"@types/csso@npm:^5.0.4": + version: 5.0.4 + resolution: "@types/csso@npm:5.0.4" dependencies: "@types/css-tree": "*" - checksum: 3d299ea755732f9b913cfb3d94849e173cd1019559058af0a372aa1ca8f48a3c63aa74932fdfa2f2f25ee78255a115feaaec01ae4fe9578e76b7c4acd8ae3f2a + checksum: 606ea4de171e807ffc8908f7ffec774c8a40f3c81e7c60f8a84c7f5327eb00f3c9948b021b91e2e8fe3a76af4623ac58538780f0789f1e03947b7de96c5f7994 languageName: node linkType: hard @@ -1687,7 +1687,17 @@ __metadata: languageName: node linkType: hard -"css-tree@npm:^2.2.1, css-tree@npm:~2.2.0": +"css-tree@npm:^2.3.1": + version: 2.3.1 + resolution: "css-tree@npm:2.3.1" + dependencies: + mdn-data: 2.0.30 + source-map-js: ^1.0.1 + checksum: 493cc24b5c22b05ee5314b8a0d72d8a5869491c1458017ae5ed75aeb6c3596637dbe1b11dac2548974624adec9f7a1f3a6cf40593dc1f9185eb0e8279543fbc0 + languageName: node + linkType: hard + +"css-tree@npm:~2.2.0": version: 2.2.1 resolution: "css-tree@npm:2.2.1" dependencies: @@ -1704,7 +1714,7 @@ __metadata: languageName: node linkType: hard -"csso@npm:5.0.5": +"csso@npm:^5.0.5": version: 5.0.5 resolution: "csso@npm:5.0.5" dependencies: @@ -3390,6 +3400,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.30": + version: 2.0.30 + resolution: "mdn-data@npm:2.0.30" + checksum: d6ac5ac7439a1607df44b22738ecf83f48e66a0874e4482d6424a61c52da5cde5750f1d1229b6f5fa1b80a492be89465390da685b11f97d62b8adcc6e88189aa + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -4429,14 +4446,14 @@ __metadata: "@rollup/plugin-commonjs": ^22.0.2 "@rollup/plugin-node-resolve": ^14.1.0 "@trysound/sax": 0.2.0 - "@types/css-tree": ^2.0.0 - "@types/csso": ~5.0.3 + "@types/css-tree": ^2.3.4 + "@types/csso": ^5.0.4 "@types/jest": ^29.5.5 commander: ^7.2.0 css-select: ^5.1.0 - css-tree: ^2.2.1 + css-tree: ^2.3.1 css-what: ^6.1.0 - csso: 5.0.5 + csso: ^5.0.5 del: ^6.0.0 eslint: ^8.55.0 jest: ^29.5.5