Comparing version 0.1.9 to 0.2.0
233
browser.js
@@ -20,2 +20,126 @@ (function (global, factory) { | ||
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 { | ||
var uri = canvas.toDataURL('image/png'); | ||
saveUri(uri, name); | ||
} | ||
}; | ||
image.src = uri; | ||
return true; | ||
} | ||
function getComputedStyles(node) { | ||
if (isDefined(node.currentStyle)) { | ||
return node.currentStyle; | ||
} else if (isDefined(window.getComputedStyle)) { | ||
return node.ownerDocument.defaultView.getComputedStyle(node, null); | ||
} else { | ||
return node.style; | ||
} | ||
} | ||
function convertComputedStyle(computed) { | ||
if (isDefined(window.getComputedStyle)) { | ||
var styles = {}; | ||
for (var i = 0, l = computed.length; i < l; i++) { | ||
var prop = computed[i]; | ||
var val = computed.getPropertyValue(prop); | ||
styles[prop] = val; | ||
} | ||
return styles; | ||
} | ||
return computed; | ||
} | ||
function copyStyles(source, target, defaultStyles) { | ||
if (defaultStyles === false) { | ||
return; | ||
} | ||
var srcStyles = getComputedStyles(source); | ||
if (defaultStyles === true) { | ||
for (var key in convertComputedStyle(srcStyles)) { | ||
target.style[key] = srcStyles[key]; | ||
} | ||
return; | ||
} | ||
var parStyles = getComputedStyles(target.parentNode); | ||
for (var key in defaultStyles) { | ||
var src = srcStyles[key]; | ||
if (src && src !== defaultStyles[key] && src !== parStyles[key]) { | ||
target.style[key] = src; | ||
} | ||
} | ||
} | ||
function cleanAttrs(el, attrs, styles) { | ||
if (attrs === true) { | ||
return; | ||
} | ||
Array.prototype.slice.call(el.attributes).forEach(function (attr) { | ||
if (attr.specified) { | ||
if (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('*'); | ||
Array.prototype.slice.call(clonedSvg.querySelectorAll('*')).forEach(function (target, index) { | ||
copyStyles(srcChildren[index], target, styles); | ||
cleanAttrs(target, attrs, styles); | ||
}); | ||
return clonedSvg; | ||
} | ||
var svgStyles = { | ||
@@ -88,81 +212,16 @@ 'alignment-baseline': 'auto', | ||
function isUndefined(value) { | ||
return typeof value === 'undefined'; | ||
} | ||
function isDefined(value) { | ||
return typeof value !== 'undefined'; | ||
} | ||
function isFunction(value) { | ||
return typeof value === 'function'; | ||
} | ||
var forEach = Array.prototype.forEach; | ||
var SvgSaver = (function () { | ||
function SvgSaver() { | ||
var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
function getStyles(node, name) { | ||
var val; | ||
_classCallCheck(this, SvgSaver); | ||
if (isDefined(node.currentStyle)) { | ||
val = node.currentStyle[name]; | ||
} else if (isDefined(window.getComputedStyle)) { | ||
val = node.ownerDocument.defaultView.getComputedStyle(node, null)[name]; | ||
} else { | ||
val = node.style[name]; | ||
this.attrs = opts.attrs === undefined ? svgAttrs : opts.attrs; | ||
this.styles = opts.styles === undefined ? svgStyles : opts.styles; | ||
} | ||
return val === '' ? undefined : val; | ||
} | ||
function copyStyles(source, target) { | ||
for (var key in svgStyles) { | ||
var _default = svgStyles[key]; | ||
var src = getStyles(source, key); | ||
var par = getStyles(target.parentNode, key); | ||
if (src && src !== _default && src !== par) { | ||
target.style[key] = src; | ||
} | ||
} | ||
} | ||
function cleanAttrs(el) { | ||
forEach.call(el.attributes, function (attr) { | ||
if (attr.specified && isUndefined(svgStyles[attr.name]) && svgAttrs.indexOf(attr.name) < 0) { | ||
el.removeAttribute(attr.name); | ||
} | ||
}); | ||
} | ||
function cloneSvg(src) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
forEach.call(clonedSvg.querySelectorAll('*'), function (target, index) { | ||
copyStyles(srcChildren[index], target); | ||
cleanAttrs(target); | ||
}); | ||
return clonedSvg; | ||
} | ||
var DownloadAttributeSupport = ('download' in document.createElement('a')); | ||
function saveUri(url, name) { | ||
if (DownloadAttributeSupport) { | ||
var dl = document.createElement('a'); | ||
dl.setAttribute('href', url); | ||
dl.setAttribute('download', name); | ||
dl.click(); | ||
} else { | ||
window.open(url, '_blank', ''); | ||
} | ||
return true; | ||
} | ||
var SvgSaver = (function () { | ||
function SvgSaver(opts) { | ||
_classCallCheck(this, SvgSaver); | ||
} | ||
_createClass(SvgSaver, [{ | ||
key: 'getHTML', | ||
value: function getHTML(el) { | ||
var svg = cloneSvg(el); | ||
var svg = cloneSvg(el, this.attrs, this.styles); | ||
@@ -190,3 +249,3 @@ svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); | ||
} | ||
return "data:image/svg+xml," + encodeURIComponent(html); | ||
return 'data:image/svg+xml,' + encodeURIComponent(html); | ||
} | ||
@@ -200,9 +259,7 @@ }, { | ||
} | ||
if (isDefined(window.saveAs) && isFunction(Blob)) { | ||
saveAs(this.getBlob(el), filename); | ||
return saveAs(this.getBlob(el), filename); | ||
} else { | ||
saveUri(this.getUri(el), filename); | ||
return saveUri(this.getUri(el), filename); | ||
} | ||
return this; | ||
} | ||
@@ -216,23 +273,3 @@ }, { | ||
} | ||
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, filename); | ||
}); | ||
} else { | ||
var uri = canvas.toDataURL('image/png'); | ||
saveUri(uri, filename); | ||
} | ||
}; | ||
image.src = this.getUri(el); | ||
return true; | ||
return savePng(this.getUri(el), filename); | ||
} | ||
@@ -239,0 +276,0 @@ }]); |
@@ -1,2 +0,1 @@ | ||
(function(global,factory){if(typeof define==="function"&&define.amd){define("SvgSaver",["exports","module"],factory)}else if(typeof exports!=="undefined"&&typeof module!=="undefined"){factory(exports,module)}else{var mod={exports:{}};factory(mod.exports,mod);global.SvgSaver=mod.exports}})(this,function(exports,module){"use strict";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"];function isUndefined(value){return typeof value==="undefined"}function isDefined(value){return typeof value!=="undefined"}function isFunction(value){return typeof value==="function"}var forEach=Array.prototype.forEach;function getStyles(node,name){var val;if(isDefined(node.currentStyle)){val=node.currentStyle[name]}else if(isDefined(window.getComputedStyle)){val=node.ownerDocument.defaultView.getComputedStyle(node,null)[name]}else{val=node.style[name]}return val===""?undefined:val}function copyStyles(source,target){for(var key in svgStyles){var _default=svgStyles[key];var src=getStyles(source,key);var par=getStyles(target.parentNode,key);if(src&&src!==_default&&src!==par){target.style[key]=src}}}function cleanAttrs(el){forEach.call(el.attributes,function(attr){if(attr.specified&&isUndefined(svgStyles[attr.name])&&svgAttrs.indexOf(attr.name)<0){el.removeAttribute(attr.name)}})}function cloneSvg(src){var clonedSvg=src.cloneNode(true);var srcChildren=src.querySelectorAll("*");forEach.call(clonedSvg.querySelectorAll("*"),function(target,index){copyStyles(srcChildren[index],target);cleanAttrs(target)});return clonedSvg}var DownloadAttributeSupport="download"in document.createElement("a");function saveUri(url,name){if(DownloadAttributeSupport){var dl=document.createElement("a");dl.setAttribute("href",url);dl.setAttribute("download",name);dl.click()}else{window.open(url,"_blank","")}return true}var SvgSaver=function(){function SvgSaver(opts){_classCallCheck(this,SvgSaver)}_createClass(SvgSaver,[{key:"getHTML",value:function getHTML(el){var svg=cloneSvg(el);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)){saveAs(this.getBlob(el),filename)}else{saveUri(this.getUri(el),filename)}return this}},{key:"asPng",value:function asPng(el,filename){if(!filename||filename===""){filename=el.getAttribute("title");filename=(filename||"untitled")+".png"}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,filename)})}else{var uri=canvas.toDataURL("image/png");saveUri(uri,filename)}};image.src=this.getUri(el);return true}}]);return SvgSaver}();module.exports=SvgSaver}); | ||
//# sourceMappingURL=browser.min.js.map | ||
(function(global,factory){if(typeof define==="function"&&define.amd){define("SvgSaver",["exports","module"],factory)}else if(typeof exports!=="undefined"&&typeof module!=="undefined"){factory(exports,module)}else{var mod={exports:{}};factory(mod.exports,mod);global.SvgSaver=mod.exports}})(this,function(exports,module){"use strict";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 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{var uri=canvas.toDataURL("image/png");saveUri(uri,name)}};image.src=uri;return true}function getComputedStyles(node){if(isDefined(node.currentStyle)){return node.currentStyle}else if(isDefined(window.getComputedStyle)){return node.ownerDocument.defaultView.getComputedStyle(node,null)}else{return node.style}}function convertComputedStyle(computed){if(isDefined(window.getComputedStyle)){var styles={};for(var i=0,l=computed.length;i<l;i++){var prop=computed[i];var val=computed.getPropertyValue(prop);styles[prop]=val}return styles}return computed}function copyStyles(source,target,defaultStyles){if(defaultStyles===false){return}var srcStyles=getComputedStyles(source);if(defaultStyles===true){for(var key in convertComputedStyle(srcStyles)){target.style[key]=srcStyles[key]}return}var parStyles=getComputedStyles(target.parentNode);for(var key in defaultStyles){var src=srcStyles[key];if(src&&src!==defaultStyles[key]&&src!==parStyles[key]){target.style[key]=src}}}function cleanAttrs(el,attrs,styles){if(attrs===true){return}Array.prototype.slice.call(el.attributes).forEach(function(attr){if(attr.specified){if(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("*");Array.prototype.slice.call(clonedSvg.querySelectorAll("*")).forEach(function(target,index){copyStyles(srcChildren[index],target,styles);cleanAttrs(target,attrs,styles)});return clonedSvg}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 SvgSaver=function(){function SvgSaver(){var opts=arguments.length<=0||arguments[0]===undefined?{}:arguments[0];_classCallCheck(this,SvgSaver);this.attrs=opts.attrs===undefined?svgAttrs:opts.attrs;this.styles=opts.styles===undefined?svgStyles:opts.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}();module.exports=SvgSaver}); |
@@ -0,1 +1,3 @@ | ||
/* Some simple utilities */ | ||
'use strict'; | ||
@@ -11,35 +13,105 @@ | ||
var _collection = require('./collection'); | ||
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'; | ||
}; | ||
function isUndefined(value) { | ||
return typeof value === 'undefined'; | ||
//detection | ||
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 isDefined(value) { | ||
return typeof value !== 'undefined'; | ||
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 { | ||
var uri = canvas.toDataURL('image/png'); | ||
saveUri(uri, name); | ||
} | ||
}; | ||
image.src = uri; | ||
return true; | ||
} | ||
function isFunction(value) { | ||
return typeof value === 'function'; | ||
} | ||
var forEach = Array.prototype.forEach; | ||
function getStyles(node, name) { | ||
var val; | ||
// Gets computed styles for an SVG element | ||
// adapted from https://github.com/angular/angular.js/issues/2866#issuecomment-31012434 | ||
function getComputedStyles(node) { | ||
if (isDefined(node.currentStyle)) { | ||
val = node.currentStyle[name]; | ||
//for old IE | ||
return node.currentStyle; | ||
} else if (isDefined(window.getComputedStyle)) { | ||
val = node.ownerDocument.defaultView.getComputedStyle(node, null)[name]; | ||
//for modern browsers | ||
return node.ownerDocument.defaultView.getComputedStyle(node, null); | ||
} else { | ||
val = node.style[name]; | ||
return node.style; | ||
} | ||
return val === '' ? undefined : val; | ||
} | ||
function copyStyles(source, target) { | ||
for (var key in _collection.svgStyles) { | ||
var _default = _collection.svgStyles[key]; | ||
var src = getStyles(source, key); | ||
// Vonvert computed styles to something we can iterate over | ||
// adapted from http://stackoverflow.com/questions/754607/can-jquery-get-all-css-styles-associated-with-an-element/6416527#6416527 | ||
function convertComputedStyle(computed) { | ||
if (isDefined(window.getComputedStyle)) { | ||
var styles = {}; | ||
for (var i = 0, l = computed.length; i < l; i++) { | ||
var prop = computed[i]; | ||
var val = computed.getPropertyValue(prop); | ||
styles[prop] = val; | ||
} | ||
return styles; | ||
} | ||
return computed; | ||
} | ||
var par = getStyles(target.parentNode, key); | ||
if (src && src !== _default && src !== par) { | ||
// Copies computed styles from source to target | ||
function copyStyles(source, target, defaultStyles) { | ||
// styles === false - copy none, true - copy all | ||
if (defaultStyles === false) { | ||
return; | ||
} | ||
var srcStyles = getComputedStyles(source); | ||
if (defaultStyles === true) { | ||
// copy all styles | ||
for (var key in convertComputedStyle(srcStyles)) { | ||
target.style[key] = srcStyles[key]; | ||
} | ||
return; | ||
} | ||
var parStyles = getComputedStyles(target.parentNode); | ||
for (var key in defaultStyles) { | ||
var src = srcStyles[key]; | ||
if (src && src !== defaultStyles[key] && src !== parStyles[key]) { | ||
target.style[key] = src; | ||
@@ -50,6 +122,16 @@ } | ||
function cleanAttrs(el) { | ||
forEach.call(el.attributes, function (attr) { | ||
if (attr.specified && isUndefined(_collection.svgStyles[attr.name]) && _collection.svgAttrs.indexOf(attr.name) < 0) { | ||
el.removeAttribute(attr.name); | ||
// Removes attributes that are not valid for SVGs | ||
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) { | ||
// remove if it is not style nor on attrs whitelist | ||
// keeping attributes that are also styles because attributes override | ||
if (attr.specified) { | ||
if (attrs === false || isUndefined(styles[attr.name]) && attrs.indexOf(attr.name) < 0) { | ||
el.removeAttribute(attr.name); | ||
} | ||
} | ||
@@ -59,9 +141,10 @@ }); | ||
function cloneSvg(src) { | ||
// Clones an SVGElement, copyies approprate atttributes and styles. | ||
function cloneSvg(src, attrs, styles) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
forEach.call(clonedSvg.querySelectorAll('*'), function (target, index) { | ||
copyStyles(srcChildren[index], target); | ||
cleanAttrs(target); | ||
Array.prototype.slice.call(clonedSvg.querySelectorAll('*')).forEach(function (target, index) { | ||
copyStyles(srcChildren[index], target, styles); | ||
cleanAttrs(target, attrs, styles); | ||
}); | ||
@@ -72,25 +155,110 @@ | ||
var DownloadAttributeSupport = ('download' in document.createElement('a')); | ||
var 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' | ||
}; | ||
function saveUri(url, name) { | ||
if (DownloadAttributeSupport) { | ||
var dl = document.createElement('a'); | ||
dl.setAttribute('href', url); | ||
dl.setAttribute('download', name); | ||
dl.click(); | ||
} else { | ||
window.open(url, '_blank', ''); | ||
} | ||
return true; | ||
} | ||
var svgAttrs = [// white list of attributes | ||
'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', 'maskUnits', 'transform', 'viewBox', 'version', // Container | ||
'preserveAspectRatio', 'xmlns', 'points', // Polygons | ||
'offset']; | ||
var SvgSaver = (function () { | ||
function SvgSaver(opts) { | ||
/** | ||
* SvgSaver constructor. | ||
* @constructs SvgSaver | ||
* @api public | ||
* | ||
* @example | ||
* var svgsaver = new SvgSaver(); // creates a new instance | ||
* var svg = document.querySelector('#mysvg'); // find the SVG element | ||
* svgsaver.asSvg(svg); // save as SVG | ||
*/ | ||
function SvgSaver() { | ||
var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
_classCallCheck(this, SvgSaver); | ||
this.attrs = opts.attrs === undefined ? svgAttrs : opts.attrs; | ||
this.styles = opts.styles === undefined ? svgStyles : opts.styles; | ||
} | ||
/** | ||
* Return the SVG HTML text after cleaning | ||
* | ||
* @param {SVGElement} el The element to copy. | ||
* @returns {String} SVG text after cleaning | ||
* @api public | ||
*/ | ||
_createClass(SvgSaver, [{ | ||
key: 'getHTML', | ||
value: function getHTML(el) { | ||
var svg = cloneSvg(el); | ||
var svg = cloneSvg(el, this.attrs, this.styles); | ||
@@ -100,2 +268,3 @@ svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); | ||
// height and width needed to download in FireFox | ||
svg.setAttribute('width', svg.getAttribute('width') || '500'); | ||
@@ -106,2 +275,10 @@ svg.setAttribute('height', svg.getAttribute('height') || '900'); | ||
} | ||
/** | ||
* Return the SVG, after cleaning, as a text/xml Blob | ||
* | ||
* @param {SVGElement} el The element to copy. | ||
* @returns {Blog} SVG as a text/xml Blob | ||
* @api public | ||
*/ | ||
}, { | ||
@@ -113,2 +290,10 @@ key: 'getBlob', | ||
} | ||
/** | ||
* Return the SVG, after cleaning, as a image/svg+xml;base64 URI encoded string | ||
* | ||
* @param {SVGElement} el The element to copy. | ||
* @returns {String} SVG as image/svg+xml;base64 URI encoded string | ||
* @api public | ||
*/ | ||
}, { | ||
@@ -121,4 +306,13 @@ key: 'getUri', | ||
} | ||
return "data:image/svg+xml," + encodeURIComponent(html); | ||
return 'data:image/svg+xml,' + encodeURIComponent(html); | ||
} | ||
/** | ||
* Saves the SVG as a SVG file using method compatible with the browser | ||
* | ||
* @param {SVGElement} el The element to copy. | ||
* @param {string} [filename] The filename to save, defaults to the SVG title or 'untitled.svg' | ||
* @returns {SvgSaver} The SvgSaver instance | ||
* @api public | ||
*/ | ||
}, { | ||
@@ -131,10 +325,17 @@ key: 'asSvg', | ||
} | ||
if (isDefined(window.saveAs) && isFunction(Blob)) { | ||
saveAs(this.getBlob(el), filename); | ||
return saveAs(this.getBlob(el), filename); | ||
} else { | ||
saveUri(this.getUri(el), filename); | ||
return saveUri(this.getUri(el), filename); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Saves the SVG as a PNG file using method compatible with the browser | ||
* | ||
* @param {SVGElement} el The element to copy. | ||
* @param {string} [filename] The filename to save, defaults to the SVG title or 'untitled.png' | ||
* @returns {SvgSaver} The SvgSaver instance | ||
* @api public | ||
*/ | ||
}, { | ||
@@ -147,23 +348,3 @@ key: 'asPng', | ||
} | ||
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, filename); | ||
}); | ||
} else { | ||
var uri = canvas.toDataURL('image/png'); | ||
saveUri(uri, filename); | ||
} | ||
}; | ||
image.src = this.getUri(el); | ||
return true; | ||
return savePng(this.getUri(el), filename); | ||
} | ||
@@ -175,4 +356,3 @@ }]); | ||
exports.SvgSaver = SvgSaver; | ||
exports['default'] = SvgSaver; | ||
//# sourceMappingURL=svgsaver.js.map | ||
module.exports = exports['default']; |
@@ -0,1 +1,3 @@ | ||
The MIT License (MIT) | ||
Copyright © 2015 Jayson Harshbarger | ||
@@ -2,0 +4,0 @@ |
{ | ||
"name": "svgsaver", | ||
"version": "0.1.9", | ||
"version": "0.2.0", | ||
"description": "download an SVG element with css styles", | ||
@@ -11,12 +11,12 @@ "main": "index.js", | ||
"scripts": { | ||
"babel": "babel ./src/ -d lib/ --no-comments --source-maps", | ||
"roll": "rollup index.es6.js | babel -m umd -o browser.js --module-id SvgSaver --no-comments", | ||
"uglify": "uglifyjs browser.js -o browser.min.js --source-map browser.min.js.map", | ||
"roll:cjs": "rollup ./src/index.js | babel -o ./lib/svgsaver.js", | ||
"roll:umd": "rollup ./src/index.js | babel -m umd -o browser.js --module-id SvgSaver --no-comments", | ||
"uglify": "uglifyjs browser.js -o browser.min.js", | ||
"test": "npm run build && karma start", | ||
"build": "npm run babel && npm run roll && npm run uglify", | ||
"lint": "eslint src/index.js", | ||
"build": "npm run roll:cjs && npm run roll:umd && npm run uglify && npm run jsdoc2md", | ||
"lint": "eslint src/*.js", | ||
"watch": "watch \"npm run build\" src/", | ||
"demo": "live-server --open=demo --ignore=src", | ||
"start": "npm run demo & npm run watch", | ||
"jsdoc2md": "jsdoc-parse ./src/svgsaver.js | dmd > api.md" | ||
"jsdoc2md": "jsdoc-parse ./src/svgsaver.js | dmd > API.md" | ||
}, | ||
@@ -31,4 +31,6 @@ "keywords": [ | ||
"babel": "^5.8.23", | ||
"dmd": "^1.2.0", | ||
"eslint": "^1.4.3", | ||
"jasmine-core": "^2.3.4", | ||
"jsdoc-parse": "^1.1.0", | ||
"karma": "^0.13.9", | ||
@@ -44,5 +46,3 @@ "karma-chrome-launcher": "^0.2.0", | ||
"uglifyjs": "^2.4.10", | ||
"watch": "^0.16.0", | ||
"jsdoc-parse": "^1.1.0", | ||
"dmd": "^1.2.0" | ||
"watch": "^0.16.0" | ||
}, | ||
@@ -49,0 +49,0 @@ "dependencies": {}, |
svgsaver | ||
=== | ||
download an svg element as an SVG or PNG file, including CSS defined styles. | ||
download an SVG element as an SVG or PNG file, including CSS defined styles. | ||
## Features | ||
- Download `<svg>` by element object or css selectors. | ||
- Download `<svg>` by element object or CSS selectors. | ||
- Copies SVG element styles as rendered in the browser, including styles defined in CSS stylesheets. | ||
@@ -26,5 +26,7 @@ - Copies only SVG relevant and non-default styles. [See here](http://www.w3.org/TR/SVG/propidx.html). | ||
- http://bl.ocks.org/Hypercubed/db9e99d761f90d87cf43 | ||
- http://bl.ocks.org/Hypercubed/58fff7215e53d6565f32 | ||
- http://codepen.io/Hypercubed/pen/OyWadQ | ||
- [Epicyclic Gearing](http://bl.ocks.org/Hypercubed/db9e99d761f90d87cf43) - d3 | ||
- [Superformula Explorer](http://bl.ocks.org/Hypercubed/58fff7215e53d6565f32) - d3 | ||
- [City Construction Site](http://codepen.io/Hypercubed/pen/OyWadQ) - jQuery and TweenMax | ||
- [City Construction Site](http://codepen.io/Hypercubed/pen/OyWadQ) - jQuery and TweenMax | ||
- [Chiasm Boilerplate (with download buttons)](http://bl.ocks.org/Hypercubed/b01a767b41b0e679aade) - Chiasm | ||
@@ -31,0 +33,0 @@ ## Acknowledgments |
@@ -0,71 +1,8 @@ | ||
/* global saveAs:true */ | ||
import {svgAttrs, svgStyles} from './collection'; | ||
import {cloneSvg} from './clonesvg'; | ||
import {saveUri, savePng} from './saveuri'; | ||
import {isDefined, isFunction} from './utils'; | ||
function isUndefined(value) {return typeof value === 'undefined';} | ||
function isDefined(value) {return typeof value !== 'undefined';} | ||
function isFunction(value) {return typeof value === 'function';} | ||
var forEach = Array.prototype.forEach; | ||
// adapted from https://github.com/angular/angular.js/issues/2866#issuecomment-31012434 | ||
function getStyles(node, name) { | ||
var val; | ||
if (isDefined(node.currentStyle)) { //for old IE | ||
val = node.currentStyle[name]; | ||
} else if (isDefined(window.getComputedStyle)){ //for modern browsers | ||
val = node.ownerDocument.defaultView.getComputedStyle(node,null)[name]; | ||
} else { | ||
val = node.style[name]; | ||
} | ||
return (val === '') ? undefined : val; | ||
} | ||
function copyStyles(source, target) { | ||
for (var key in svgStyles) { | ||
var _default = svgStyles[key]; | ||
var src = getStyles(source,key); | ||
//var tgt = getStyles(target,key); | ||
var par = getStyles(target.parentNode,key); | ||
if (src && src !== _default /* && src !== tgt */ && src !== par ) { | ||
target.style[key] = src; | ||
} | ||
} | ||
} | ||
function cleanAttrs(el) { | ||
forEach.call(el.attributes, function(attr) { | ||
// remove if it is not style nor on whitelist | ||
// keeping attributes that are also styles because some styles are not copied | ||
if(attr.specified && isUndefined(svgStyles[attr.name]) && svgAttrs.indexOf(attr.name) < 0) { | ||
el.removeAttribute(attr.name); | ||
} | ||
}); | ||
} | ||
function cloneSvg(src) { | ||
var clonedSvg = src.cloneNode(true); | ||
var srcChildren = src.querySelectorAll('*'); | ||
forEach.call(clonedSvg.querySelectorAll('*'), function( target, index ){ | ||
copyStyles(srcChildren[index], target); | ||
cleanAttrs(target); | ||
}); | ||
return clonedSvg; | ||
} | ||
//detection | ||
var DownloadAttributeSupport = 'download' in document.createElement('a'); | ||
function saveUri(url, name){ | ||
if (DownloadAttributeSupport) { | ||
var dl = document.createElement('a'); | ||
dl.setAttribute('href', url); | ||
dl.setAttribute('download', name); | ||
dl.click(); | ||
} else { | ||
window.open(url, '_blank', ''); | ||
} | ||
return true; | ||
} | ||
export class SvgSaver { | ||
@@ -83,4 +20,5 @@ | ||
*/ | ||
constructor(opts) { | ||
// todo: options | ||
constructor(opts = {}) { | ||
this.attrs = (opts.attrs === undefined) ? svgAttrs : opts.attrs; | ||
this.styles = (opts.styles === undefined) ? svgStyles : opts.styles; | ||
} | ||
@@ -96,3 +34,3 @@ | ||
getHTML(el) { | ||
var svg = cloneSvg(el); | ||
var svg = cloneSvg(el, this.attrs, this.styles); | ||
@@ -133,3 +71,3 @@ svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); | ||
} | ||
return "data:image/svg+xml," + encodeURIComponent(html); | ||
return 'data:image/svg+xml,' + encodeURIComponent(html); | ||
} | ||
@@ -150,10 +88,7 @@ | ||
} | ||
if (isDefined(window.saveAs) && isFunction(Blob)) { | ||
saveAs(this.getBlob(el), filename); | ||
return saveAs(this.getBlob(el), filename); | ||
} else { | ||
saveUri(this.getUri(el), filename); | ||
return saveUri(this.getUri(el), filename); | ||
} | ||
return this; | ||
} | ||
@@ -174,24 +109,3 @@ | ||
} | ||
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, filename); | ||
}); | ||
} else { | ||
var uri = canvas.toDataURL('image/png'); | ||
saveUri(uri, filename); | ||
} | ||
}; | ||
image.src = this.getUri(el); | ||
return true; | ||
return savePng(this.getUri(el), filename); | ||
} | ||
@@ -198,0 +112,0 @@ |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
849
37
40659
13
1