From 6f2f62c5ee8a841ca0793207e38ed82e939a8942 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Thu, 18 Mar 2021 18:53:20 +0300 Subject: [PATCH] Access attributes directly (#1433) Got rid from `.attrs`, `.attr()` and `.addAttr()` usages --- lib/svgo/css-select-adapter.js | 4 +- lib/svgo/js2svg.js | 10 ++- lib/svgo/jsAPI.js | 2 +- plugins/_applyTransforms.js | 33 +++++---- plugins/_path.js | 4 +- plugins/addAttributesToSVGElement.js | 13 ++-- plugins/cleanupIDs.js | 2 +- plugins/cleanupListOfValues.js | 82 +++++++++++----------- plugins/cleanupNumericValues.js | 6 +- plugins/convertShapeToPath.js | 68 +++++++------------ plugins/convertStyleToAttrs.js | 39 +++++------ plugins/convertTransform.js | 2 +- plugins/inlineStyles.js | 6 +- plugins/mergePaths.js | 34 +++++----- plugins/minifyStyles.js | 42 +++++------- plugins/moveElemsAttrsToGroup.js | 7 +- plugins/prefixIds.js | 97 ++++++++++++++------------- plugins/removeElementsByAttr.js | 10 ++- plugins/removeEmptyContainers.js | 2 +- plugins/removeHiddenElems.js | 26 +++---- plugins/removeOffCanvasPaths.js | 20 +++--- plugins/removeUselessStrokeAndFill.js | 5 +- plugins/reusePaths.js | 30 ++++----- 23 files changed, 261 insertions(+), 283 deletions(-) diff --git a/lib/svgo/css-select-adapter.js b/lib/svgo/css-select-adapter.js index 0d01f06f..79bf24f8 100644 --- a/lib/svgo/css-select-adapter.js +++ b/lib/svgo/css-select-adapter.js @@ -19,7 +19,7 @@ const existsOne = (test, elems) => { }; const getAttributeValue = (elem, name) => { - return elem.hasAttr(name) ? elem.attr(name).value : undefined; + return elem.attributes[name]; }; const getChildren = (node) => { @@ -47,7 +47,7 @@ const getText = (node) => { }; const hasAttrib = (elem, name) => { - return getAttributeValue(elem, name) !== undefined; + return elem.attributes[name] !== undefined; }; const removeSubsets = (nodes) => { diff --git a/lib/svgo/js2svg.js b/lib/svgo/js2svg.js index f9f812b4..69cf52bc 100644 --- a/lib/svgo/js2svg.js +++ b/lib/svgo/js2svg.js @@ -203,9 +203,13 @@ JS2SVG.prototype.createCDATA = function (node) { */ JS2SVG.prototype.createElem = function (data) { // beautiful injection for obtaining SVG information :) - if (data.isElem('svg') && data.hasAttr('width') && data.hasAttr('height')) { - this.width = data.attr('width').value; - this.height = data.attr('height').value; + if ( + data.name === 'svg' && + data.attributes.width != null && + data.attributes.height != null + ) { + this.width = data.attributes.width; + this.height = data.attributes.height; } // empty element and short tag diff --git a/lib/svgo/jsAPI.js b/lib/svgo/jsAPI.js index 29a1cc1d..acceb7e3 100644 --- a/lib/svgo/jsAPI.js +++ b/lib/svgo/jsAPI.js @@ -289,7 +289,7 @@ JSAPI.prototype.computedAttr = function (name, val) { for ( var elem = this; - elem && (!elem.hasAttr(name) || !elem.attr(name).value); + elem && (!elem.hasAttr(name) || !elem.attributes[name]); elem = elem.parentNode ); diff --git a/plugins/_applyTransforms.js b/plugins/_applyTransforms.js index 6d450de6..63dbc056 100644 --- a/plugins/_applyTransforms.js +++ b/plugins/_applyTransforms.js @@ -38,7 +38,7 @@ const applyTransforms = (elem, pathData, params) => { return; } - const matrix = transformsMultiply(transform2js(elem.attr('transform').value)); + const matrix = transformsMultiply(transform2js(elem.attributes.transform)); const stroke = elem.computedAttr('stroke'); const id = elem.computedAttr('id'); const transformPrecision = params.transformPrecision; @@ -77,34 +77,33 @@ const applyTransforms = (elem, pathData, params) => { elem.computedAttr('stroke-width') || defaultStrokeWidth; if ( - !elem.hasAttr('vector-effect') || - elem.attr('vector-effect').value !== 'non-scaling-stroke' + elem.attributes['vector-effect'] == null || + elem.attributes['vector-effect'] !== 'non-scaling-stroke' ) { - if (elem.hasAttr('stroke-width')) { - elem.attrs['stroke-width'].value = elem.attrs['stroke-width'].value + if (elem.attributes['stroke-width'] != null) { + elem.attributes['stroke-width'] = elem.attributes['stroke-width'] .trim() .replace(regNumericValues, (num) => removeLeadingZero(num * scale)); } else { - elem.addAttr({ - name: 'stroke-width', - value: strokeWidth.replace(regNumericValues, (num) => - removeLeadingZero(num * scale) - ), - }); + elem.attributes[ + 'stroke-width' + ] = strokeWidth.replace(regNumericValues, (num) => + removeLeadingZero(num * scale) + ); } - if (elem.hasAttr('stroke-dashoffset')) { - elem.attrs['stroke-dashoffset'].value = elem.attrs[ + if (elem.attributes['stroke-dashoffset'] != null) { + elem.attributes['stroke-dashoffset'] = elem.attributes[ 'stroke-dashoffset' - ].value + ] .trim() .replace(regNumericValues, (num) => removeLeadingZero(num * scale)); } - if (elem.hasAttr('stroke-dasharray')) { - elem.attrs['stroke-dasharray'].value = elem.attrs[ + if (elem.attributes['stroke-dasharray'] != null) { + elem.attributes['stroke-dasharray'] = elem.attributes[ 'stroke-dasharray' - ].value + ] .trim() .replace(regNumericValues, (num) => removeLeadingZero(num * scale)); } diff --git a/plugins/_path.js b/plugins/_path.js index 4793102b..a4316079 100644 --- a/plugins/_path.js +++ b/plugins/_path.js @@ -14,7 +14,7 @@ var prevCtrlPoint; exports.path2js = function (path) { if (path.pathJS) return path.pathJS; const pathData = []; // JS representation of the path data - const newPathData = parsePathData(path.attr('d').value); + const newPathData = parsePathData(path.attributes.d); for (const { command, args } of newPathData) { if (command === 'Z' || command === 'z') { pathData.push({ instruction: 'z' }); @@ -343,7 +343,7 @@ exports.js2path = function (path, data, params) { }); } - path.attr('d').value = stringifyPathData({ + path.attributes.d = stringifyPathData({ pathData, precision: params.floatPrecision, disableSpaceAfterFlags: params.noSpaceAfterFlags, diff --git a/plugins/addAttributesToSVGElement.js b/plugins/addAttributesToSVGElement.js index dfe6ce50..aa480a20 100644 --- a/plugins/addAttributesToSVGElement.js +++ b/plugins/addAttributesToSVGElement.js @@ -62,18 +62,13 @@ exports.fn = function (data, params) { if (svg.isElem('svg')) { attributes.forEach(function (attribute) { if (typeof attribute === 'string') { - if (!svg.hasAttr(attribute)) { - svg.addAttr({ - name: attribute, - }); + if (svg.attributes[attribute] == null) { + svg.attributes[attribute] = undefined; } } else if (typeof attribute === 'object') { Object.keys(attribute).forEach(function (key) { - if (!svg.hasAttr(key)) { - svg.addAttr({ - name: key, - value: attribute[key], - }); + if (svg.attributes[key] == null) { + svg.attributes[key] = attribute[key]; } }); } diff --git a/plugins/cleanupIDs.js b/plugins/cleanupIDs.js index d9ec43dd..62d382a2 100644 --- a/plugins/cleanupIDs.js +++ b/plugins/cleanupIDs.js @@ -208,7 +208,7 @@ exports.fn = function (data, params) { ); } while (idPreserved(currentIDstring)); - IDs.get(key).attr('id').value = currentIDstring; + IDs.get(key).attributes.id = currentIDstring; for (const { element, name, value } of refs) { element.attributes[name] = value.includes(idValuePrefix) diff --git a/plugins/cleanupListOfValues.js b/plugins/cleanupListOfValues.js index 7639c04b..5094225d 100644 --- a/plugins/cleanupListOfValues.js +++ b/plugins/cleanupListOfValues.js @@ -1,5 +1,7 @@ 'use strict'; +const { removeLeadingZero } = require('../lib/svgo/tools.js'); + exports.type = 'perItem'; exports.active = false; @@ -13,17 +15,16 @@ exports.params = { convertToPx: true, }; -var regNumericValues = /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/, - regSeparator = /\s+,?\s*|,\s*/, - removeLeadingZero = require('../lib/svgo/tools').removeLeadingZero, - absoluteLengths = { - // relative to px - cm: 96 / 2.54, - mm: 96 / 25.4, - in: 96, - pt: 4 / 3, - pc: 16, - }; +const regNumericValues = /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/; +const regSeparator = /\s+,?\s*|,\s*/; +const absoluteLengths = { + // relative to px + cm: 96 / 2.54, + mm: 96 / 25.4, + in: 96, + pt: 4 / 3, + pc: 16, +}; /** * Round list of values to the fixed precision. @@ -46,49 +47,55 @@ var regNumericValues = /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft| * @author kiyopikko */ exports.fn = function (item, params) { - if (item.hasAttr('points')) { - roundValues(item.attrs.points); + if (item.type !== 'element') { + return; } - if (item.hasAttr('enable-background')) { - roundValues(item.attrs['enable-background']); + if (item.attributes.points != null) { + item.attributes.points = roundValues(item.attributes.points); } - if (item.hasAttr('viewBox')) { - roundValues(item.attrs.viewBox); + if (item.attributes['enable-background'] != null) { + item.attributes['enable-background'] = roundValues( + item.attributes['enable-background'] + ); } - if (item.hasAttr('stroke-dasharray')) { - roundValues(item.attrs['stroke-dasharray']); + if (item.attributes.viewBox != null) { + item.attributes.viewBox = roundValues(item.attributes.viewBox); } - if (item.hasAttr('dx')) { - roundValues(item.attrs.dx); + if (item.attributes['stroke-dasharray'] != null) { + item.attributes['stroke-dasharray'] = roundValues( + item.attributes['stroke-dasharray'] + ); } - if (item.hasAttr('dy')) { - roundValues(item.attrs.dy); + if (item.attributes.dx != null) { + item.attributes.dx = roundValues(item.attributes.dx); } - if (item.hasAttr('x')) { - roundValues(item.attrs.x); + if (item.attributes.dy != null) { + item.attributes.dy = roundValues(item.attributes.dy); } - if (item.hasAttr('y')) { - roundValues(item.attrs.y); + if (item.attributes.x != null) { + item.attributes.x = roundValues(item.attributes.x); } - function roundValues($prop) { + if (item.attributes.y != null) { + item.attributes.y = roundValues(item.attributes.y); + } + + function roundValues(lists) { var num, units, match, matchNew, - lists = $prop.value, listsArr = lists.split(regSeparator), - roundedListArr = [], - roundedList; + roundedList = []; - listsArr.forEach(function (elem) { + for (const elem of listsArr) { match = elem.match(regNumericValues); matchNew = elem.match(/new/); @@ -118,17 +125,16 @@ exports.fn = function (item, params) { units = ''; } - roundedListArr.push(num + units); + roundedList.push(num + units); } // if attribute value is "new"(only enable-background). else if (matchNew) { - roundedListArr.push('new'); + roundedList.push('new'); } else if (elem) { - roundedListArr.push(elem); + roundedList.push(elem); } - }); + } - roundedList = roundedListArr.join(' '); - $prop.value = roundedList; + return roundedList.join(' '); } }; diff --git a/plugins/cleanupNumericValues.js b/plugins/cleanupNumericValues.js index f8f9b726..5fb7936c 100644 --- a/plugins/cleanupNumericValues.js +++ b/plugins/cleanupNumericValues.js @@ -39,9 +39,9 @@ exports.fn = function (item, params) { if (item.type === 'element') { var floatPrecision = params.floatPrecision; - if (item.hasAttr('viewBox')) { - var nums = item.attr('viewBox').value.split(/\s,?\s*|,\s*/g); - item.attr('viewBox').value = nums + if (item.attributes.viewBox != null) { + var nums = item.attributes.viewBox.split(/\s,?\s*|,\s*/g); + item.attributes.viewBox = nums .map(function (value) { var num = +value; return isNaN(num) ? value : +num.toFixed(floatPrecision); diff --git a/plugins/convertShapeToPath.js b/plugins/convertShapeToPath.js index 25caf53e..2b5e9bd1 100644 --- a/plugins/convertShapeToPath.js +++ b/plugins/convertShapeToPath.js @@ -13,7 +13,6 @@ exports.params = { floatPrecision: null, }; -const none = { value: 0 }; const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g; /** @@ -35,15 +34,15 @@ exports.fn = function (item, params) { if ( item.isElem('rect') && - item.hasAttr('width') && - item.hasAttr('height') && - !item.hasAttr('rx') && - !item.hasAttr('ry') + item.attributes.width != null && + item.attributes.height != null && + item.attributes.rx == null && + item.attributes.ry == null ) { - var x = +(item.attr('x') || none).value, - y = +(item.attr('y') || none).value, - width = +item.attr('width').value, - height = +item.attr('height').value; + const x = Number(item.attributes.x || '0'); + const y = Number(item.attributes.y || '0'); + const width = Number(item.attributes.width); + const height = Number(item.attributes.height); // Values like '100%' compute to NaN, thus running after // cleanupNumericValues when 'px' units has already been removed. // TODO: Calculate sizes from % and non-px units if possible. @@ -55,10 +54,7 @@ exports.fn = function (item, params) { { command: 'H', args: [x] }, { command: 'z', args: [] }, ]; - item.addAttr({ - name: 'd', - value: stringifyPathData({ pathData, precision }), - }); + item.attributes.d = stringifyPathData({ pathData, precision }); item.renameElem('path'); delete item.attributes.x; delete item.attributes.y; @@ -67,19 +63,16 @@ exports.fn = function (item, params) { } if (item.isElem('line')) { - var x1 = +(item.attr('x1') || none).value, - y1 = +(item.attr('y1') || none).value, - x2 = +(item.attr('x2') || none).value, - y2 = +(item.attr('y2') || none).value; + const x1 = Number(item.attributes.x1 || '0'); + const y1 = Number(item.attributes.y1 || '0'); + const x2 = Number(item.attributes.x2 || '0'); + const y2 = Number(item.attributes.y2 || '0'); if (isNaN(x1 - y1 + x2 - y2)) return; const pathData = [ { command: 'M', args: [x1, y1] }, { command: 'L', args: [x2, y2] }, ]; - item.addAttr({ - name: 'd', - value: stringifyPathData({ pathData, precision }), - }); + item.attributes.d = stringifyPathData({ pathData, precision }); item.renameElem('path'); delete item.attributes.x1; delete item.attributes.y1; @@ -89,9 +82,9 @@ exports.fn = function (item, params) { if ( (item.isElem('polyline') || item.isElem('polygon')) && - item.hasAttr('points') + item.attributes.points != null ) { - var coords = (item.attr('points').value.match(regNumber) || []).map(Number); + const coords = (item.attributes.points.match(regNumber) || []).map(Number); if (coords.length < 4) return false; const pathData = []; for (let i = 0; i < coords.length; i += 2) { @@ -103,18 +96,15 @@ exports.fn = function (item, params) { if (item.isElem('polygon')) { pathData.push({ command: 'z', args: [] }); } - item.addAttr({ - name: 'd', - value: stringifyPathData({ pathData, precision }), - }); + item.attributes.d = stringifyPathData({ pathData, precision }); item.renameElem('path'); delete item.attributes.points; } if (item.isElem('circle') && convertArcs) { - var cx = +(item.attr('cx') || none).value; - var cy = +(item.attr('cy') || none).value; - var r = +(item.attr('r') || none).value; + const cx = Number(item.attributes.cx || '0'); + const cy = Number(item.attributes.cy || '0'); + const r = Number(item.attributes.r || '0'); if (isNaN(cx - cy + r)) { return; } @@ -124,10 +114,7 @@ exports.fn = function (item, params) { { command: 'A', args: [r, r, 0, 1, 0, cx, cy - r] }, { command: 'z', args: [] }, ]; - item.addAttr({ - name: 'd', - value: stringifyPathData({ pathData, precision }), - }); + item.attributes.d = stringifyPathData({ pathData, precision }); item.renameElem('path'); delete item.attributes.cx; delete item.attributes.cy; @@ -135,10 +122,10 @@ exports.fn = function (item, params) { } if (item.isElem('ellipse') && convertArcs) { - var ecx = +(item.attr('cx') || none).value; - var ecy = +(item.attr('cy') || none).value; - var rx = +(item.attr('rx') || none).value; - var ry = +(item.attr('ry') || none).value; + const ecx = Number(item.attributes.cx || '0'); + const ecy = Number(item.attributes.cy || '0'); + const rx = Number(item.attributes.rx || '0'); + const ry = Number(item.attributes.ry || '0'); if (isNaN(ecx - ecy + rx - ry)) { return; } @@ -148,10 +135,7 @@ exports.fn = function (item, params) { { command: 'A', args: [rx, ry, 0, 1, 0, ecx, ecy - ry] }, { command: 'z', args: [] }, ]; - item.addAttr({ - name: 'd', - value: stringifyPathData({ pathData, precision }), - }); + item.attributes.d = stringifyPathData({ pathData, precision }); item.renameElem('path'); delete item.attributes.cx; delete item.attributes.cy; diff --git a/plugins/convertStyleToAttrs.js b/plugins/convertStyleToAttrs.js index 739347e9..66f706e9 100644 --- a/plugins/convertStyleToAttrs.js +++ b/plugins/convertStyleToAttrs.js @@ -67,20 +67,22 @@ var stylingProps = require('./_collections').attrsGroups.presentation, * @author Kir Belevich */ exports.fn = function (item, params) { - if (item.type === 'element' && item.hasAttr('style')) { + if (item.type === 'element' && item.attributes.style != null) { // ['opacity: 1', 'color: #000'] - var styleValue = item.attr('style').value, - styles = [], - attrs = {}; + let styles = []; + const newAttributes = {}; // Strip CSS comments preserving escape sequences and strings. - styleValue = styleValue.replace(regStripComments, function (match) { - return match[0] == '/' - ? '' - : match[0] == '\\' && /[-g-z]/i.test(match[1]) - ? match[1] - : match; - }); + const styleValue = item.attributes.style.replace( + regStripComments, + (match) => { + return match[0] == '/' + ? '' + : match[0] == '\\' && /[-g-z]/i.test(match[1]) + ? match[1] + : match; + } + ); regDeclarationBlock.lastIndex = 0; // eslint-disable-next-line no-cond-assign @@ -100,11 +102,8 @@ exports.fn = function (item, params) { val = val.slice(1, -1); } - if (stylingProps.indexOf(prop) > -1) { - attrs[prop] = { - name: prop, - value: val, - }; + if (stylingProps.includes(prop)) { + newAttributes[prop] = val; return false; } @@ -113,13 +112,11 @@ exports.fn = function (item, params) { return true; }); - Object.assign(item.attrs, attrs); + Object.assign(item.attributes, newAttributes); if (styles.length) { - item.attr('style').value = styles - .map(function (declaration) { - return declaration.join(':'); - }) + item.attributes.style = styles + .map((declaration) => declaration.join(':')) .join(';'); } else { delete item.attributes.style; diff --git a/plugins/convertTransform.js b/plugins/convertTransform.js index d0128d24..ac346d04 100644 --- a/plugins/convertTransform.js +++ b/plugins/convertTransform.js @@ -70,7 +70,7 @@ exports.fn = function (item, params) { * @param {Object} params plugin params */ function convertTransform(item, attrName, params) { - var data = transform2js(item.attr(attrName).value); + let data = transform2js(item.attributes[attrName]); params = definePrecision(data, params); if (params.collapseIntoOne && data.length > 1) { diff --git a/plugins/inlineStyles.js b/plugins/inlineStyles.js index d7c9de65..1be26575 100644 --- a/plugins/inlineStyles.js +++ b/plugins/inlineStyles.js @@ -55,9 +55,9 @@ exports.fn = function (document, opts) { for (var styleEl of styleEls) { // values other than the empty string or text/css are not used if ( - styleEl.hasAttr('type') && - styleEl.attr('type').value !== '' && - styleEl.attr('type').value !== 'text/css' + styleEl.attributes.type != null && + styleEl.attributes.type !== '' && + styleEl.attributes.type !== 'text/css' ) { continue; } diff --git a/plugins/mergePaths.js b/plugins/mergePaths.js index 3e88ad0f..db205012 100644 --- a/plugins/mergePaths.js +++ b/plugins/mergePaths.js @@ -28,18 +28,18 @@ exports.params = { exports.fn = function (item, params) { if (item.type !== 'element' || item.children.length === 0) return; - var prevContentItem = null, - prevContentItemKeys = null; + let prevContentItem = null; + let prevContentItemKeys = null; item.children = item.children.filter(function (contentItem) { if ( prevContentItem && prevContentItem.isElem('path') && prevContentItem.children.length === 0 && - prevContentItem.hasAttr('d') && + prevContentItem.attributes.d != null && contentItem.isElem('path') && contentItem.children.length === 0 && - contentItem.hasAttr('d') + contentItem.attributes.d != null ) { const computedStyle = computeStyle(contentItem); // keep path to not break markers @@ -51,21 +51,21 @@ exports.fn = function (item, params) { return true; } if (!prevContentItemKeys) { - prevContentItemKeys = Object.keys(prevContentItem.attrs); + prevContentItemKeys = Object.keys(prevContentItem.attributes); } - var contentItemAttrs = Object.keys(contentItem.attrs), - equalData = - prevContentItemKeys.length == contentItemAttrs.length && - contentItemAttrs.every(function (key) { - return ( - key == 'd' || - (prevContentItem.hasAttr(key) && - prevContentItem.attr(key).value == contentItem.attr(key).value) - ); - }), - prevPathJS = path2js(prevContentItem), - curPathJS = path2js(contentItem); + const contentItemAttrs = Object.keys(contentItem.attributes); + const equalData = + prevContentItemKeys.length == contentItemAttrs.length && + contentItemAttrs.every(function (key) { + return ( + key == 'd' || + (prevContentItem.attributes[key] != null && + prevContentItem.attributes[key] == contentItem.attributes[key]) + ); + }); + const prevPathJS = path2js(prevContentItem); + const curPathJS = path2js(contentItem); if (equalData && (params.force || !intersects(prevPathJS, curPathJS))) { js2path(prevContentItem, prevPathJS.concat(curPathJS), params); diff --git a/plugins/minifyStyles.js b/plugins/minifyStyles.js index f586e27d..b4cc2be9 100755 --- a/plugins/minifyStyles.js +++ b/plugins/minifyStyles.js @@ -56,9 +56,9 @@ exports.fn = function (ast, options) { } } else { // style attribute - var elemStyle = elem.attr('style').value; + var elemStyle = elem.attributes.style; - elem.attr('style').value = csso.minifyBlock( + elem.attributes.style = csso.minifyBlock( elemStyle, minifyOptionsForAttribute ).css; @@ -84,7 +84,7 @@ function findStyleElems(ast) { if (item.isElem('style') && item.children.length !== 0) { styles.push(item); - } else if (item.type === 'element' && item.hasAttr('style')) { + } else if (item.type === 'element' && item.attributes.style != null) { styles.push(item); } } @@ -109,41 +109,33 @@ function shouldFilter(options, name) { function collectUsageData(ast, options) { function walk(items, usageData) { - for (var i = 0; i < items.children.length; i++) { - var item = items.children[i]; - + for (const item of items.children) { // go deeper - if (item.children) { + if (item.type === 'root' || item.type === 'element') { walk(item, usageData); } - if (item.isElem('script')) { - safe = false; - } - if (item.type === 'element') { - usageData.tags[item.name] = true; - - if (item.hasAttr('id')) { - usageData.ids[item.attr('id').value] = true; + if (item.name === 'script') { + safe = false; } - if (item.hasAttr('class')) { - item - .attr('class') - .value.replace(/^\s+|\s+$/g, '') + usageData.tags[item.name] = true; + + if (item.attributes.id != null) { + usageData.ids[item.attributes.id] = true; + } + + if (item.attributes.class != null) { + item.attributes.class + .replace(/^\s+|\s+$/g, '') .split(/\s+/) .forEach(function (className) { usageData.classes[className] = true; }); } - if ( - item.attrs && - Object.keys(item.attrs).some(function (name) { - return /^on/i.test(name); - }) - ) { + if (Object.keys(item.attributes).some((name) => /^on/i.test(name))) { safe = false; } } diff --git a/plugins/moveElemsAttrsToGroup.js b/plugins/moveElemsAttrsToGroup.js index 14644a49..cd8210e3 100644 --- a/plugins/moveElemsAttrsToGroup.js +++ b/plugins/moveElemsAttrsToGroup.js @@ -69,15 +69,16 @@ exports.fn = function (item) { if (name === 'transform') { if (!hasTransform) { if (item.hasAttr('transform')) { - item.attr('transform').value += ' ' + value; + item.attributes.transform = + item.attributes.transform + ' ' + value; } else { - item.addAttr({ name, value }); + item.attributes.transform = value; } hasTransform = true; } } else { - item.addAttr({ name, value }); + item.attributes[name] = value; } } } diff --git a/plugins/prefixIds.js b/plugins/prefixIds.js index 22b78841..42ea528b 100755 --- a/plugins/prefixIds.js +++ b/plugins/prefixIds.js @@ -51,11 +51,6 @@ var matchUrl = function (val) { return urlMatches[1]; }; -// Checks if attribute is empty -var attrNotEmpty = function (attr) { - return attr && attr.value && attr.value.length > 0; -}; - // prefixes an #ID var prefixId = function (val) { var idName = matchId(val); @@ -65,74 +60,88 @@ var prefixId = function (val) { return '#' + addPrefix(idName); }; -// attr.value helper methods - // prefixes a class attribute value -var addPrefixToClassAttr = function (attr) { - if (!attrNotEmpty(attr)) { +const addPrefixToClassAttr = (element, name) => { + if ( + element.attributes[name] == null || + element.attributes[name].length === 0 + ) { return; } - attr.value = attr.value.split(/\s+/).map(addPrefix).join(' '); + element.attributes[name] = element.attributes[name] + .split(/\s+/) + .map(addPrefix) + .join(' '); }; // prefixes an ID attribute value -var addPrefixToIdAttr = function (attr) { - if (!attrNotEmpty(attr)) { +const addPrefixToIdAttr = (element, name) => { + if ( + element.attributes[name] == null || + element.attributes[name].length === 0 + ) { return; } - attr.value = addPrefix(attr.value); + element.attributes[name] = addPrefix(element.attributes[name]); }; // prefixes a href attribute value -var addPrefixToHrefAttr = function (attr) { - if (!attrNotEmpty(attr)) { +const addPrefixToHrefAttr = (element, name) => { + if ( + element.attributes[name] == null || + element.attributes[name].length === 0 + ) { return; } - var idPrefixed = prefixId(attr.value); + const idPrefixed = prefixId(element.attributes[name]); if (!idPrefixed) { return; } - attr.value = idPrefixed; + element.attributes[name] = idPrefixed; }; // prefixes an URL attribute value -var addPrefixToUrlAttr = function (attr) { - if (!attrNotEmpty(attr)) { +const addPrefixToUrlAttr = (element, name) => { + if ( + element.attributes[name] == null || + element.attributes[name].length === 0 + ) { return; } // url(...) in value - var urlVal = matchUrl(attr.value); + const urlVal = matchUrl(element.attributes[name]); if (!urlVal) { return; } - var idPrefixed = prefixId(urlVal); + const idPrefixed = prefixId(urlVal); if (!idPrefixed) { return; } - attr.value = 'url(' + idPrefixed + ')'; + element.attributes[name] = 'url(' + idPrefixed + ')'; }; // prefixes begin/end attribute value -var addPrefixToBeginEndAttr = function (attr) { - if (!attrNotEmpty(attr)) { +const addPrefixToBeginEndAttr = (element, name) => { + if ( + element.attributes[name] == null || + element.attributes[name].length === 0 + ) { return; } - var parts = attr.value.split('; ').map(function (val) { + const parts = element.attributes[name].split('; ').map((val) => { val = val.trim(); if (val.endsWith('.end') || val.endsWith('.start')) { - var idPostfix = val.split('.'), - id = idPostfix[0], - postfix = idPostfix[1]; + const [id, postfix] = val.split('.'); - var idPrefixed = prefixId(`#${id}`); + let idPrefixed = prefixId(`#${id}`); if (!idPrefixed) { return val; @@ -145,7 +154,7 @@ var addPrefixToBeginEndAttr = function (attr) { } }); - attr.value = parts.join('; '); + element.attributes[name] = parts.join('; '); }; const getBasename = (path) => { @@ -169,7 +178,7 @@ const getBasename = (path) => { exports.fn = function (node, opts, extra) { // skip subsequent passes when multipass is used if (extra.multipassCount && extra.multipassCount > 0) { - return node; + return; } // prefix, from file name or option @@ -200,7 +209,7 @@ exports.fn = function (node, opts, extra) { if (node.type === 'element' && node.name === 'style') { if (node.children.length === 0) { // skip empty