Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow choosing EOL and appending final newline #1546

Merged
merged 7 commits into from Sep 11, 2021
116 changes: 116 additions & 0 deletions lib/svgo.test.js
Expand Up @@ -64,6 +64,122 @@ test('allow to disable and customize plugins in preset', () => {
`);
});

describe('allow to configure EOL', () => {
test('should respect EOL set to LF', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, {
js2svg: { eol: 'lf', pretty: true, indent: 2 },
});
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120">\n <circle fill="red" cx="60" cy="60" r="50"/>\n</svg>\n'
);
});

test('should respect EOL set to CRLF', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, {
js2svg: { eol: 'crlf', pretty: true, indent: 2 },
});
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120">\r\n <circle fill="red" cx="60" cy="60" r="50"/>\r\n</svg>\r\n'
);
});

test('should default to LF line break for any other EOL values', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, {
js2svg: { eol: 'invalid', pretty: true, indent: 2 },
});
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120">\n <circle fill="red" cx="60" cy="60" r="50"/>\n</svg>\n'
);
});
});

describe('allow to configure final newline', () => {
test('should not add final newline when unset', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, { js2svg: { eol: 'lf' } });
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120"><circle fill="red" cx="60" cy="60" r="50"/></svg>'
);
});

test('should add final newline when set', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, {
js2svg: { finalNewline: true, eol: 'lf' },
});
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120"><circle fill="red" cx="60" cy="60" r="50"/></svg>\n'
);
});

test('should not add extra newlines when using pretty: true', () => {
const svg = `
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 120 120">
<desc>
Not standard description
</desc>
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
</svg>
`;
const { data } = optimize(svg, {
js2svg: { finalNewline: true, pretty: true, indent: 2, eol: 'lf' },
});
// using toEqual because line endings matter in these tests
expect(data).toEqual(
'<svg viewBox="0 0 120 120">\n <circle fill="red" cx="60" cy="60" r="50"/>\n</svg>\n'
);
});
});

test('allow to customize precision for preset', () => {
const svg = `
<svg viewBox="0 0 120 120">
Expand Down
26 changes: 26 additions & 0 deletions lib/svgo/coa.js
Expand Up @@ -54,6 +54,11 @@ module.exports = function makeProgram(program) {
)
.option('--pretty', 'Make SVG pretty printed')
.option('--indent <INTEGER>', 'Indent number when pretty printing SVGs')
.option(
'--eol <EOL>',
'Line break to use when outputting SVG: lf, crlf. If unspecified, uses platform default.'
)
.option('--final-newline', 'Ensure SVG ends with a line break')
.option(
'-r, --recursive',
"Use with '--folder'. Optimizes *.svg files in folders recursively."
Expand Down Expand Up @@ -112,6 +117,15 @@ async function action(args, opts, command) {
}
}

if (opts.eol != null) {
adalinesimonian marked this conversation as resolved.
Show resolved Hide resolved
if (opts.eol !== 'lf' && opts.eol !== 'crlf') {
console.error(
"error: option '--eol' must have one of the following values: 'lf' or 'crlf'"
);
process.exit(1);
}
}

// --show-plugins
if (opts.showPlugins) {
showAvailablePlugins();
Expand Down Expand Up @@ -185,6 +199,18 @@ async function action(args, opts, command) {
}
}

// --eol
if (opts.eol) {
config.js2svg = config.js2svg || {};
config.js2svg.eol = opts.eol;
}

// --final-newline
if (opts.finalNewline) {
config.js2svg = config.js2svg || {};
config.js2svg.finalNewline = true;
}

// --output
if (output) {
if (input.length && input[0] != '-') {
Expand Down
35 changes: 26 additions & 9 deletions lib/svgo/js2svg.js
@@ -1,6 +1,6 @@
'use strict';

var EOL = require('os').EOL,
var platformEOL = require('os').EOL,
textElems = require('../../plugins/_collections.js').textElems;

var defaults = {
Expand Down Expand Up @@ -28,6 +28,8 @@ var defaults = {
encodeEntity: encodeEntity,
pretty: false,
useShortTags: true,
eol: platformEOL === '\r\n' ? 'crlf' : 'lf',
finalNewline: false,
};

var entities = {
Expand Down Expand Up @@ -64,15 +66,21 @@ function JS2SVG(config) {
this.config.indent = ' ';
}

if (this.config.eol === 'crlf') {
this.eol = '\r\n';
} else {
this.eol = '\n';
}
adalinesimonian marked this conversation as resolved.
Show resolved Hide resolved

if (this.config.pretty) {
this.config.doctypeEnd += EOL;
this.config.procInstEnd += EOL;
this.config.commentEnd += EOL;
this.config.cdataEnd += EOL;
this.config.tagShortEnd += EOL;
this.config.tagOpenEnd += EOL;
this.config.tagCloseEnd += EOL;
this.config.textEnd += EOL;
this.config.doctypeEnd += this.eol;
this.config.procInstEnd += this.eol;
this.config.commentEnd += this.eol;
this.config.cdataEnd += this.eol;
this.config.tagShortEnd += this.eol;
this.config.tagOpenEnd += this.eol;
this.config.tagCloseEnd += this.eol;
this.config.textEnd += this.eol;
}

this.indentLevel = 0;
Expand Down Expand Up @@ -118,6 +126,15 @@ JS2SVG.prototype.convert = function (data) {

this.indentLevel--;

if (
this.config.finalNewline &&
this.indentLevel === 0 &&
svg.length > 0 &&
svg[svg.length - 1] !== '\n'
adalinesimonian marked this conversation as resolved.
Show resolved Hide resolved
) {
svg += this.eol;
}

return {
data: svg,
info: {
Expand Down