diff --git a/.editorconfig b/.editorconfig index db401d026..e567937ee 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = true +insert_final_newline = false [Makefile] indent_style = tab diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9dc6e4947..42acb1d56 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: node-version: [8.x, 10.x, 12.x] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: diff --git a/lib/svgo.js b/lib/svgo.js index 7d6c2fa31..f002353ae 100755 --- a/lib/svgo.js +++ b/lib/svgo.js @@ -23,6 +23,8 @@ var SVGO = function(config) { SVGO.prototype.optimize = function(svgstr, info) { info = info || {}; + info.multipassCount = 0; + return new Promise((resolve, reject) => { if (this.config.error) { reject(this.config.error); @@ -39,8 +41,8 @@ SVGO.prototype.optimize = function(svgstr, info) { return; } - info.multipassCount = counter; - if (++counter < maxPassCount && svgjs.data.length < prevResultSize) { + var numberOfPasses = info.multipassCount = ++counter; + if (numberOfPasses < maxPassCount && svgjs.data.length < prevResultSize) { prevResultSize = svgjs.data.length; this._optimizeOnce(svgjs.data, info, optimizeOnceCallback); } else { diff --git a/test/coa/_index.js b/test/coa/_index.js index ada38de1d..c3908feaa 100644 --- a/test/coa/_index.js +++ b/test/coa/_index.js @@ -1,12 +1,20 @@ 'use strict'; const fs = require('fs'), + yaml = require('js-yaml'), svgo = require(process.env.COVERAGE ? '../../lib-cov/svgo/coa.js' : '../../lib/svgo/coa.js').api, + defaults = Object.assign({}, yaml.safeLoad(fs.readFileSync(__dirname + '/../../.svgo.yml', 'utf8'))), path = require('path'), svgPath = path.resolve(__dirname, 'test.svg'), svgFolderPath = path.resolve(__dirname, 'testSvg'), + prefixIdsFolderPath = path.resolve(__dirname, 'testPrefixIds'), + prefixIdsSvgInPath = path.resolve(prefixIdsFolderPath, 'in.svg'), + mpDirPath = path.resolve(__dirname, 'testMultipass'), + mpSvgInPath = path.resolve(mpDirPath, 'in.svg'), + mpSvgExpPath = path.resolve(mpDirPath, 'out.svg'), + mpSvgExp = fs.readFileSync(mpSvgExpPath, 'utf8'), svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively'), svgFiles = [path.resolve(__dirname, 'testSvg/test.svg'), path.resolve(__dirname, 'testSvg/test.1.svg')], tempFolder = 'temp', @@ -157,6 +165,79 @@ describe('coa', function() { } }); + it('should pass the filename to the prefixIds plugin', function(done) { + svgo({ + input: prefixIdsSvgInPath, + output: 'temp.svg', + quiet: true, + multipass: false, + disable: defaults.plugins, // disable all plugins except ... + enable: [ 'prefixIds' ] // ... prefixIds + }).then(function() { + const svgOut = fs.readFileSync('temp.svg', 'utf8'); + + done(/in_svg__/.test(svgOut) ? null : 'filename isn\'t passed to prefixIds plugin.'); + fse.removeSync('temp.svg'); + }, error => done(error)); + }); + + describe('multipass', function() { + it('should optimize using multiple passes with multipass enabled', function(done) { + svgo({ + input: mpSvgInPath, + output: 'temp.svg', + quiet: true, + multipass: true + }).then(function() { + const mpSvgOut = fs.readFileSync('temp.svg', 'utf8'); + done(mpSvgOut === mpSvgExp ? null : 'Multipass wasn\'t properly used.'); + fse.removeSync('temp.svg'); + }, error => done(error)); + }); + + it('should allow prefixId plugin to detect subsequent passes with multipass enabled', function(done) { + svgo({ + input: mpSvgInPath, + output: 'temp.svg', + quiet: true, + multipass: true, + disable: defaults.plugins, // disable all plugins except ... + enable: [ 'prefixIds' ] // ... prefixIds + }).then(function() { + const mpSvgOut = fs.readFileSync('temp.svg', 'utf8'); + + done(!/in_svg__in_svg__/.test(mpSvgOut) ? null : 'prefixIds plugin doesn\'t detect subsequent passes with multipass enabled.'); + + // https://github.com/svg/svgo/issues/659 + // https://github.com/svg/svgo/issues/1133 + fse.removeSync('temp.svg'); + }, error => done(error)); + }); + + it('should allow addAttributesToSVGElement plugin to correctly handle subsequent passes with multipass enabled', function(done) { + svgo({ + input: mpSvgInPath, + output: 'temp.svg', + quiet: true, + multipass: true, + config: `{ + "plugins": [{ "addAttributesToSVGElement": { + "attribute": "aria-hidden=\\"true\\"" + } }] + }` + }).then(function() { + const mpSvgOut = fs.readFileSync('temp.svg', 'utf8'); + + done(!/aria-hidden="true" aria-hidden='true'/.test(mpSvgOut) ? null : 'addAttributesToSVGElement plugin doesn\'t correctly handle subsequent passes with multipass enabled.'); + + // https://github.com/svg/svgo/issues/659 + // https://github.com/svg/svgo/issues/1133 + fse.removeSync('temp.svg'); + }, error => done(error)); + }); + }); + + describe('stdout', function() { it('should show file content when no output set', function(done) { replaceConsoleLog(); diff --git a/test/coa/testMultipass/in.svg b/test/coa/testMultipass/in.svg new file mode 100644 index 000000000..e4426ec7f --- /dev/null +++ b/test/coa/testMultipass/in.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/coa/testMultipass/out.svg b/test/coa/testMultipass/out.svg new file mode 100644 index 000000000..36dc90338 --- /dev/null +++ b/test/coa/testMultipass/out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/coa/testPrefixIds/in.svg b/test/coa/testPrefixIds/in.svg new file mode 100644 index 000000000..108ff654a --- /dev/null +++ b/test/coa/testPrefixIds/in.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/test/svgo/_index.js b/test/svgo/_index.js index 327c5de72..b9e788d56 100644 --- a/test/svgo/_index.js +++ b/test/svgo/_index.js @@ -9,9 +9,7 @@ var FS = require('fs'), '../../lib/svgo'); describe('indentation', function() { - it('should create indent with 2 spaces', function(done) { - var filepath = PATH.resolve(__dirname, './test.svg'), svgo; @@ -34,13 +32,39 @@ describe('indentation', function() { normalize(result.data).should.be.equal(should); done(); }); - }); - }); +}); + +describe('invocation', function() { + it('should optimize without an info object', function(done) { + var filepath = PATH.resolve(__dirname, './test.svg'), + svgo; + FS.readFile(filepath, 'utf8', function(err, data) { + if (err) { + throw err; + } + + var splitted = normalize(data).split(/\s*@@@\s*/), + orig = splitted[0], + should = splitted[1]; + + svgo = new SVGO({ + full : true, + plugins : [], + js2svg : { pretty: true, indent: 2 } + }); + + svgo.optimize(orig, undefined).then(function(result) { + normalize(result.data).should.be.equal(should); + done(); + }); + }); + }); }); + function normalize(file) { return file.trim().replace(regEOL, '\n'); }