diff --git a/.svgo.yml b/.svgo.yml index 80dfdfc2..3db9f590 100644 --- a/.svgo.yml +++ b/.svgo.yml @@ -36,13 +36,13 @@ plugins: active: true type: perItem - - name: cleanupSVGElem + - name: removeUnknownsAndDefaults active: true type: perItem params: - id: true - version: true - xmlspace: true + unknownContent: true + unknownAttrs: true + defaultAttrs: true - name: removeViewBox active: true diff --git a/plugins/_collections.js b/plugins/_collections.js index e87d0e86..4bda42b9 100644 --- a/plugins/_collections.js +++ b/plugins/_collections.js @@ -1,3 +1,822 @@ +// http://www.w3.org/TR/SVG/intro.html#Definitions +var elemsGroups = exports.elemsGroups = { + animation: ['animate', 'animateColor', 'animateMotion', 'animateTransform', 'set'], + descriptive: ['desc', 'metadata', 'title'], + shape: ['circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect'], + structural: ['defs', 'g', 'svg', 'symbol', 'use'], + gradient: ['linearGradient', 'radialGradient'], + container: ['a', 'defs', 'glyph', 'g', 'marker', 'mask', 'missing-glyph', 'pattern', 'svg', 'switch', 'symbol'] +}; + +// var defaults = exports.defaults = { +// 'externalResourcesRequired': 'false', +// 'xlink:type': 'simple' +// }; + +// http://www.w3.org/TR/SVG/intro.html#Definitions +var attrsGroups = exports.attrsGroups = { + animationAddition: ['additive', 'accumulate'], + animationAttributeTarget: ['attributeType', 'attributeName'], + animationEvent: ['onbegin', 'onend', 'onrepeat', 'onload'], + animationTiming: ['begin', 'dur', 'end', 'min', 'max', 'restart', 'repeatCount', 'repeatDur', 'fill'], + animationValue: ['calcMode', 'values', 'keyTimes', 'keySplines', 'from', 'to', 'by'], + conditionalProcessing: ['requiredFeatures', 'requiredExtensions', 'systemLanguage'], + core: ['id', 'xml:base', 'xml:lang', 'xml:space'], + graphicalEvent: ['onfocusin', 'onfocusout', 'onactivate', 'onclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onload'], + presentation: ['alignment-baseline', 'baseline-shift', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'dominant-baseline', 'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'overflow', 'pointer-events', 'shape-rendering', 'stop-color', 'stop-opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'unicode-bidi', 'visibility', 'word-spacing', 'writing-mode'], + xlink: ['xlink:href', 'xlink:show', 'xlink:actuate', 'xlink:type', 'xlink:role', 'xlink:arcrole', 'xlink:title'], + documentEvent: ['onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onzoom'], + filterPrimitive: ['x', 'y', 'width', 'height'], + transferFunction: ['type', 'tableValues', 'slope', 'intercept', 'amplitude', 'exponent', 'offset'] +}; + +var groupDefaults = exports.groupDefaults = { + filterPrimitive: {x: '0', y: '0', width: '100%', height: '100%'}, + transferFunction: {slope: '1', intercept: '0', amplitude: '1', exponent: '1', offset: '0'} +}; + +// http://www.w3.org/TR/SVG/eltindex.html +exports.elems = { + a: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + attrsGroups.xlink, + 'class', + 'style', + 'externalResourcesRequired', + 'transform', + 'target' + ], + defaults: { + target: '_self' + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive, + elemsGroups.shape, + elemsGroups.structural, + elemsGroups.gradient, + 'a', + 'altGlyphDef', + 'clipPath', + 'color-profile', + 'cursor', + 'filter', + 'font', + 'font-face', + 'foreignObject', + 'image', + 'marker', + 'mask', + 'pattern', + 'script', + 'style', + 'switch', + 'text', + 'view' + ] + }, + altGlyph: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + attrsGroups.xlink, + 'class', + 'style', + 'externalResourcesRequired', + 'x', + 'y', + 'dx', + 'dy', + 'glyphRef', + 'format', + 'rotate' + ], + content: [] + }, + altGlyphDef: { + attrs: [attrsGroups.core], + content: ['glyphRef'] + }, + altGlyphItem: { + attrs: [attrsGroups.core], + content: [ + 'glyphRef', + 'altGlyphItem' + ] + }, + animate: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.animationAddition, + attrsGroups.animationAttributeTarget, + attrsGroups.animationEvent, + attrsGroups.animationTiming, + attrsGroups.animationValue, + attrsGroups.presentation, + attrsGroups.xlink, + 'externalResourcesRequired' + ], + content: [elemsGroups.descriptive] + }, + animateColor: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.animationEvent, + attrsGroups.xlink, + attrsGroups.animationAttributeTarget, + attrsGroups.animationTiming, + attrsGroups.animationValue, + attrsGroups.animationAddition, + attrsGroups.presentation, + 'externalResourcesRequired' + ], + content: [elemsGroups.descriptive] + }, + animateMotion: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.animationEvent, + attrsGroups.xlink, + attrsGroups.animationTiming, + attrsGroups.animationValue, + attrsGroups.animationAddition, + 'externalResourcesRequired', + 'path', + 'keyPoints', + 'rotate', + 'origin' + ], + defaults: { + 'rotate': '0' + }, + content: [ + elemsGroups.descriptive, + 'mpath' + ] + }, + animateTransform: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.animationEvent, + attrsGroups.xlink, + attrsGroups.animationAttributeTarget, + attrsGroups.animationTiming, + attrsGroups.animationValue, + attrsGroups.animationAddition, + 'externalResourcesRequired', + 'type' + ], + defaults: { + type: 'translate' + }, + content: [elemsGroups.descriptive] + }, + circle: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform', + 'cx', + 'cy', + 'r' + ], + defaults: { + cx: 0, + cy: 0 + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive + ] + }, + clipPath: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform', + 'clipPathUnits' + ], + defaults: { + clipPathUnits: 'userSpaceOnUse' + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive, + elemsGroups.shape, + 'text', + 'use' + ] + }, + 'color-profile': { + attrs: [ + attrsGroups.core, + attrsGroups.xlink, + 'local', + 'name', + 'rendering-intent' + ], + defaults: { + name: 'sRGB', + 'rendering-intent': 'auto' + }, + content: [elemsGroups.descriptive] + }, + cursor: { + attrs: [ + attrsGroups.core, + attrsGroups.conditionalProcessing, + attrsGroups.xlink, + 'externalResourcesRequired', + 'x', + 'y' + ], + defaults: { + x: '0', + y: '0' + }, + content: [elemsGroups.descriptive] + }, + defs: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform' + ], + content: [ + elemsGroups.animation, + elemsGroups.descriptive, + elemsGroups.shape, + elemsGroups.structural, + elemsGroups.gradient, + 'a', + 'altGlyphDef', + 'clipPath', + 'color-profile', + 'cursor', + 'filter', + 'font', + 'font-face', + 'foreignObject', + 'image', + 'marker', + 'mask', + 'pattern', + 'script', + 'style', + 'switch', + 'text', + 'view' + ] + }, + desc: { + attrs: [ + attrsGroups.core, + 'class', + 'style' + ] + }, + ellipse: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform', + 'cx', + 'cy', + 'rx', + 'ry' + ], + defaults: { + cx: '0', + cy: '0' + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive + ] + }, + feBlend: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + // TODO: in - 'If no value is provided and this is the first filter primitive, + // then this filter primitive will use SourceGraphic as its input' + 'in', + 'in2', + 'mode' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + mode: 'normal' + }, + content: [ + 'animate', + 'set' + ] + }, + feColorMatrix: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'type', + 'values' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + type: 'matrix' + }, + content: [ + 'animate', + 'set' + ] + }, + feComponentTransfer: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in' + ], + groupDefaults: groupDefaults.filterPrimitive, + content: [ + 'feFuncA', + 'feFuncB', + 'feFuncG', + 'feFuncR' + ] + }, + feComposite: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'in2', + 'operator', + 'k1', + 'k2', + 'k3', + 'k4' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + operator: 'over', + k1: '0', + k2: '0', + k3: '0', + k4: '0' + }, + content: [ + 'animate', + 'set' + ] + }, + feConvolveMatrix: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'order', + 'kernelMatrix', + // TODO: divisor - 'The default value is the sum of all values in kernelMatrix, + // with the exception that if the sum is zero, then the divisor is set to 1' + 'divisor', + 'bias', + // TODO: targetX - 'By default, the convolution matrix is centered in X over each + // pixel of the input image (i.e., targetX = floor ( orderX / 2 ))' + 'targetX', + 'targetY', + 'edgeMode', + // TODO: kernelUnitLength - 'The first number is the value. The second number + // is the value. If the value is not specified, it defaults to the same value as ' + 'kernelUnitLength', + 'preserveAlpha' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + order: '3', + bias: '0', + edgeMode: 'duplicate', + preserveAlpha: 'false' + }, + content: [ + 'animate', + 'set' + ] + }, + feDiffuseLighting: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'surfaceScale', + 'diffuseConstant', + 'kernelUnitLength' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + surfaceScale: '1', + diffuseConstant: '1' + }, + content: [ + elemsGroups.descriptive, + // TODO: 'exactly one light source element, in any order' + 'feDistantLight', + 'fePointLight', + 'feSpotLight' + ] + }, + feDisplacementMap: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'in2', + 'scale', + 'xChannelSelector', + 'yChannelSelector' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + scale: '0', + xChannelSelector: 'A', + yChannelSelector: 'A' + }, + content: [ + 'animate', + 'set' + ] + }, + feDistantLight: { + attrs: [ + attrsGroups.core, + 'azimuth', + 'elevation' + ], + defaults: { + azimuth: '0', + elevation: '0' + }, + content: [ + 'animate', + 'set' + ] + }, + feFlood: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style' + ], + groupDefaults: groupDefaults.filterPrimitive, + content: [ + 'animate', + 'animateColor', + 'set' + ] + }, + feFuncA: { + attrs: [ + attrsGroups.core, + attrsGroups.transferFunction + ], + groupDefaults: groupDefaults.transferFunction, + content: [ + 'set', + 'animate' + ] + }, + feFuncB: { + attrs: [ + attrsGroups.core, + attrsGroups.transferFunction + ], + groupDefaults: groupDefaults.transferFunction, + content: [ + 'set', + 'animate' + ] + }, + feFuncG: { + attrs: [ + attrsGroups.core, + attrsGroups.transferFunction + ], + groupDefaults: groupDefaults.transferFunction, + content: [ + 'set', + 'animate' + ] + }, + feFuncR: { + attrs: [ + attrsGroups.core, + attrsGroups.transferFunction + ], + groupDefaults: groupDefaults.transferFunction, + content: [ + 'set', + 'animate' + ] + }, + feGaussianBlur: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.filterPrimitive, + 'class', + 'style', + 'in', + 'stdDeviation' + ], + groupDefaults: groupDefaults.filterPrimitive, + defaults: { + stdDeviation: '0' + }, + content: [ + 'set', + 'animate' + ] + }, + feImage: {}, + feMerge: {}, + feMergeNode: {}, + feMorphology: {}, + feOffset: {}, + fePointLight: {}, + feSpecularLighting: {}, + feSpotLight: {}, + feTile: {}, + feTurbulence: {}, + filter: {}, + font: {}, + 'font-face': {}, + 'font-face-format': {}, + 'font-face-name': {}, + 'font-face-src': {}, + 'font-face-uri': {}, + foreignObject: {}, + g: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform' + ], + content: [ + elemsGroups.animation, + elemsGroups.descriptive, + elemsGroups.shape, + elemsGroups.structural, + elemsGroups.gradient, + 'a', + 'altGlyphDef', + 'clipPath', + 'color-profile', + 'cursor', + 'filter', + 'font', + 'font-face', + 'foreignObject', + 'image', + 'marker', + 'mask', + 'pattern', + 'script', + 'style', + 'switch', + 'text', + 'view' + ] + }, + glyph: {}, + glyphRef: {}, + hkern: {}, + image: { + attrs: [ + attrsGroups.core, + attrsGroups.conditionalProcessing, + attrsGroups.graphicalEvent, + attrsGroups.xlink, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'preserveAspectRatio', + 'transform', + 'x', + 'y', + 'width', + 'height', + 'xlink:href' + ], + defaults: { + x: '0', + y: '0', + preserveAspectRatio: 'xMidYMid meet' + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive + ] + }, + line: {}, + linearGradient: { + attrs: [ + attrsGroups.core, + attrsGroups.presentation, + attrsGroups.xlink, + 'class', + 'style', + 'externalResourcesRequired', + 'x1', + 'y1', + 'x2', + 'y2', + 'gradientUnits', + 'gradientTransform', + 'spreadMethod', + 'xlink:href' + ], + defaults: { + x1: '0', + y1: '0', + x2: '100%', + y2: '0', + spreadMethod: 'pad' + }, + content: [ + elemsGroups.descriptive, + 'animate', + 'animateTransform', + 'set', + 'stop' + ] + }, + marker: {}, + mask: {}, + metadata: {}, + 'missing-glyph': {}, + mpath: {}, + path: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'externalResourcesRequired', + 'transform', + 'd', + 'pathLength' + ], + content: [ + elemsGroups.animation, + elemsGroups.descriptive + ] + }, + pattern: {}, + polygon: {}, + polyline: {}, + radialGradient: { + defaults: { + cx: '50%', + cy: '50%', + r: '50%' + } + }, + rect: {}, + script: {}, + set: {}, + stop: {}, + style: {}, + svg: { + attrs: [ + attrsGroups.conditionalProcessing, + attrsGroups.core, + attrsGroups.documentEvent, + attrsGroups.graphicalEvent, + attrsGroups.presentation, + 'class', + 'style', + 'x', + 'y', + 'width', + 'height', + 'viewBox', + 'preserveAspectRatio', + 'zoomAndPan', + 'version', + 'baseProfile', + 'contentScriptType', + 'contentStyleType' + ], + defaults: { + x: '0', + y: '0', + width: '100%', + height: '100%', + preserveAspectRatio: 'xMidYMid meet', + zoomAndPan: 'magnify', + version: '1.1', + baseProfile: 'none', + contentScriptType: 'application/ecmascript', + contentStyleType: 'text/css' + }, + content: [ + elemsGroups.animation, + elemsGroups.descriptive, + elemsGroups.shape, + elemsGroups.structural, + elemsGroups.gradient, + 'a', + 'altGlyphDef', + 'clipPath', + 'color-profile', + 'cursor', + 'filter', + 'font', + 'font-face', + 'foreignObject', + 'image', + 'marker', + 'mask', + 'pattern', + 'script', + 'style', + 'switch', + 'text', + 'view' + ] + }, + switch: {}, + symbol: {}, + text: {}, + textPath: {}, + title: {}, + tref: {}, + tspan: {}, + use: {}, + view: {}, + vkern: {} +}; + + // http://wiki.inkscape.org/wiki/index.php/Inkscape-specific_XML_attributes exports.editorNamespaces = [ 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd', @@ -79,32 +898,6 @@ exports.stylingProps = [ 'writing-mode' ]; -// http://www.w3.org/TR/SVG/intro.html#Definitions -var elems = exports.elems = { - 'animation': ['animate', 'animateColor', 'animateMotion', 'animateTransform', 'set'], - 'descriptive': ['desc', 'metadata', 'title'], - 'shape': ['circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect'], - 'structural': ['defs', 'g', 'svg', 'symbol', 'use'], - 'gradient': ['linearGradient', 'radialGradient'], - // http://www.w3.org/TR/SVG/intro.html#TermContainerElement - 'container': ['a', 'defs', 'glyph', 'g', 'marker', 'mask', 'missing-glyph', 'pattern', 'svg', 'switch', 'symbol'] -}; - -// http://www.w3.org/TR/SVG/intro.html#Definitions -var attrs = exports.attrs = { - 'animationAddition': ['additive', 'accumulate'], - 'animationAttributeTarget': ['attributeType', 'attributeName'], - 'animationEvent': ['onbegin', 'onend', 'onrepeat', 'onload'], - 'animationTiming': ['begin', 'dur', 'end', 'min', 'max', 'restart', 'repeatCount', 'repeatDur', 'fill'], - 'animationValue': ['calcMode', 'values', 'keyTimes', 'keySplines', 'from', 'to', 'by'], - 'conditionalProcessing': ['requiredFeatures', 'requiredExtensions', 'systemLanguage'], - 'core': ['id', 'xml:base', 'xml:lang', 'xml:space'], - 'graphicalEvent': ['onfocusin', 'onfocusout', 'onactivate', 'onclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout', 'onload'], - 'presentation': ['alignment-baseline', 'baseline-shift', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', 'dominant-baseline', 'enable-background', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'overflow', 'pointer-events', 'shape-rendering', 'stop-color', 'stop-opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'unicode-bidi', 'visibility', 'word-spacing', 'writing-mode'], - 'xlink': ['xlink:href', 'xlink:show', 'xlink:actuate', 'xlink:type', 'xlink:role', 'xlink:arcrole', 'xlink:title'], - 'documentEvent': ['onunload', 'onabort', 'onerror', 'onresize', 'onscroll', 'onzoom'] -}; - // http://www.w3.org/TR/SVG/propidx.html exports.nonInheritedAttrs = [ 'alignment-baseline', diff --git a/plugins/removeEmptyContainers.js b/plugins/removeEmptyContainers.js index 8f49611f..66a329db 100644 --- a/plugins/removeEmptyContainers.js +++ b/plugins/removeEmptyContainers.js @@ -1,4 +1,4 @@ -var container = require('./_collections').elems.container; +var container = require('./_collections').elemsGroups.container; /** * Remove empty containers. diff --git a/plugins/removeUnknownsAndDefaults.js b/plugins/removeUnknownsAndDefaults.js new file mode 100644 index 00000000..a6ed9c27 --- /dev/null +++ b/plugins/removeUnknownsAndDefaults.js @@ -0,0 +1,87 @@ +var flattenOneLevel = require('../lib/svgo/tools').flattenOneLevel, + elems = require('./_collections').elems; + +// flatten and extend all collection references +for (var elem in elems) { + elem = elems[elem]; + + // attrs + if (elem.attrs) { + elem.attrs = flattenOneLevel(elem.attrs); + } + + // contennt + if (elem.content) { + elem.content = flattenOneLevel(elem.content); + } + + // extend defaults with groupDefaults + if (elem.groupDefaults) { + elem.defaults = elem.defaults || {}; + for(var groupDefault in elem.groupDefaults) { + elem.defaults[groupDefault] = elem.groupDefaults[groupDefault]; + } + } +} + +/** + * Remove unknown elements content and attributes, + * remove attributes with default values. + * + * @param {Object} item current iteration item + * @param {Object} params plugin params + * @return {Boolean} if false, item will be filtered out + * + * @author Kir Belevich + */ +exports.removeUnknownsAndDefaults = function(item, params) { + + // elems w/o namespace prefix + if (item.isElem() && !item.prefix) { + + var elem = item.elem; + + // remove unknown element's content + if ( + params.unknownContent && + !item.isEmpty() && + elems[elem].content + ) { + item.content.forEach(function(content, i) { + if ( + content.isElem() && + !content.prefix && + elems[elem].content.indexOf(content.elem) === -1 + ) { + item.content.splice(i, 1); + } + }); + } + + // remove element's unknown attrs and attrs with default values + if (elems[elem].attrs) { + + item.eachAttr(function(attr) { + + if (attr.name !== 'xmlns' && !attr.prefix) { + if ( + // unknown attrs + (params.unknownAttrs && + elems[elem].attrs.indexOf(attr.name) === -1) || + // attrs with default values + (params.defaultAttrs && + elems[elem].defaults && + elems[elem].defaults[attr.name] === attr.value + ) + ) { + item.removeAttr(attr.name); + } + } + + }); + + } + + } + +}; diff --git a/test/plugins/cleanupSVGElem.01.orig.svg b/test/plugins/cleanupSVGElem.01.orig.svg deleted file mode 100644 index 3cbe4fc2..00000000 --- a/test/plugins/cleanupSVGElem.01.orig.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/test/plugins/cleanupSVGElem.01.should.svg b/test/plugins/cleanupSVGElem.01.should.svg deleted file mode 100644 index 04fe48c1..00000000 --- a/test/plugins/cleanupSVGElem.01.should.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/test/plugins/removeUnknownsAndDefaults.01.orig.svg b/test/plugins/removeUnknownsAndDefaults.01.orig.svg new file mode 100644 index 00000000..d0b0d622 --- /dev/null +++ b/test/plugins/removeUnknownsAndDefaults.01.orig.svg @@ -0,0 +1,3 @@ + + test + diff --git a/test/plugins/removeUnknownsAndDefaults.01.should.svg b/test/plugins/removeUnknownsAndDefaults.01.should.svg new file mode 100644 index 00000000..de0295bb --- /dev/null +++ b/test/plugins/removeUnknownsAndDefaults.01.should.svg @@ -0,0 +1,3 @@ + + test + diff --git a/test/plugins/removeUnknownsAndDefaults.02.orig.svg b/test/plugins/removeUnknownsAndDefaults.02.orig.svg new file mode 100644 index 00000000..3ae88821 --- /dev/null +++ b/test/plugins/removeUnknownsAndDefaults.02.orig.svg @@ -0,0 +1,11 @@ + + + test + + + test + + + test + + diff --git a/test/plugins/removeUnknownsAndDefaults.02.should.svg b/test/plugins/removeUnknownsAndDefaults.02.should.svg new file mode 100644 index 00000000..8235d58a --- /dev/null +++ b/test/plugins/removeUnknownsAndDefaults.02.should.svg @@ -0,0 +1,8 @@ + + + test + + + test + +