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:
@ -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];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)
|
||||||
);
|
);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 =
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Reference in New Issue
Block a user