Comparing version 0.3.3 to 0.4.0
@@ -55,3 +55,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SvgSaver = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
'overflow': 'visible', | ||
'paint-order': 'normal', | ||
'paint-order': 'fill', | ||
'pointer-events': 'auto', | ||
@@ -79,5 +79,5 @@ 'shape-rendering': 'auto', | ||
var svgAttrs = [// white list of attributes | ||
'id', 'xml:base', 'xml:lang', 'xml:space', // Core | ||
'id', 'xml: base', 'xml: lang', 'xml: space', // Core | ||
'height', 'result', 'width', 'x', 'y', // Primitive | ||
'xlink:href', // Xlink attribute | ||
'xlink: href', // Xlink attribute | ||
'style', 'class', 'd', 'pathLength', // Path | ||
@@ -104,7 +104,6 @@ 'x', 'y', 'dx', 'dy', 'glyphRef', 'format', 'x1', 'y1', 'x2', 'y2', 'rotate', 'textLength', 'cx', 'cy', 'r', 'rx', 'ry', 'fx', 'fy', 'width', 'height', 'refX', 'refY', 'orient', 'markerUnits', 'markerWidth', 'markerHeight', 'maskUnits', 'transform', 'viewBox', 'version', // Container | ||
//detection | ||
// detection | ||
var DownloadAttributeSupport = typeof document !== 'undefined' && 'download' in document.createElement('a'); | ||
function saveUri(uri, name) { | ||
if (DownloadAttributeSupport) { | ||
@@ -152,3 +151,3 @@ var dl = document.createElement('a'); | ||
}; | ||
var isObject = function isObject(a) { | ||
var _isObject = function _isObject(a) { | ||
return a !== null && typeof a === 'object'; | ||
@@ -159,4 +158,4 @@ }; | ||
function isNode(val) { | ||
if (!isObject(val)) return false; | ||
if (_isDefined(window) && isObject(window.Node)) return val instanceof window.Node; | ||
if (!_isObject(val)) return false; | ||
if (_isDefined(window) && _isObject(window.Node)) return val instanceof window.Node; | ||
return 'number' == typeof val.nodeType && 'string' == typeof val.nodeName; | ||
@@ -241,15 +240,35 @@ } | ||
// Clones an SVGElement, copyies approprate atttributes and styles. | ||
function cleanStyle(tgt, parentStyles) { | ||
if (tgt.style) { | ||
inheritableAttrs.forEach(function (key) { | ||
if (tgt.style[key] === parentStyles[key]) { | ||
tgt.style.removeProperty(key); | ||
} | ||
}); | ||
} | ||
} | ||
function walker(attrs, defaultStyles) { | ||
return function walk(src, tgt) { | ||
if (!tgt.style) return; | ||
computedStyles(src, tgt.style, defaultStyles); | ||
var children = src.childNodes; | ||
for (var i = 0; i < children.length; i++) { | ||
walk(children[i], tgt.childNodes[i]); | ||
cleanStyle(tgt.childNodes[i], tgt.style); | ||
} | ||
if (tgt.attributes) { | ||
cleanAttrs(tgt, attrs, defaultStyles); | ||
} | ||
}; | ||
} | ||
// Clones an SVGElement, copies approprate atttributes and styles. | ||
function cloneSvg(src, attrs, styles) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
walker(attrs, styles)(src, clonedSvg); | ||
computedStyles(src, clonedSvg.style, styles); | ||
cleanAttrs(clonedSvg, attrs, styles); | ||
Array.prototype.slice.call(clonedSvg.querySelectorAll('*')).forEach(function (target, index) { | ||
computedStyles(srcChildren[index], target.style, styles); | ||
cleanAttrs(target, attrs, styles); | ||
}); | ||
return clonedSvg; | ||
@@ -256,0 +275,0 @@ } |
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SvgSaver=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor}}();function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}var svgStyles={"alignment-baseline":"auto","baseline-shift":"baseline",clip:"auto","clip-path":"none","clip-rule":"nonzero",color:"rgb(51, 51, 51)","color-interpolation":"srgb","color-interpolation-filters":"linearrgb","color-profile":"auto","color-rendering":"auto",cursor:"auto",direction:"ltr",display:"inline","dominant-baseline":"auto","enable-background":"",fill:"rgb(0, 0, 0)","fill-opacity":"1","fill-rule":"nonzero",filter:"none","flood-color":"rgb(0, 0, 0)","flood-opacity":"1",font:"","font-family":"normal","font-size":"medium","font-size-adjust":"auto","font-stretch":"normal","font-style":"normal","font-variant":"normal","font-weight":"400","glyph-orientation-horizontal":"0deg","glyph-orientation-vertical":"auto","image-rendering":"auto",kerning:"auto","letter-spacing":"0","lighting-color":"rgb(255, 255, 255)",marker:"","marker-end":"none","marker-mid":"none","marker-start":"none",mask:"none",opacity:"1",overflow:"visible","paint-order":"normal","pointer-events":"auto","shape-rendering":"auto","stop-color":"rgb(0, 0, 0)","stop-opacity":"1",stroke:"none","stroke-dasharray":"none","stroke-dashoffset":"0","stroke-linecap":"butt","stroke-linejoin":"miter","stroke-miterlimit":"4","stroke-opacity":"1","stroke-width":"1","text-anchor":"start","text-decoration":"none","text-rendering":"auto","unicode-bidi":"normal",visibility:"visible","word-spacing":"0px","writing-mode":"lr-tb"};var svgAttrs=["id","xml:base","xml:lang","xml:space","height","result","width","x","y","xlink:href","style","class","d","pathLength","x","y","dx","dy","glyphRef","format","x1","y1","x2","y2","rotate","textLength","cx","cy","r","rx","ry","fx","fy","width","height","refX","refY","orient","markerUnits","markerWidth","markerHeight","maskUnits","transform","viewBox","version","preserveAspectRatio","xmlns","points","offset"];var inheritableAttrs=["clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cursor","direction","fill","fill-opacity","fill-rule","font","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","marker","marker-end","marker-mid","marker-start","pointer-events","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-anchor","text-rendering","transform","visibility","white-space","word-spacing","writing-mode"];var isFunction=function isFunction(a){return typeof a==="function"};var isDefined=function isDefined(a){return typeof a!=="undefined"};var isUndefined=function isUndefined(a){return typeof a==="undefined"};var DownloadAttributeSupport=typeof document!=="undefined"&&"download"in document.createElement("a");function saveUri(uri,name){if(DownloadAttributeSupport){var dl=document.createElement("a");dl.setAttribute("href",uri);dl.setAttribute("download",name);dl.click();return true}else if(typeof window!=="undefined"){window.open(uri,"_blank","");return true}return false}function savePng(uri,name){var canvas=document.createElement("canvas");var context=canvas.getContext("2d");var image=new Image;image.onload=function(){canvas.width=image.width;canvas.height=image.height;context.drawImage(image,0,0);if(isDefined(window.saveAs)&&isDefined(canvas.toBlob)){canvas.toBlob(function(blob){saveAs(blob,name)})}else{saveUri(canvas.toDataURL("image/png"),name)}};image.src=uri;return true}var _isDefined=function _isDefined(a){return typeof a!=="undefined"};var _isUndefined=function _isUndefined(a){return typeof a==="undefined"};var isObject=function isObject(a){return a!==null&&typeof a==="object"};function isNode(val){if(!isObject(val))return false;if(_isDefined(window)&&isObject(window.Node))return val instanceof window.Node;return"number"==typeof val.nodeType&&"string"==typeof val.nodeName}var useComputedStyles=_isDefined(window)&&_isDefined(window.getComputedStyle);function getComputedStyles(node){if(useComputedStyles){var view=node.ownerDocument.defaultView;if(!view.opener)view=window;return view.getComputedStyle(node,null)}else{return node.currentStyle||node.style}}function computedStyles(node){var target=arguments.length<=1||arguments[1]===undefined?{}:arguments[1];var styleList=arguments.length<=2||arguments[2]===undefined?true:arguments[2];if(!isNode(node)){throw new Error("parameter 1 is not of type 'Element'")}if(styleList===false)return target;var computed=getComputedStyles(node);if(styleList===true){var keysArray=useComputedStyles?computed:Object.keys(computed)}else{var keysArray=Object.keys(styleList)}for(var i=0,l=keysArray.length;i<l;i++){var key=keysArray[i];var def=styleList===true||styleList[key];if(def===false||_isUndefined(def))continue;var value=computed[key];if(typeof value!=="string"||value==="")continue;if(def===true||value!==def){target[key]=value}}return target}function cleanAttrs(el,attrs,styles){if(attrs===true){return}Array.prototype.slice.call(el.attributes).forEach(function(attr){if(attr.specified){if(attrs===""||attrs===false||isUndefined(styles[attr.name])&&attrs.indexOf(attr.name)<0){el.removeAttribute(attr.name)}}})}function cloneSvg(src,attrs,styles){var clonedSvg=src.cloneNode(true);var srcChildren=src.querySelectorAll("*");computedStyles(src,clonedSvg.style,styles);cleanAttrs(clonedSvg,attrs,styles);Array.prototype.slice.call(clonedSvg.querySelectorAll("*")).forEach(function(target,index){computedStyles(srcChildren[index],target.style,styles);cleanAttrs(target,attrs,styles)});return clonedSvg}inheritableAttrs.forEach(function(k){if(k in svgStyles){svgStyles[k]=true}});var SvgSaver=function(){function SvgSaver(){var _ref=arguments.length<=0||arguments[0]===undefined?{}:arguments[0];var attrs=_ref.attrs;var styles=_ref.styles;_classCallCheck(this,SvgSaver);this.attrs=attrs===undefined?svgAttrs:attrs;this.styles=styles===undefined?svgStyles:styles}_createClass(SvgSaver,[{key:"getHTML",value:function getHTML(el){var svg=cloneSvg(el,this.attrs,this.styles);svg.setAttribute("xmlns","http://www.w3.org/2000/svg");svg.setAttribute("version",1.1);svg.setAttribute("width",svg.getAttribute("width")||"500");svg.setAttribute("height",svg.getAttribute("height")||"900");return svg.outerHTML||(new window.XMLSerializer).serializeToString(svg)}},{key:"getBlob",value:function getBlob(el){var html=this.getHTML(el);return new Blob([html],{type:"text/xml"})}},{key:"getUri",value:function getUri(el){var html=this.getHTML(el);if(isDefined(window.btoa)){return"data:image/svg+xml;base64,"+window.btoa(html)}return"data:image/svg+xml,"+encodeURIComponent(html)}},{key:"asSvg",value:function asSvg(el,filename){if(!filename||filename===""){filename=el.getAttribute("title");filename=(filename||"untitled")+".svg"}if(isDefined(window.saveAs)&&isFunction(Blob)){return saveAs(this.getBlob(el),filename)}else{return saveUri(this.getUri(el),filename)}}},{key:"asPng",value:function asPng(el,filename){if(!filename||filename===""){filename=el.getAttribute("title");filename=(filename||"untitled")+".png"}return savePng(this.getUri(el),filename)}}]);return SvgSaver}();exports["default"]=SvgSaver;module.exports=exports["default"]},{}]},{},[1])(1)}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SvgSaver=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor}}();function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}var svgStyles={"alignment-baseline":"auto","baseline-shift":"baseline",clip:"auto","clip-path":"none","clip-rule":"nonzero",color:"rgb(51, 51, 51)","color-interpolation":"srgb","color-interpolation-filters":"linearrgb","color-profile":"auto","color-rendering":"auto",cursor:"auto",direction:"ltr",display:"inline","dominant-baseline":"auto","enable-background":"",fill:"rgb(0, 0, 0)","fill-opacity":"1","fill-rule":"nonzero",filter:"none","flood-color":"rgb(0, 0, 0)","flood-opacity":"1",font:"","font-family":"normal","font-size":"medium","font-size-adjust":"auto","font-stretch":"normal","font-style":"normal","font-variant":"normal","font-weight":"400","glyph-orientation-horizontal":"0deg","glyph-orientation-vertical":"auto","image-rendering":"auto",kerning:"auto","letter-spacing":"0","lighting-color":"rgb(255, 255, 255)",marker:"","marker-end":"none","marker-mid":"none","marker-start":"none",mask:"none",opacity:"1",overflow:"visible","paint-order":"fill","pointer-events":"auto","shape-rendering":"auto","stop-color":"rgb(0, 0, 0)","stop-opacity":"1",stroke:"none","stroke-dasharray":"none","stroke-dashoffset":"0","stroke-linecap":"butt","stroke-linejoin":"miter","stroke-miterlimit":"4","stroke-opacity":"1","stroke-width":"1","text-anchor":"start","text-decoration":"none","text-rendering":"auto","unicode-bidi":"normal",visibility:"visible","word-spacing":"0px","writing-mode":"lr-tb"};var svgAttrs=["id","xml: base","xml: lang","xml: space","height","result","width","x","y","xlink: href","style","class","d","pathLength","x","y","dx","dy","glyphRef","format","x1","y1","x2","y2","rotate","textLength","cx","cy","r","rx","ry","fx","fy","width","height","refX","refY","orient","markerUnits","markerWidth","markerHeight","maskUnits","transform","viewBox","version","preserveAspectRatio","xmlns","points","offset"];var inheritableAttrs=["clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cursor","direction","fill","fill-opacity","fill-rule","font","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","marker","marker-end","marker-mid","marker-start","pointer-events","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-anchor","text-rendering","transform","visibility","white-space","word-spacing","writing-mode"];var isFunction=function isFunction(a){return typeof a==="function"};var isDefined=function isDefined(a){return typeof a!=="undefined"};var isUndefined=function isUndefined(a){return typeof a==="undefined"};var DownloadAttributeSupport=typeof document!=="undefined"&&"download"in document.createElement("a");function saveUri(uri,name){if(DownloadAttributeSupport){var dl=document.createElement("a");dl.setAttribute("href",uri);dl.setAttribute("download",name);dl.click();return true}else if(typeof window!=="undefined"){window.open(uri,"_blank","");return true}return false}function savePng(uri,name){var canvas=document.createElement("canvas");var context=canvas.getContext("2d");var image=new Image;image.onload=function(){canvas.width=image.width;canvas.height=image.height;context.drawImage(image,0,0);if(isDefined(window.saveAs)&&isDefined(canvas.toBlob)){canvas.toBlob(function(blob){saveAs(blob,name)})}else{saveUri(canvas.toDataURL("image/png"),name)}};image.src=uri;return true}var _isDefined=function _isDefined(a){return typeof a!=="undefined"};var _isUndefined=function _isUndefined(a){return typeof a==="undefined"};var _isObject=function _isObject(a){return a!==null&&typeof a==="object"};function isNode(val){if(!_isObject(val))return false;if(_isDefined(window)&&_isObject(window.Node))return val instanceof window.Node;return"number"==typeof val.nodeType&&"string"==typeof val.nodeName}var useComputedStyles=_isDefined(window)&&_isDefined(window.getComputedStyle);function getComputedStyles(node){if(useComputedStyles){var view=node.ownerDocument.defaultView;if(!view.opener)view=window;return view.getComputedStyle(node,null)}else{return node.currentStyle||node.style}}function computedStyles(node){var target=arguments.length<=1||arguments[1]===undefined?{}:arguments[1];var styleList=arguments.length<=2||arguments[2]===undefined?true:arguments[2];if(!isNode(node)){throw new Error("parameter 1 is not of type 'Element'")}if(styleList===false)return target;var computed=getComputedStyles(node);if(styleList===true){var keysArray=useComputedStyles?computed:Object.keys(computed)}else{var keysArray=Object.keys(styleList)}for(var i=0,l=keysArray.length;i<l;i++){var key=keysArray[i];var def=styleList===true||styleList[key];if(def===false||_isUndefined(def))continue;var value=computed[key];if(typeof value!=="string"||value==="")continue;if(def===true||value!==def){target[key]=value}}return target}function cleanAttrs(el,attrs,styles){if(attrs===true){return}Array.prototype.slice.call(el.attributes).forEach(function(attr){if(attr.specified){if(attrs===""||attrs===false||isUndefined(styles[attr.name])&&attrs.indexOf(attr.name)<0){el.removeAttribute(attr.name)}}})}function cleanStyle(tgt,parentStyles){if(tgt.style){inheritableAttrs.forEach(function(key){if(tgt.style[key]===parentStyles[key]){tgt.style.removeProperty(key)}})}}function walker(attrs,defaultStyles){return function walk(src,tgt){if(!tgt.style)return;computedStyles(src,tgt.style,defaultStyles);var children=src.childNodes;for(var i=0;i<children.length;i++){walk(children[i],tgt.childNodes[i]);cleanStyle(tgt.childNodes[i],tgt.style)}if(tgt.attributes){cleanAttrs(tgt,attrs,defaultStyles)}}}function cloneSvg(src,attrs,styles){var clonedSvg=src.cloneNode(true);walker(attrs,styles)(src,clonedSvg);return clonedSvg}inheritableAttrs.forEach(function(k){if(k in svgStyles){svgStyles[k]=true}});var SvgSaver=function(){function SvgSaver(){var _ref=arguments.length<=0||arguments[0]===undefined?{}:arguments[0];var attrs=_ref.attrs;var styles=_ref.styles;_classCallCheck(this,SvgSaver);this.attrs=attrs===undefined?svgAttrs:attrs;this.styles=styles===undefined?svgStyles:styles}_createClass(SvgSaver,[{key:"getHTML",value:function getHTML(el){var svg=cloneSvg(el,this.attrs,this.styles);svg.setAttribute("xmlns","http://www.w3.org/2000/svg");svg.setAttribute("version",1.1);svg.setAttribute("width",svg.getAttribute("width")||"500");svg.setAttribute("height",svg.getAttribute("height")||"900");return svg.outerHTML||(new window.XMLSerializer).serializeToString(svg)}},{key:"getBlob",value:function getBlob(el){var html=this.getHTML(el);return new Blob([html],{type:"text/xml"})}},{key:"getUri",value:function getUri(el){var html=this.getHTML(el);if(isDefined(window.btoa)){return"data:image/svg+xml;base64,"+window.btoa(html)}return"data:image/svg+xml,"+encodeURIComponent(html)}},{key:"asSvg",value:function asSvg(el,filename){if(!filename||filename===""){filename=el.getAttribute("title");filename=(filename||"untitled")+".svg"}if(isDefined(window.saveAs)&&isFunction(Blob)){return saveAs(this.getBlob(el),filename)}else{return saveUri(this.getUri(el),filename)}}},{key:"asPng",value:function asPng(el,filename){if(!filename||filename===""){filename=el.getAttribute("title");filename=(filename||"untitled")+".png"}return savePng(this.getUri(el),filename)}}]);return SvgSaver}();exports["default"]=SvgSaver;module.exports=exports["default"]},{}]},{},[1])(1)}); |
@@ -9,2 +9,5 @@ CHANGELOG | ||
## 0.4.0 (2015-11-05) | ||
* Clean superfluous inheritable styles | ||
## 0.3.3 (2015-10-28) | ||
@@ -22,2 +25,1 @@ * Use latest computed-styles, fixes IE11 | ||
* No longer removes styles from elements that match parent styles (not all styles are inheritable) | ||
@@ -54,3 +54,3 @@ 'use strict'; | ||
'overflow': 'visible', | ||
'paint-order': 'normal', | ||
'paint-order': 'fill', | ||
'pointer-events': 'auto', | ||
@@ -78,5 +78,5 @@ 'shape-rendering': 'auto', | ||
var svgAttrs = [// white list of attributes | ||
'id', 'xml:base', 'xml:lang', 'xml:space', // Core | ||
'id', 'xml: base', 'xml: lang', 'xml: space', // Core | ||
'height', 'result', 'width', 'x', 'y', // Primitive | ||
'xlink:href', // Xlink attribute | ||
'xlink: href', // Xlink attribute | ||
'style', 'class', 'd', 'pathLength', // Path | ||
@@ -103,7 +103,6 @@ 'x', 'y', 'dx', 'dy', 'glyphRef', 'format', 'x1', 'y1', 'x2', 'y2', 'rotate', 'textLength', 'cx', 'cy', 'r', 'rx', 'ry', 'fx', 'fy', 'width', 'height', 'refX', 'refY', 'orient', 'markerUnits', 'markerWidth', 'markerHeight', 'maskUnits', 'transform', 'viewBox', 'version', // Container | ||
//detection | ||
// detection | ||
var DownloadAttributeSupport = typeof document !== 'undefined' && 'download' in document.createElement('a'); | ||
function saveUri(uri, name) { | ||
if (DownloadAttributeSupport) { | ||
@@ -151,3 +150,3 @@ var dl = document.createElement('a'); | ||
}; | ||
var isObject = function isObject(a) { | ||
var _isObject = function _isObject(a) { | ||
return a !== null && typeof a === 'object'; | ||
@@ -158,4 +157,4 @@ }; | ||
function isNode(val) { | ||
if (!isObject(val)) return false; | ||
if (_isDefined(window) && isObject(window.Node)) return val instanceof window.Node; | ||
if (!_isObject(val)) return false; | ||
if (_isDefined(window) && _isObject(window.Node)) return val instanceof window.Node; | ||
return 'number' == typeof val.nodeType && 'string' == typeof val.nodeName; | ||
@@ -240,15 +239,35 @@ } | ||
// Clones an SVGElement, copyies approprate atttributes and styles. | ||
function cleanStyle(tgt, parentStyles) { | ||
if (tgt.style) { | ||
inheritableAttrs.forEach(function (key) { | ||
if (tgt.style[key] === parentStyles[key]) { | ||
tgt.style.removeProperty(key); | ||
} | ||
}); | ||
} | ||
} | ||
function walker(attrs, defaultStyles) { | ||
return function walk(src, tgt) { | ||
if (!tgt.style) return; | ||
computedStyles(src, tgt.style, defaultStyles); | ||
var children = src.childNodes; | ||
for (var i = 0; i < children.length; i++) { | ||
walk(children[i], tgt.childNodes[i]); | ||
cleanStyle(tgt.childNodes[i], tgt.style); | ||
} | ||
if (tgt.attributes) { | ||
cleanAttrs(tgt, attrs, defaultStyles); | ||
} | ||
}; | ||
} | ||
// Clones an SVGElement, copies approprate atttributes and styles. | ||
function cloneSvg(src, attrs, styles) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
walker(attrs, styles)(src, clonedSvg); | ||
computedStyles(src, clonedSvg.style, styles); | ||
cleanAttrs(clonedSvg, attrs, styles); | ||
Array.prototype.slice.call(clonedSvg.querySelectorAll('*')).forEach(function (target, index) { | ||
computedStyles(srcChildren[index], target.style, styles); | ||
cleanAttrs(target, attrs, styles); | ||
}); | ||
return clonedSvg; | ||
@@ -255,0 +274,0 @@ } |
{ | ||
"name": "svgsaver", | ||
"version": "0.3.3", | ||
"version": "0.4.0", | ||
"description": "download an SVG element with css styles", | ||
@@ -10,12 +10,15 @@ "main": "lib/svgsaver.js", | ||
"uglify": "uglifyjs browser.js -o browser.min.js", | ||
"test": "npm run compile && karma start", | ||
"test": "npm run zuul:phantom", | ||
"compile": "npm run rollup && npm run browserify && npm run uglify", | ||
"build": "npm run compile && npm run jsdoc2md", | ||
"lint": "eslint src/ test/", | ||
"lint": "semistandard test/*.js src/*.js", | ||
"check": "npm run lint -s && dependency-check package.json --entry src", | ||
"watch": "watch \"npm run build\" src/", | ||
"watch:test": "watch \"npm test\" src/ test/", | ||
"demo": "live-server --open=demo --ignore=src", | ||
"start": "npm run demo & npm run watch", | ||
"jsdoc2md": "jsdoc-parse ./src/svgsaver.js | dmd > API.md", | ||
"version": "chg release -y && git add -A CHANGELOG.md" | ||
"version": "chg release -y && git add -A CHANGELOG.md", | ||
"zuul:server": "zuul --local 9966 --ui tape -- test/svgsaver-spec.js", | ||
"zuul:phantom": "zuul --phantom --ui tape -- test/svgsaver-spec.js | tap-spec" | ||
}, | ||
@@ -33,19 +36,16 @@ "keywords": [ | ||
"babel": "^5.8.23", | ||
"babelify": "^6.4.0", | ||
"browserify": "^11.2.0", | ||
"dependency-check": "^2.5.1", | ||
"dmd": "^1.2.0", | ||
"eslint": "^1.4.3", | ||
"jasmine-core": "^2.3.4", | ||
"jsdoc-parse": "^1.1.0", | ||
"karma": "^0.13.9", | ||
"karma-chrome-launcher": "^0.2.0", | ||
"karma-firefox-launcher": "^0.1.6", | ||
"karma-ie-launcher": "^0.2.0", | ||
"karma-jasmine": "^0.3.6", | ||
"karma-phantomjs-launcher": "^0.2.1", | ||
"live-server": "^0.8.1", | ||
"phantomjs": "^1.9.18", | ||
"rollup": "^0.16.4", | ||
"semistandard": "^7.0.2", | ||
"tap-spec": "^4.1.0", | ||
"tape": "^4.2.2", | ||
"uglifyjs": "^2.4.10", | ||
"watch": "^0.16.0" | ||
"watch": "^0.16.0", | ||
"zuul": "^3.6.0" | ||
}, | ||
@@ -52,0 +52,0 @@ "dependencies": { |
@@ -5,5 +5,12 @@ # svgsaver | ||
[![NPM version][npm-image]][npm-url] | ||
[![Downloads][download-badge]][npm-url] | ||
[![NPM version][npm-badge]][npm] | ||
[![Downloads][download-badge]][npm] | ||
![Downloads][bower-badge] | ||
[![Build Status][travis-image]][travis-url] | ||
[![Codacy Badge][codacy-badge]][Codacy] | ||
[![js-semistandard-style][standard-badge]][semistandard] | ||
[![License][license-badge]][MIT License] | ||
## Features | ||
@@ -60,7 +67,17 @@ - Download `<svg>` by element object. | ||
## License | ||
[MIT License](http://en.wikipedia.org/wiki/MIT_License) | ||
[MIT License] | ||
[npm-url]: https://npmjs.org/package/svgsaver | ||
[npm-image]: https://img.shields.io/npm/v/svgsaver.svg?style=flat-square | ||
[npm]: https://npmjs.org/package/svgsaver | ||
[bower]: https://npmjs.org/package/svgsaver | ||
[semistandard]: https://github.com/Flet/semistandard | ||
[Codacy]: https://www.codacy.com/app/hypercubed/svgsaver | ||
[MIT License]: http://en.wikipedia.org/wiki/MIT_License | ||
[travis-url]: https://travis-ci.org/Hypercubed/svgsaver | ||
[download-badge]: http://img.shields.io/npm/dm/svgsaver.svg?style=flat-squar | ||
[travis-image]: https://img.shields.io/travis/Hypercubed/svgsaver.svg | ||
[npm-badge]: https://img.shields.io/npm/v/svgsaver.svg | ||
[bower-badge]: https://img.shields.io/bower/v/svgsaver.svg | ||
[standard-badge]: https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg | ||
[download-badge]: http://img.shields.io/npm/dm/svgsaver.svg | ||
[codacy-badge]: https://api.codacy.com/project/badge/6fe47dae30b34d2da78572b3ea36cfe0 | ||
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg |
/* Some utilities for cloning SVGs with inline styles */ | ||
import computedStyles from 'computed-styles'; | ||
import {isUndefined} from './utils'; | ||
import {isUndefined, isObject, clone} from './utils'; | ||
import {inheritableAttrs} from './collection'; | ||
// Removes attributes that are not valid for SVGs | ||
function cleanAttrs(el, attrs, styles) { // attrs === false - remove all, attrs === true - allow all | ||
function cleanAttrs (el, attrs, styles) { // attrs === false - remove all, attrs === true - allow all | ||
if (attrs === true) { return; } | ||
Array.prototype.slice.call(el.attributes) | ||
.forEach(function(attr) { | ||
.forEach(function (attr) { | ||
// remove if it is not style nor on attrs whitelist | ||
// keeping attributes that are also styles because attributes override | ||
if (attr.specified) { | ||
if(attrs ==='' || attrs === false || (isUndefined(styles[attr.name]) && attrs.indexOf(attr.name) < 0)) { | ||
if (attrs === '' || attrs === false || (isUndefined(styles[attr.name]) && attrs.indexOf(attr.name) < 0)) { | ||
el.removeAttribute(attr.name); | ||
@@ -21,17 +22,36 @@ } | ||
// Clones an SVGElement, copyies approprate atttributes and styles. | ||
export function cloneSvg(src, attrs, styles) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
function cleanStyle (tgt, parentStyles) { | ||
if (tgt.style) { | ||
inheritableAttrs.forEach(function (key) { | ||
if (tgt.style[key] === parentStyles[key]) { | ||
tgt.style.removeProperty(key); | ||
} | ||
}); | ||
} | ||
} | ||
computedStyles(src, clonedSvg.style, styles); | ||
cleanAttrs(clonedSvg, attrs, styles); | ||
function walker (attrs, defaultStyles) { | ||
return function walk (src, tgt) { | ||
if (!tgt.style) return; | ||
Array.prototype.slice.call(clonedSvg.querySelectorAll('*')) | ||
.forEach(function( target, index ) { | ||
computedStyles(srcChildren[index], target.style, styles); | ||
cleanAttrs(target, attrs, styles); | ||
}); | ||
computedStyles(src, tgt.style, defaultStyles); | ||
const children = src.childNodes; | ||
for (var i = 0; i < children.length; i++) { | ||
walk(children[i], tgt.childNodes[i]); | ||
cleanStyle(tgt.childNodes[i], tgt.style); | ||
} | ||
if (tgt.attributes) { | ||
cleanAttrs(tgt, attrs, defaultStyles); | ||
} | ||
}; | ||
} | ||
// Clones an SVGElement, copies approprate atttributes and styles. | ||
export function cloneSvg (src, attrs, styles) { | ||
const clonedSvg = src.cloneNode(true); | ||
walker(attrs, styles)(src, clonedSvg); | ||
return clonedSvg; | ||
} |
export const svgStyles = { // Whitelist of CSS styles and default values | ||
'alignment-baseline':'auto', | ||
'baseline-shift':'baseline', | ||
'clip':'auto', | ||
'clip-path':'none', | ||
'clip-rule':'nonzero', | ||
'color':'rgb(51, 51, 51)', | ||
'color-interpolation':'srgb', | ||
'color-interpolation-filters':'linearrgb', | ||
'color-profile':'auto', | ||
'color-rendering':'auto', | ||
'cursor':'auto', | ||
'direction':'ltr', | ||
'display':'inline', | ||
'dominant-baseline':'auto', | ||
'enable-background':'', | ||
'fill':'rgb(0, 0, 0)', | ||
'fill-opacity':'1', | ||
'fill-rule':'nonzero', | ||
'filter':'none', | ||
'flood-color':'rgb(0, 0, 0)', | ||
'flood-opacity':'1', | ||
'font':'', | ||
'font-family':'normal', | ||
'font-size':'medium', | ||
'font-size-adjust':'auto', | ||
'font-stretch':'normal', | ||
'font-style':'normal', | ||
'font-variant':'normal', | ||
'font-weight':'400', | ||
'glyph-orientation-horizontal':'0deg', | ||
'glyph-orientation-vertical':'auto', | ||
'image-rendering':'auto', | ||
'kerning':'auto', | ||
'letter-spacing':'0', | ||
'lighting-color':'rgb(255, 255, 255)', | ||
'marker':'', | ||
'marker-end':'none', | ||
'marker-mid':'none', | ||
'marker-start':'none', | ||
'mask':'none', | ||
'opacity':'1', | ||
'overflow':'visible', | ||
'paint-order': 'normal', | ||
'pointer-events':'auto', | ||
'shape-rendering':'auto', | ||
'stop-color':'rgb(0, 0, 0)', | ||
'stop-opacity':'1', | ||
'stroke':'none', | ||
'stroke-dasharray':'none', | ||
'stroke-dashoffset':'0', | ||
'stroke-linecap':'butt', | ||
'stroke-linejoin':'miter', | ||
'stroke-miterlimit':'4', | ||
'stroke-opacity':'1', | ||
'stroke-width':'1', | ||
'text-anchor':'start', | ||
'text-decoration':'none', | ||
'text-rendering':'auto', | ||
'unicode-bidi':'normal', | ||
'visibility':'visible', | ||
'word-spacing':'0px', | ||
'writing-mode':'lr-tb' | ||
'alignment-baseline': 'auto', | ||
'baseline-shift': 'baseline', | ||
'clip': 'auto', | ||
'clip-path': 'none', | ||
'clip-rule': 'nonzero', | ||
'color': 'rgb(51, 51, 51)', | ||
'color-interpolation': 'srgb', | ||
'color-interpolation-filters': 'linearrgb', | ||
'color-profile': 'auto', | ||
'color-rendering': 'auto', | ||
'cursor': 'auto', | ||
'direction': 'ltr', | ||
'display': 'inline', | ||
'dominant-baseline': 'auto', | ||
'enable-background': '', | ||
'fill': 'rgb(0, 0, 0)', | ||
'fill-opacity': '1', | ||
'fill-rule': 'nonzero', | ||
'filter': 'none', | ||
'flood-color': 'rgb(0, 0, 0)', | ||
'flood-opacity': '1', | ||
'font': '', | ||
'font-family': 'normal', | ||
'font-size': 'medium', | ||
'font-size-adjust': 'auto', | ||
'font-stretch': 'normal', | ||
'font-style': 'normal', | ||
'font-variant': 'normal', | ||
'font-weight': '400', | ||
'glyph-orientation-horizontal': '0deg', | ||
'glyph-orientation-vertical': 'auto', | ||
'image-rendering': 'auto', | ||
'kerning': 'auto', | ||
'letter-spacing': '0', | ||
'lighting-color': 'rgb(255, 255, 255)', | ||
'marker': '', | ||
'marker-end': 'none', | ||
'marker-mid': 'none', | ||
'marker-start': 'none', | ||
'mask': 'none', | ||
'opacity': '1', | ||
'overflow': 'visible', | ||
'paint-order': 'fill', | ||
'pointer-events': 'auto', | ||
'shape-rendering': 'auto', | ||
'stop-color': 'rgb(0, 0, 0)', | ||
'stop-opacity': '1', | ||
'stroke': 'none', | ||
'stroke-dasharray': 'none', | ||
'stroke-dashoffset': '0', | ||
'stroke-linecap': 'butt', | ||
'stroke-linejoin': 'miter', | ||
'stroke-miterlimit': '4', | ||
'stroke-opacity': '1', | ||
'stroke-width': '1', | ||
'text-anchor': 'start', | ||
'text-decoration': 'none', | ||
'text-rendering': 'auto', | ||
'unicode-bidi': 'normal', | ||
'visibility': 'visible', | ||
'word-spacing': '0px', | ||
'writing-mode': 'lr-tb' | ||
}; | ||
export const svgAttrs = [ // white list of attributes | ||
'id', 'xml:base', 'xml:lang', 'xml:space', // Core | ||
'id', 'xml: base', 'xml: lang', 'xml: space', // Core | ||
'height', 'result', 'width', 'x', 'y', // Primitive | ||
'xlink:href', // Xlink attribute | ||
'style','class', | ||
'd','pathLength', // Path | ||
'x','y','dx','dy','glyphRef','format', | ||
'x1','y1','x2','y2', | ||
'rotate','textLength', | ||
'cx','cy','r', | ||
'rx','ry', | ||
'fx','fy', | ||
'width','height', | ||
'refX','refY','orient', | ||
'markerUnits','markerWidth','markerHeight', | ||
'xlink: href', // Xlink attribute | ||
'style', 'class', | ||
'd', 'pathLength', // Path | ||
'x', 'y', 'dx', 'dy', 'glyphRef', 'format', | ||
'x1', 'y1', 'x2', 'y2', | ||
'rotate', 'textLength', | ||
'cx', 'cy', 'r', | ||
'rx', 'ry', | ||
'fx', 'fy', | ||
'width', 'height', | ||
'refX', 'refY', 'orient', | ||
'markerUnits', 'markerWidth', 'markerHeight', | ||
'maskUnits', | ||
'transform', | ||
'viewBox','version', // Container | ||
'preserveAspectRatio','xmlns', | ||
'viewBox', 'version', // Container | ||
'preserveAspectRatio', 'xmlns', | ||
'points', // Polygons | ||
@@ -86,0 +86,0 @@ 'offset' |
@@ -1,2 +0,2 @@ | ||
/* global saveAs:true */ | ||
/* global saveAs Image */ | ||
@@ -7,7 +7,6 @@ /* Some simple utilities for saving SVGs, including an alternative to saveAs */ | ||
//detection | ||
// detection | ||
const DownloadAttributeSupport = (typeof document !== 'undefined') && ('download' in document.createElement('a')); | ||
export function saveUri(uri, name){ | ||
export function saveUri (uri, name) { | ||
if (DownloadAttributeSupport) { | ||
@@ -27,3 +26,3 @@ const dl = document.createElement('a'); | ||
export function savePng(uri, name){ | ||
export function savePng (uri, name) { | ||
const canvas = document.createElement('canvas'); | ||
@@ -33,3 +32,3 @@ const context = canvas.getContext('2d'); | ||
const image = new Image(); | ||
image.onload = function() { | ||
image.onload = function () { | ||
canvas.width = image.width; | ||
@@ -40,3 +39,3 @@ canvas.height = image.height; | ||
if (isDefined(window.saveAs) && isDefined(canvas.toBlob)) { | ||
canvas.toBlob(function(blob) { | ||
canvas.toBlob(function (blob) { | ||
saveAs(blob, name); | ||
@@ -47,3 +46,2 @@ }); | ||
} | ||
}; | ||
@@ -50,0 +48,0 @@ image.src = uri; |
@@ -1,2 +0,2 @@ | ||
/* global saveAs:true */ | ||
/* global saveAs Blob */ | ||
@@ -9,3 +9,3 @@ import {svgAttrs, svgStyles, inheritableAttrs} from './collection'; | ||
// inheritable styles may be overridden by parent, always copy for now | ||
inheritableAttrs.forEach(function(k) { | ||
inheritableAttrs.forEach(function (k) { | ||
if (k in svgStyles) { | ||
@@ -28,3 +28,3 @@ svgStyles[k] = true; | ||
*/ | ||
constructor({ attrs, styles } = {}) { | ||
constructor ({ attrs, styles } = {}) { | ||
this.attrs = (attrs === undefined) ? svgAttrs : attrs; | ||
@@ -41,3 +41,3 @@ this.styles = (styles === undefined) ? svgStyles : styles; | ||
*/ | ||
getHTML(el) { | ||
getHTML (el) { | ||
const svg = cloneSvg(el, this.attrs, this.styles); | ||
@@ -62,3 +62,3 @@ | ||
*/ | ||
getBlob(el) { | ||
getBlob (el) { | ||
const html = this.getHTML(el); | ||
@@ -75,3 +75,3 @@ return new Blob([html], { type: 'text/xml' }); | ||
*/ | ||
getUri(el) { | ||
getUri (el) { | ||
const html = this.getHTML(el); | ||
@@ -92,6 +92,6 @@ if (isDefined(window.btoa)) { | ||
*/ | ||
asSvg(el, filename) { | ||
asSvg (el, filename) { | ||
if (!filename || filename === '') { | ||
filename = el.getAttribute('title'); | ||
filename = (filename || 'untitled')+'.svg'; | ||
filename = (filename || 'untitled') + '.svg'; | ||
} | ||
@@ -113,6 +113,6 @@ if (isDefined(window.saveAs) && isFunction(Blob)) { | ||
*/ | ||
asPng(el, filename) { | ||
asPng (el, filename) { | ||
if (!filename || filename === '') { | ||
filename = el.getAttribute('title'); | ||
filename = (filename || 'untitled')+'.png'; | ||
filename = (filename || 'untitled') + '.png'; | ||
} | ||
@@ -119,0 +119,0 @@ return savePng(this.getUri(el), filename); |
@@ -6,1 +6,11 @@ /* Some simple utilities */ | ||
export const isUndefined = (a) => typeof a === 'undefined'; | ||
export const isObject = (a) => (a !== null && typeof a === 'object'); | ||
export function clone (obj) { | ||
if (obj == null || typeof obj !== 'object') return obj; | ||
var copy = obj.constructor(); | ||
for (var attr in obj) { | ||
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; | ||
} | ||
return copy; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
53061
15
1040
82