Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svgsaver

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svgsaver - npm Package Compare versions

Comparing version 0.1.9 to 0.2.0

src/clonesvg.js

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 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc