Skip to content

Commit

Permalink
Add mergeStyles plugin (#1381)
Browse files Browse the repository at this point in the history
  • Loading branch information
strarsis authored Mar 27, 2021
1 parent d89d36e commit 19c77d2
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 6 deletions.
20 changes: 16 additions & 4 deletions lib/css-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ function csstreeToStyleDeclaration(declaration) {
* @return {string} CSS string or empty array if no styles are set
*/
function getCssStr(elem) {
if (elem.children[0].type === 'text' || elem.children[0].type === 'cdata') {
if (
elem.children.length > 0 &&
(elem.children[0].type === 'text' || elem.children[0].type === 'cdata')
) {
return elem.children[0].value;
}
return '';
Expand All @@ -203,10 +206,19 @@ function getCssStr(elem) {
* @return {string} reference to field with CSS
*/
function setCssStr(elem, css) {
if (elem.children[0].type === 'text' || elem.children[0].type === 'cdata') {
elem.children[0].value = css;
return elem.children[0].value;
if (elem.children.length === 0) {
elem.children.push({
type: 'text',
value: '',
});
}

if (elem.children[0].type !== 'text' && elem.children[0].type !== 'cdata') {
return css;
}

elem.children[0].value = css;

return css;
}

Expand Down
1 change: 1 addition & 0 deletions lib/svgo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const pluginsOrder = [
'removeXMLNS',
'removeEditorsNSData',
'cleanupAttrs',
'mergeStyles',
'inlineStyles',
'minifyStyles',
'convertStyleToAttrs',
Expand Down
87 changes: 87 additions & 0 deletions plugins/mergeStyles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use strict';

const { querySelectorAll, closestByName } = require('../lib/xast.js');
const { getCssStr, setCssStr } = require('../lib/css-tools');

exports.type = 'full';
exports.active = true;
exports.description = 'merge multiple style elements into one';

/**
* Merge multiple style elements into one.
*
* @param {Object} document document element
*
* @author strarsis <strarsis@gmail.com>
*/
exports.fn = function (document) {
// collect <style/>s with valid type attribute (preserve order)
const styleElements = querySelectorAll(document, 'style');

// no <styles/>s, nothing to do
if (styleElements.length === 0) {
return document;
}

const styles = [];
for (const styleElement of styleElements) {
if (
styleElement.attributes.type &&
styleElement.attributes.type !== 'text/css'
) {
// skip <style> with invalid type attribute
continue;
}

if (closestByName(styleElement, 'foreignObject')) {
// skip <foreignObject> content
continue;
}

const cssString = getCssStr(styleElement);

styles.push({
styleElement: styleElement,

mq: styleElement.attributes.media,
cssStr: cssString,
});
}

const collectedStyles = [];
for (let styleNo = 0; styleNo < styles.length; styleNo += 1) {
const style = styles[styleNo];

if (style.mq) {
const wrappedStyles = `@media ${style.mq}{${style.cssStr}}`;
collectedStyles.push(wrappedStyles);
} else {
collectedStyles.push(style.cssStr);
}

// remove all processed style elements – except the first one
if (styleNo > 0) {
removeFromParent(style.styleElement);
}
}
const collectedStylesString = collectedStyles.join('');

// combine collected styles in the first style element
const firstStyle = styles[0];
delete firstStyle.styleElement.attributes.media; // remove media mq attribute as CSS media queries are used
if (collectedStylesString.trim().length > 0) {
setCssStr(firstStyle.styleElement, collectedStylesString);
} else {
removeFromParent(firstStyle.styleElement);
}

return document;
};

function removeFromParent(element) {
const parentElement = element.parentNode;
return parentElement.children.splice(
parentElement.children.indexOf(element),
1
);
}
1 change: 1 addition & 0 deletions plugins/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exports.convertPathData = require('./convertPathData.js');
exports.convertShapeToPath = require('./convertShapeToPath.js');
exports.convertStyleToAttrs = require('./convertStyleToAttrs.js');
exports.convertTransform = require('./convertTransform.js');
exports.mergeStyles = require('./mergeStyles.js');
exports.inlineStyles = require('./inlineStyles.js');
exports.mergePaths = require('./mergePaths.js');
exports.minifyStyles = require('./minifyStyles.js');
Expand Down
4 changes: 2 additions & 2 deletions test/config/_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ describe('config', function () {
(item) => item.name === 'cleanupIDs'
);
it('should preserve internal plugins order', () => {
expect(removeAttrsIndex).to.equal(40);
expect(cleanupIDsIndex).to.equal(10);
expect(removeAttrsIndex).to.equal(41);
expect(cleanupIDsIndex).to.equal(11);
});
it('should activate inactive by default plugins', () => {
const removeAttrsPlugin = resolvePluginConfig(
Expand Down
19 changes: 19 additions & 0 deletions test/plugins/mergeStyles.01.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions test/plugins/mergeStyles.02.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions test/plugins/mergeStyles.03.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions test/plugins/mergeStyles.04.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions test/plugins/mergeStyles.05.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions test/plugins/mergeStyles.06.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions test/plugins/mergeStyles.07.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions test/plugins/mergeStyles.08.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions test/plugins/mergeStyles.09.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions test/plugins/mergeStyles.10.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 19c77d2

Please sign in to comment.