Skip to content

Commit 9f084cc

Browse files
authored
Preserve whitespace in elements containing text (#1220)
1 parent 0021144 commit 9f084cc

12 files changed

+35
-42
lines changed

lib/svgo/js2svg.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
var EOL = require('os').EOL,
4-
textElem = require('../../plugins/_collections.js').elemsGroups.textContent.concat('title');
4+
textElems = require('../../plugins/_collections.js').textElems;
55

66
var defaults = {
77
doctypeStart: '<!DOCTYPE',
@@ -258,7 +258,7 @@ JS2SVG.prototype.createElem = function(data) {
258258
tagCloseStart = this.config.tagCloseStart,
259259
tagCloseEnd = this.config.tagCloseEnd,
260260
openIndent = this.createIndent(),
261-
textIndent = '',
261+
closeIndent = this.createIndent(),
262262
processedData = '',
263263
dataEnd = '';
264264

@@ -268,29 +268,27 @@ JS2SVG.prototype.createElem = function(data) {
268268
tagCloseStart = defaults.tagCloseStart;
269269
tagCloseEnd = defaults.tagCloseEnd;
270270
openIndent = '';
271-
} else if (data.isElem(textElem)) {
272-
if (this.config.pretty) {
273-
textIndent += openIndent + this.config.indent;
274-
}
271+
} else if (data.isElem(textElems)) {
272+
tagOpenEnd = defaults.tagOpenEnd;
273+
tagCloseStart = defaults.tagCloseStart;
274+
closeIndent = '';
275275
this.textContext = data;
276276
}
277277

278278
processedData += this.convert(data).data;
279279

280280
if (this.textContext == data) {
281281
this.textContext = null;
282-
if (this.config.pretty) dataEnd = EOL;
283282
}
284283

285284
return openIndent +
286285
tagOpenStart +
287286
data.elem +
288287
this.createAttrs(data) +
289288
tagOpenEnd +
290-
textIndent +
291289
processedData +
292290
dataEnd +
293-
this.createIndent() +
291+
closeIndent +
294292
tagCloseStart +
295293
data.elem +
296294
tagCloseEnd;

lib/svgo/svg2js.js

+4-21
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ var SAX = require('@trysound/sax'),
44
JSAPI = require('./jsAPI.js'),
55
CSSClassList = require('./css-class-list'),
66
CSSStyleDeclaration = require('./css-style-declaration'),
7+
textElems = require('../../plugins/_collections.js').textElems,
78
entityDeclaration = /<!ENTITY\s+(\S+)\s+(?:'([^']+)'|"([^"]+)")\s*>/g;
89

910
var config = {
1011
strict: true,
1112
trim: false,
12-
normalize: true,
13+
normalize: false,
1314
lowercase: true,
1415
xmlns: true,
1516
position: true
@@ -115,8 +116,8 @@ module.exports = function(data) {
115116
elem = pushToContent(elem);
116117
current = elem;
117118

118-
// Save info about <text> tag to prevent trimming of meaningful whitespace
119-
if (data.name == 'text' && !data.prefix) {
119+
// Save info about tags containing text to prevent trimming of meaningful whitespace
120+
if (textElems.includes(data.name) && !data.prefix) {
120121
textContext = current;
121122
}
122123

@@ -143,9 +144,7 @@ module.exports = function(data) {
143144

144145
var last = stack.pop();
145146

146-
// Trim text inside <text> tag.
147147
if (last == textContext) {
148-
trim(textContext);
149148
textContext = null;
150149
}
151150
current = stack[stack.length - 1];
@@ -168,20 +167,4 @@ module.exports = function(data) {
168167
return { error: e.message };
169168
}
170169

171-
function trim(elem) {
172-
if (!elem.content) return elem;
173-
174-
var start = elem.content[0],
175-
end = elem.content[elem.content.length - 1];
176-
177-
while (start && start.content && !start.text) start = start.content[0];
178-
if (start && start.text) start.text = start.text.replace(/^\s+/, '');
179-
180-
while (end && end.content && !end.text) end = end.content[end.content.length - 1];
181-
if (end && end.text) end.text = end.text.replace(/\s+$/, '');
182-
183-
return elem;
184-
185-
}
186-
187170
};

plugins/_collections.js

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ exports.elemsGroups = {
1515
filterPrimitive: ['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feFlood', 'feGaussianBlur', 'feImage', 'feMerge', 'feMorphology', 'feOffset', 'feSpecularLighting', 'feTile', 'feTurbulence']
1616
};
1717

18+
exports.textElems = exports.elemsGroups.textContent.concat('title');
19+
1820
exports.pathElems = ['path', 'glyph', 'missing-glyph'];
1921

2022
// http://www.w3.org/TR/SVG11/intro.html#Definitions

test/plugins/cleanupIDs.09.svg

+2-1
Loading

test/plugins/cleanupIDs.10.svg

+2-1
Loading

test/plugins/cleanupIDs.13.svg

+2-1
Loading

test/plugins/cleanupIDs.14.svg

+2-1
Loading

test/plugins/collapseGroups.13.svg

+2-1
Loading

test/plugins/inlineStyles.13.svg

+1-3
Loading

test/plugins/inlineStyles.16.svg

+1-3
Loading

test/svg2js/_index.js

+9
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ describe('svg2js', function() {
177177

178178
});
179179

180+
describe('text nodes', function() {
181+
182+
it('should contain preserved whitespace', function() {
183+
const textNode = root.content[3].content[1].content[0].content[1];
184+
return expect(textNode.content[0].text).to.equal(' test ');
185+
});
186+
187+
});
188+
180189
describe('API', function() {
181190

182191
describe('clone()', function() {

test/svg2js/test.svg

+1-1
Loading

0 commit comments

Comments
 (0)