1
0
mirror of https://github.com/svg/svgo.git synced 2025-08-01 18:46:52 +03:00

Remove hasAttr and hasAttrLocal usages (#1447)

In most cases simple check for null is enough.
This commit is contained in:
Bogdan Chadkin
2021-03-22 01:24:59 +03:00
committed by GitHub
parent 447f82ca6b
commit 316a002299
12 changed files with 122 additions and 87 deletions

View File

@ -296,7 +296,7 @@ JSAPI.prototype.computedAttr = function (name, val) {
if (val != null) { if (val != null) {
return elem ? elem.hasAttr(name, val) : false; return elem ? elem.hasAttr(name, val) : false;
} else if (elem && elem.hasAttr(name)) { } else if (elem && elem.hasAttr(name)) {
return elem.attrs[name].value; return elem.attributes[name];
} }
}; };

View File

@ -58,9 +58,11 @@ const applyTransforms = (elem, pathData, params) => {
let hasStrokeWidth = false; let hasStrokeWidth = false;
do { do {
if (idElem.hasAttr('stroke-width')) hasStrokeWidth = true; if (idElem.attributes['stroke-width']) {
hasStrokeWidth = true;
}
} while ( } while (
!idElem.hasAttr('id', id) && idElem.attributes.id !== id &&
!hasStrokeWidth && !hasStrokeWidth &&
(idElem = idElem.parentNode) (idElem = idElem.parentNode)
); );

View File

@ -1,22 +1,23 @@
'use strict'; 'use strict';
const { inheritableAttrs, elemsGroups } = require('./_collections');
exports.type = 'perItemReverse'; exports.type = 'perItemReverse';
exports.active = true; exports.active = true;
exports.description = 'collapses useless groups'; exports.description = 'collapses useless groups';
var collections = require('./_collections'), function hasAnimatedAttr(item, name) {
attrsInheritable = collections.inheritableAttrs, if (item.type === 'element') {
animationElems = collections.elemsGroups.animation; return (
(elemsGroups.animation.includes(item.name) &&
function hasAnimatedAttr(item) { item.attributes.attributeName === name) ||
return ( (item.children.length !== 0 &&
(item.isElem(animationElems) && item.hasAttr('attributeName', this)) || item.children.some((child) => hasAnimatedAttr(child, name)))
(item.type === 'element' && );
item.children.length !== 0 && }
item.children.some(hasAnimatedAttr, this)) return false;
);
} }
/* /*
@ -51,33 +52,35 @@ exports.fn = function (item) {
) { ) {
item.children.forEach(function (g, i) { item.children.forEach(function (g, i) {
// non-empty groups // non-empty groups
if (g.isElem('g') && g.children.length !== 0) { if (g.type === 'element' && g.name === 'g' && g.children.length !== 0) {
// move group attibutes to the single child element // move group attibutes to the single child element
if (g.hasAttr() && g.children.length === 1) { if (Object.keys(g.attributes).length !== 0 && g.children.length === 1) {
var inner = g.children[0]; var inner = g.children[0];
if ( if (
inner.type === 'element' && inner.type === 'element' &&
!inner.hasAttr('id') && inner.attributes.id == null &&
!g.hasAttr('filter') && g.attributes.filter == null &&
!(g.hasAttr('class') && inner.hasAttr('class')) && (g.attributes.class == null || inner.attributes.class == null) &&
((!g.hasAttr('clip-path') && !g.hasAttr('mask')) || ((g.attributes['clip-path'] == null && g.attributes.mask == null) ||
(inner.isElem('g') && (inner.type === 'element' &&
!g.hasAttr('transform') && inner.name === 'g' &&
!inner.hasAttr('transform'))) g.attributes.transform == null &&
inner.attributes.transform == null))
) { ) {
for (const [name, value] of Object.entries(g.attributes)) { for (const [name, value] of Object.entries(g.attributes)) {
if (g.children.some(hasAnimatedAttr, name)) return; if (g.children.some((item) => hasAnimatedAttr(item, name)))
return;
if (!inner.hasAttr(name)) { if (inner.attributes[name] == null) {
inner.attributes[name] = value; inner.attributes[name] = value;
} else if (name == 'transform') { } else if (name == 'transform') {
inner.attributes[name] = value + ' ' + inner.attributes[name]; inner.attributes[name] = value + ' ' + inner.attributes[name];
} else if (inner.hasAttr(name, 'inherit')) { } else if (inner.attributes[name] === 'inherit') {
inner.attributes[name] = value; inner.attributes[name] = value;
} else if ( } else if (
attrsInheritable.includes(name) === false && inheritableAttrs.includes(name) === false &&
!inner.hasAttr(name, value) inner.attributes[name] !== value
) { ) {
return; return;
} }
@ -89,10 +92,8 @@ exports.fn = function (item) {
// collapse groups without attributes // collapse groups without attributes
if ( if (
!g.hasAttr() && Object.keys(g.attributes).length === 0 &&
!g.children.some(function (item) { !g.children.some((item) => item.isElem(elemsGroups.animation))
return item.isElem(animationElems);
})
) { ) {
item.spliceContent(i, 1, g.children); item.spliceContent(i, 1, g.children);
} }

View File

@ -57,7 +57,11 @@ let arcTolerance;
* @author Kir Belevich * @author Kir Belevich
*/ */
exports.fn = function (item, params) { exports.fn = function (item, params) {
if (item.isElem(pathElems) && item.hasAttr('d')) { if (
item.type === 'element' &&
pathElems.includes(item.name) &&
item.attributes.d != null
) {
const computedStyle = computeStyle(item); const computedStyle = computeStyle(item);
precision = params.floatPrecision; precision = params.floatPrecision;
error = error =

View File

@ -46,17 +46,17 @@ var cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
exports.fn = function (item, params) { exports.fn = function (item, params) {
if (item.type === 'element') { if (item.type === 'element') {
// transform // transform
if (item.hasAttr('transform')) { if (item.attributes.transform != null) {
convertTransform(item, 'transform', params); convertTransform(item, 'transform', params);
} }
// gradientTransform // gradientTransform
if (item.hasAttr('gradientTransform')) { if (item.attributes.gradientTransform != null) {
convertTransform(item, 'gradientTransform', params); convertTransform(item, 'gradientTransform', params);
} }
// patternTransform // patternTransform
if (item.hasAttr('patternTransform')) { if (item.attributes.patternTransform != null) {
convertTransform(item, 'patternTransform', params); convertTransform(item, 'patternTransform', params);
} }
} }

View File

@ -1,14 +1,13 @@
'use strict'; 'use strict';
const { inheritableAttrs, pathElems } = require('./_collections');
exports.type = 'perItemReverse'; exports.type = 'perItemReverse';
exports.active = true; exports.active = true;
exports.description = 'moves elements attributes to the existing group wrapper'; exports.description = 'moves elements attributes to the existing group wrapper';
var inheritableAttrs = require('./_collections').inheritableAttrs,
pathElems = require('./_collections.js').pathElems;
/** /**
* Collapse content's intersected and inheritable * Collapse content's intersected and inheritable
* attributes to the existing group wrapper. * attributes to the existing group wrapper.
@ -34,14 +33,22 @@ var inheritableAttrs = require('./_collections').inheritableAttrs,
* @author Kir Belevich * @author Kir Belevich
*/ */
exports.fn = function (item) { exports.fn = function (item) {
if (item.isElem('g') && item.children.length > 1) { if (
item.type === 'element' &&
item.name === 'g' &&
item.children.length > 1
) {
var intersection = {}, var intersection = {},
hasTransform = false, hasTransform = false,
hasClip = item.hasAttr('clip-path') || item.hasAttr('mask'), hasClip =
item.attributes['clip-path'] != null || item.attributes.mask != null,
intersected = item.children.every(function (inner) { intersected = item.children.every(function (inner) {
if (inner.type === 'element' && inner.hasAttr()) { if (
inner.type === 'element' &&
Object.keys(inner.attributes).length !== 0
) {
// don't mess with possible styles (hack until CSS parsing is implemented) // don't mess with possible styles (hack until CSS parsing is implemented)
if (inner.hasAttr('class')) return false; if (inner.attributes.class) return false;
if (!Object.keys(intersection).length) { if (!Object.keys(intersection).length) {
intersection = inner.attributes; intersection = inner.attributes;
} else { } else {
@ -68,7 +75,7 @@ exports.fn = function (item) {
if (name === 'transform') { if (name === 'transform') {
if (!hasTransform) { if (!hasTransform) {
if (item.hasAttr('transform')) { if (item.attributes.transform != null) {
item.attributes.transform = item.attributes.transform =
item.attributes.transform + ' ' + value; item.attributes.transform + ' ' + value;
} else { } else {

View File

@ -1,14 +1,14 @@
'use strict'; 'use strict';
const { pathElems, referencesProps } = require('./_collections.js');
exports.type = 'perItem'; exports.type = 'perItem';
exports.active = true; exports.active = true;
exports.description = 'moves some group attributes to the content elements'; exports.description = 'moves some group attributes to the content elements';
var collections = require('./_collections.js'), const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text'];
pathElems = collections.pathElems.concat(['g', 'text']),
referencesProps = collections.referencesProps;
/** /**
* Move group attrs to the content elements. * Move group attrs to the content elements.
@ -41,7 +41,9 @@ exports.fn = function (item) {
referencesProps.includes(name) && value.includes('url(') referencesProps.includes(name) && value.includes('url(')
) === false && ) === false &&
item.children.every( item.children.every(
(inner) => inner.isElem(pathElems) && !inner.hasAttr('id') (inner) =>
pathElemsWithGroupsAndText.includes(inner.name) &&
inner.attributes.id == null
) )
) { ) {
for (const inner of item.children) { for (const inner of item.children) {

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict';
const { elemsGroups } = require('./_collections');
exports.type = 'perItemReverse'; exports.type = 'perItemReverse';
exports.active = true; exports.active = true;
exports.description = 'removes empty container elements'; exports.description = 'removes empty container elements';
var container = require('./_collections').elemsGroups.container;
/** /**
* Remove empty containers. * Remove empty containers.
* *
@ -25,16 +25,19 @@ var container = require('./_collections').elemsGroups.container;
* @author Kir Belevich * @author Kir Belevich
*/ */
exports.fn = function (item) { exports.fn = function (item) {
return ( if (item.type === 'element') {
item.isElem(container) === false || return (
(item.type === 'element' && item.children.length !== 0) || item.children.length !== 0 ||
item.isElem('svg') || elemsGroups.container.includes(item.name) === false ||
// empty patterns may contain reusable configuration item.name === 'svg' ||
(item.isElem('pattern') && Object.keys(item.attributes).length !== 0) || // empty patterns may contain reusable configuration
// The 'g' may not have content, but the filter may cause a rectangle (item.name === 'pattern' && Object.keys(item.attributes).length !== 0) ||
// to be created and filled with pattern. // The 'g' may not have content, but the filter may cause a rectangle
(item.isElem('g') && item.hasAttr('filter')) || // to be created and filled with pattern.
// empty <mask> hides masked element (item.name === 'g' && item.attributes.filter != null) ||
(item.isElem('mask') && item.hasAttr('id')) // empty <mask> hides masked element
); (item.name === 'mask' && item.attributes.id != null)
);
}
return true;
}; };

View File

@ -34,18 +34,24 @@ exports.params = {
* @author Kir Belevich * @author Kir Belevich
*/ */
exports.fn = function (item, params) { exports.fn = function (item, params) {
// Remove empty text element if (item.type === 'element') {
if (params.text && item.isElem('text') && item.children.length === 0) { // Remove empty text element
return false; if (params.text && item.name === 'text' && item.children.length === 0) {
} return false;
}
// Remove empty tspan element // Remove empty tspan element
if (params.tspan && item.isElem('tspan') && item.children.length === 0) { if (params.tspan && item.name === 'tspan' && item.children.length === 0) {
return false; return false;
} }
// Remove tref with empty xlink:href attribute // Remove tref with empty xlink:href attribute
if (params.tref && item.isElem('tref') && !item.hasAttrLocal('href')) { if (
return false; params.tref &&
item.name === 'tref' &&
item.attributes['xlink:href'] == null
) {
return false;
}
} }
}; };

View File

@ -25,7 +25,8 @@ var _path = require('./_path.js'),
*/ */
exports.fn = function (item) { exports.fn = function (item) {
if ( if (
item.isElem('path') && item.type === 'element' &&
item.name === 'path' &&
item.attributes.d != null && item.attributes.d != null &&
typeof viewBox !== 'undefined' typeof viewBox !== 'undefined'
) { ) {
@ -44,7 +45,7 @@ exports.fn = function (item) {
return intersects(viewBoxJS, pathJS); return intersects(viewBoxJS, pathJS);
} }
if (item.isElem('svg')) { if (item.type === 'element' && item.name === 'svg') {
parseViewBox(item); parseViewBox(item);
} }
@ -59,8 +60,10 @@ exports.fn = function (item) {
*/ */
function hasTransform(item) { function hasTransform(item) {
return ( return (
item.hasAttr('transform') || item.attributes.transform != null ||
(item.parentNode && hasTransform(item.parentNode)) (item.parentNode &&
item.parentNode.type === 'element' &&
hasTransform(item.parentNode))
); );
} }

View File

@ -18,8 +18,10 @@ exports.description = 'removes raster images (disabled by default)';
*/ */
exports.fn = function (item) { exports.fn = function (item) {
if ( if (
item.isElem('image') && item.type === 'element' &&
item.hasAttrLocal('href', /(\.|image\/)(jpg|png|gif)/) item.name === 'image' &&
item.attributes['xlink:href'] != null &&
/(\.|image\/)(jpg|png|gif)/.test(item.attributes['xlink:href'])
) { ) {
return false; return false;
} }

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict';
const { elemsGroups } = require('./_collections');
exports.type = 'perItem'; exports.type = 'perItem';
exports.active = true; exports.active = true;
exports.description = 'removes elements in <defs> without id'; exports.description = 'removes elements in <defs> without id';
var nonRendering = require('./_collections').elemsGroups.nonRendering;
/** /**
* Removes content of defs and properties that aren't rendered directly without ids. * Removes content of defs and properties that aren't rendered directly without ids.
* *
@ -17,20 +17,25 @@ var nonRendering = require('./_collections').elemsGroups.nonRendering;
* @author Lev Solntsev * @author Lev Solntsev
*/ */
exports.fn = function (item) { exports.fn = function (item) {
if (item.isElem('defs')) { if (item.type === 'element') {
item.children = getUsefulItems(item, []); if (item.name === 'defs') {
if (item.children.length === 0) { item.children = getUsefulItems(item, []);
if (item.children.length === 0) {
return false;
}
} else if (
elemsGroups.nonRendering.includes(item.name) &&
item.attributes.id == null
) {
return false; return false;
} }
} else if (item.isElem(nonRendering) && !item.hasAttr('id')) {
return false;
} }
}; };
function getUsefulItems(item, usefulItems) { function getUsefulItems(item, usefulItems) {
for (const child of item.children) { for (const child of item.children) {
if (child.type === 'element') { if (child.type === 'element') {
if (child.hasAttr('id') || child.isElem('style')) { if (child.attributes.id != null || child.name === 'style') {
usefulItems.push(child); usefulItems.push(child);
child.parentNode = item; child.parentNode = item;
} else { } else {