UNPKG

svg-protect

Version:

Flatten, optimise, CC Lisence and split paths to prevent Illustrators from changing your work without permission.

1,153 lines (994 loc) 36 kB
//////////////////////////////////// // svg Jimmy //////////////////////////////////// //https://nytimes.github.io/svg-crowbar/ //from plugin module.exports={png:save,svge:savesvgelements,svg:savesvg} function save(name) { var name = name || "untitled"; (function() { var global = global || this; var document = global.document, body = document.body, forEach = Array.prototype.forEach, styles = document.querySelectorAll("style"); forEach.call(document.querySelectorAll("svg"), function(svg) { if (svg.namespaceURI !== "http://www.w3.org/2000/svg") return; // Not really an SVG. if (svg.ownerSVGElement) return; // An SVG within another SVG. forEach.call(styles, function(style) { svg.appendChild(style.cloneNode(true)); }); var canvas = document.createElement("canvas"), context = canvas.getContext("2d"), image = new Image(), ratio = global.devicePixelRatio || 1, width = svg.getAttribute("width") * ratio, height = svg.getAttribute("height") * ratio, url = URL.createObjectURL(new Blob( [new XMLSerializer().serializeToString(svg)], { type: "image/svg+xml" } )); image.onload = function() { context.drawImage(this, 0, 0, width, height); url = URL.revokeObjectURL(url); canvas.toBlob(function(blob) { var a = document.createElement("a"); a.download = name + ".png"; a.href = url = URL.createObjectURL(blob); body.appendChild(a); a.click(); setTimeout( function() { url = URL.revokeObjectURL(url); body.removeChild(a); }, 10 ); }); }; canvas.width = width; canvas.height = height; image.src = url; }); })(); } //////////////////////////////////// // Svg crowbar 2 //////////////////////////////////// function savesvgelements() { (function() { var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; window.URL = window.URL || window.webkitURL; var body = document.body, emptySvg; var prefix = { xmlns: "http://www.w3.org/2000/xmlns/", xlink: "http://www.w3.org/1999/xlink", svg: "http://www.w3.org/2000/svg" }; initialize(); function initialize() { var documents = [window.document], SVGSources = []; iframes = document.querySelectorAll( "iframe" ), objects = document.querySelectorAll("object"); // add empty svg element var emptySvg = window.document.createElementNS(prefix.svg, "svg"); window.document.body.appendChild(emptySvg); var emptySvgDeclarationComputed = getComputedStyle(emptySvg); [].forEach.call(iframes, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); [].forEach.call(objects, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); documents.forEach(function(doc) { var newSources = getSources(doc, emptySvgDeclarationComputed); // because of prototype on NYT pages for (var i = 0; i < newSources.length; i++) { SVGSources.push(newSources[i]); } }); if (SVGSources.length > 1) { createPopover(SVGSources); } else if (SVGSources.length > 0) { download(SVGSources[0]); } else { alert("The Crowbar couldn’t find any SVG nodes."); } } function createPopover(sources) { cleanup(); sources.forEach(function(s1) { sources.forEach(function(s2) { if (s1 !== s2) { if ( Math.abs(s1.top - s2.top) < 38 && Math.abs(s1.left - s2.left) < 38 ) { s2.top += 38; s2.left += 38; } } }); }); var buttonsContainer = document.createElement("div"); body.appendChild(buttonsContainer); buttonsContainer.setAttribute("class", "svg-crowbar"); buttonsContainer.style["z-index"] = 1e7; buttonsContainer.style["position"] = "absolute"; buttonsContainer.style["top"] = 0; buttonsContainer.style["left"] = 0; var background = document.createElement("div"); body.appendChild(background); background.setAttribute("class", "svg-crowbar"); background.style["background"] = "rgba(255, 255, 255, 0.7)"; background.style["position"] = "fixed"; background.style["left"] = 0; background.style["top"] = 0; background.style["width"] = "100%"; background.style["height"] = "100%"; sources.forEach(function(d, i) { var buttonWrapper = document.createElement("div"); buttonsContainer.appendChild(buttonWrapper); buttonWrapper.setAttribute("class", "svg-crowbar"); buttonWrapper.style["position"] = "absolute"; buttonWrapper.style["top"] = d.top + document.body.scrollTop + "px"; buttonWrapper.style["left"] = document.body.scrollLeft + d.left + "px"; buttonWrapper.style["padding"] = "4px"; buttonWrapper.style["border-radius"] = "3px"; buttonWrapper.style["color"] = "white"; buttonWrapper.style["text-align"] = "center"; buttonWrapper.style["font-family"] = "'Helvetica Neue'"; buttonWrapper.style["background"] = "rgba(0, 0, 0, 0.8)"; buttonWrapper.style["box-shadow"] = "0px 4px 18px rgba(0, 0, 0, 0.4)"; buttonWrapper.style["cursor"] = "move"; buttonWrapper.textContent = "SVG #" + i + ": " + (d.id ? "#" + d.id : "") + (d.class ? "." + d.class : ""); var button = document.createElement("button"); buttonWrapper.appendChild(button); button.setAttribute("data-source-id", i); button.style["width"] = "150px"; button.style["font-size"] = "12px"; button.style["line-height"] = "1.4em"; button.style["margin"] = "5px 0 0 0"; button.textContent = "Download"; button.onclick = function(el) { // console.log(el, d, i, sources) download(d); }; }); } function cleanup() { var crowbarElements = document.querySelectorAll(".svg-crowbar"); [].forEach.call(crowbarElements, function(el) { el.parentNode.removeChild(el); }); } function getSources(doc, emptySvgDeclarationComputed) { var svgInfo = [], svgs = doc.querySelectorAll("svg"); [].forEach.call(svgs, function(svg) { svg.setAttribute("version", "1.1"); // removing attributes so they aren't doubled up svg.removeAttribute("xmlns"); svg.removeAttribute("xlink"); // These are needed for the svg if (!svg.hasAttributeNS(prefix.xmlns, "xmlns")) { svg.setAttributeNS(prefix.xmlns, "xmlns", prefix.svg); } if (!svg.hasAttributeNS(prefix.xmlns, "xmlns:xlink")) { svg.setAttributeNS(prefix.xmlns, "xmlns:xlink", prefix.xlink); } setInlineStyles(svg, emptySvgDeclarationComputed); var source = new XMLSerializer().serializeToString(svg); var rect = svg.getBoundingClientRect(); svgInfo.push({ top: rect.top, left: rect.left, width: rect.width, height: rect.height, class: svg.getAttribute("class"), id: svg.getAttribute("id"), childElementCount: svg.childElementCount, source: [doctype + source] }); }); return svgInfo; } function download(source) { var filename = "untitled"; if (source.id) { filename = source.id; } else if (source.class) { filename = source.class; } else if (window.document.title) { filename = window.document.title .replace(/[^a-z0-9]/gi, "-") .toLowerCase(); } var url = window.URL.createObjectURL(new Blob(source.source, { type: "text\/xml" })); var a = document.createElement("a"); body.appendChild(a); a.setAttribute("class", "svg-crowbar"); a.setAttribute("download", filename + ".svg"); a.setAttribute("href", url); a.style["display"] = "none"; a.click(); setTimeout( function() { window.URL.revokeObjectURL(url); }, 10 ); } function setInlineStyles(svg, emptySvgDeclarationComputed) { function explicitlySetStyle(element) { var cSSStyleDeclarationComputed = getComputedStyle(element); var i, len, key, value; var computedStyleStr = ""; for (i = 0, len = cSSStyleDeclarationComputed.length; i < len; i++) { key = cSSStyleDeclarationComputed[i]; value = cSSStyleDeclarationComputed.getPropertyValue(key); if (value !== emptySvgDeclarationComputed.getPropertyValue(key)) { computedStyleStr += key + ":" + value + ";"; } } element.setAttribute("style", computedStyleStr); } function traverse(obj) { var tree = []; tree.push(obj); visit(obj); function visit(node) { if (node && node.hasChildNodes()) { var child = node.firstChild; while (child) { if (child.nodeType === 1 && child.nodeName != "SCRIPT") { tree.push(child); visit(child); } child = child.nextSibling; } } } return tree; } // hardcode computed css styles inside svg var allElements = traverse(svg); var i = allElements.length; while (i--) { explicitlySetStyle(allElements[i]); } } })(); } //////////////////////////////////// // svg crowbar //////////////////////////////////// function savesvg() { (function() { var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; window.URL = window.URL || window.webkitURL; var body = document.body; var prefix = { xmlns: "http://www.w3.org/2000/xmlns/", xlink: "http://www.w3.org/1999/xlink", svg: "http://www.w3.org/2000/svg" }; initialize(); function initialize() { var documents = [window.document], SVGSources = []; iframes = document.querySelectorAll( "iframe" ), objects = document.querySelectorAll("object"); [].forEach.call(iframes, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); [].forEach.call(objects, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); documents.forEach(function(doc) { var styles = getStyles(doc); var newSources = getSources(doc, styles); // because of prototype on NYT pages for (var i = 0; i < newSources.length; i++) { SVGSources.push(newSources[i]); } }); if (SVGSources.length > 1) { createPopover(SVGSources); } else if (SVGSources.length > 0) { download(SVGSources[0]); } else { alert("The Crowbar couldn’t find any SVG nodes."); } } function createPopover(sources) { cleanup(); sources.forEach(function(s1) { sources.forEach(function(s2) { if (s1 !== s2) { if ( Math.abs(s1.top - s2.top) < 38 && Math.abs(s1.left - s2.left) < 38 ) { s2.top += 38; s2.left += 38; } } }); }); var buttonsContainer = document.createElement("div"); body.appendChild(buttonsContainer); buttonsContainer.setAttribute("class", "svg-crowbar"); buttonsContainer.style["z-index"] = 1e7; buttonsContainer.style["position"] = "absolute"; buttonsContainer.style["top"] = 0; buttonsContainer.style["left"] = 0; var background = document.createElement("div"); body.appendChild(background); background.setAttribute("class", "svg-crowbar"); background.style["background"] = "rgba(255, 255, 255, 0.7)"; background.style["position"] = "fixed"; background.style["left"] = 0; background.style["top"] = 0; background.style["width"] = "100%"; background.style["height"] = "100%"; sources.forEach(function(d, i) { var buttonWrapper = document.createElement("div"); buttonsContainer.appendChild(buttonWrapper); buttonWrapper.setAttribute("class", "svg-crowbar"); buttonWrapper.style["position"] = "absolute"; buttonWrapper.style["top"] = d.top + document.body.scrollTop + "px"; buttonWrapper.style["left"] = document.body.scrollLeft + d.left + "px"; buttonWrapper.style["padding"] = "4px"; buttonWrapper.style["border-radius"] = "3px"; buttonWrapper.style["color"] = "white"; buttonWrapper.style["text-align"] = "center"; buttonWrapper.style["font-family"] = "'Helvetica Neue'"; buttonWrapper.style["background"] = "rgba(0, 0, 0, 0.8)"; buttonWrapper.style["box-shadow"] = "0px 4px 18px rgba(0, 0, 0, 0.4)"; buttonWrapper.style["cursor"] = "move"; buttonWrapper.textContent = "SVG #" + i + ": " + (d.id ? "#" + d.id : "") + (d.class ? "." + d.class : ""); var button = document.createElement("button"); buttonWrapper.appendChild(button); button.setAttribute("data-source-id", i); button.style["width"] = "150px"; button.style["font-size"] = "12px"; button.style["line-height"] = "1.4em"; button.style["margin"] = "5px 0 0 0"; button.textContent = "Download"; button.onclick = function(el) { // console.log(el, d, i, sources) download(d); }; }); } function cleanup() { var crowbarElements = document.querySelectorAll(".svg-crowbar"); [].forEach.call(crowbarElements, function(el) { el.parentNode.removeChild(el); }); } function getSources(doc, styles) { var svgInfo = [], svgs = doc.querySelectorAll("svg"); styles = styles === undefined ? "" : styles; [].forEach.call(svgs, function(svg) { svg.setAttribute("version", "1.1"); var defsEl = document.createElement("defs"); svg.insertBefore(defsEl, svg.firstChild); //TODO .insert("defs", ":first-child") // defsEl.setAttribute("class", "svg-crowbar"); var styleEl = document.createElement("style"); defsEl.appendChild(styleEl); styleEl.setAttribute("type", "text/css"); // removing attributes so they aren't doubled up svg.removeAttribute("xmlns"); svg.removeAttribute("xlink"); // These are needed for the svg if (!svg.hasAttributeNS(prefix.xmlns, "xmlns")) { svg.setAttributeNS(prefix.xmlns, "xmlns", prefix.svg); } if (!svg.hasAttributeNS(prefix.xmlns, "xmlns:xlink")) { svg.setAttributeNS(prefix.xmlns, "xmlns:xlink", prefix.xlink); } var source = new XMLSerializer() .serializeToString(svg) .replace("</style>", "<![CDATA[" + styles + "]]></style>"); var rect = svg.getBoundingClientRect(); svgInfo.push({ top: rect.top, left: rect.left, width: rect.width, height: rect.height, class: svg.getAttribute("class"), id: svg.getAttribute("id"), childElementCount: svg.childElementCount, source: [doctype + source] }); }); return svgInfo; } function download(source) { var filename = "untitled"; if (source.id) { filename = source.id; } else if (source.class) { filename = source.class; } else if (window.document.title) { filename = window.document.title .replace(/[^a-z0-9]/gi, "-") .toLowerCase(); } var url = window.URL.createObjectURL(new Blob(source.source, { type: "text\/xml" })); var a = document.createElement("a"); body.appendChild(a); a.setAttribute("class", "svg-crowbar"); a.setAttribute("download", filename + ".svg"); a.setAttribute("href", url); a.style["display"] = "none"; a.click(); setTimeout( function() { window.URL.revokeObjectURL(url); }, 10 ); } function getStyles(doc) { var styles = "", styleSheets = doc.styleSheets; if (styleSheets) { for (var i = 0; i < styleSheets.length; i++) { processStyleSheet(styleSheets[i]); } } function processStyleSheet(ss) { if (ss.cssRules) { for (var i = 0; i < ss.cssRules.length; i++) { var rule = ss.cssRules[i]; if (rule.type === 3) { // Import Rule processStyleSheet(rule.styleSheet); } else { // hack for illustrator crashing on descendent selectors if (rule.selectorText) { if (rule.selectorText.indexOf(">") === -1) { styles += "\n" + rule.cssText; } } } } } } return styles; } })(); } //////////////////////////////////// // svg Jimmy //////////////////////////////////// //https://nytimes.github.io/svg-crowbar/ //from plugin module.exports={png:save,svge:savesvgelements,svg:savesvg} function save(name) { var name = name || "untitled"; (function() { var global = global || this; var document = global.document, body = document.body, forEach = Array.prototype.forEach, styles = document.querySelectorAll("style"); forEach.call(document.querySelectorAll("svg"), function(svg) { if (svg.namespaceURI !== "http://www.w3.org/2000/svg") return; // Not really an SVG. if (svg.ownerSVGElement) return; // An SVG within another SVG. forEach.call(styles, function(style) { svg.appendChild(style.cloneNode(true)); }); var canvas = document.createElement("canvas"), context = canvas.getContext("2d"), image = new Image(), ratio = global.devicePixelRatio || 1, width = svg.getAttribute("width") * ratio, height = svg.getAttribute("height") * ratio, url = URL.createObjectURL(new Blob( [new XMLSerializer().serializeToString(svg)], { type: "image/svg+xml" } )); image.onload = function() { context.drawImage(this, 0, 0, width, height); url = URL.revokeObjectURL(url); canvas.toBlob(function(blob) { var a = document.createElement("a"); a.download = name + ".png"; a.href = url = URL.createObjectURL(blob); body.appendChild(a); a.click(); setTimeout( function() { url = URL.revokeObjectURL(url); body.removeChild(a); }, 10 ); }); }; canvas.width = width; canvas.height = height; image.src = url; }); })(); } //////////////////////////////////// // Svg crowbar 2 //////////////////////////////////// function savesvgelements() { (function() { var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; window.URL = window.URL || window.webkitURL; var body = document.body, emptySvg; var prefix = { xmlns: "http://www.w3.org/2000/xmlns/", xlink: "http://www.w3.org/1999/xlink", svg: "http://www.w3.org/2000/svg" }; initialize(); function initialize() { var documents = [window.document], SVGSources = []; iframes = document.querySelectorAll( "iframe" ), objects = document.querySelectorAll("object"); // add empty svg element var emptySvg = window.document.createElementNS(prefix.svg, "svg"); window.document.body.appendChild(emptySvg); var emptySvgDeclarationComputed = getComputedStyle(emptySvg); [].forEach.call(iframes, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); [].forEach.call(objects, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); documents.forEach(function(doc) { var newSources = getSources(doc, emptySvgDeclarationComputed); // because of prototype on NYT pages for (var i = 0; i < newSources.length; i++) { SVGSources.push(newSources[i]); } }); if (SVGSources.length > 1) { createPopover(SVGSources); } else if (SVGSources.length > 0) { download(SVGSources[0]); } else { alert("The Crowbar couldn’t find any SVG nodes."); } } function createPopover(sources) { cleanup(); sources.forEach(function(s1) { sources.forEach(function(s2) { if (s1 !== s2) { if ( Math.abs(s1.top - s2.top) < 38 && Math.abs(s1.left - s2.left) < 38 ) { s2.top += 38; s2.left += 38; } } }); }); var buttonsContainer = document.createElement("div"); body.appendChild(buttonsContainer); buttonsContainer.setAttribute("class", "svg-crowbar"); buttonsContainer.style["z-index"] = 1e7; buttonsContainer.style["position"] = "absolute"; buttonsContainer.style["top"] = 0; buttonsContainer.style["left"] = 0; var background = document.createElement("div"); body.appendChild(background); background.setAttribute("class", "svg-crowbar"); background.style["background"] = "rgba(255, 255, 255, 0.7)"; background.style["position"] = "fixed"; background.style["left"] = 0; background.style["top"] = 0; background.style["width"] = "100%"; background.style["height"] = "100%"; sources.forEach(function(d, i) { var buttonWrapper = document.createElement("div"); buttonsContainer.appendChild(buttonWrapper); buttonWrapper.setAttribute("class", "svg-crowbar"); buttonWrapper.style["position"] = "absolute"; buttonWrapper.style["top"] = d.top + document.body.scrollTop + "px"; buttonWrapper.style["left"] = document.body.scrollLeft + d.left + "px"; buttonWrapper.style["padding"] = "4px"; buttonWrapper.style["border-radius"] = "3px"; buttonWrapper.style["color"] = "white"; buttonWrapper.style["text-align"] = "center"; buttonWrapper.style["font-family"] = "'Helvetica Neue'"; buttonWrapper.style["background"] = "rgba(0, 0, 0, 0.8)"; buttonWrapper.style["box-shadow"] = "0px 4px 18px rgba(0, 0, 0, 0.4)"; buttonWrapper.style["cursor"] = "move"; buttonWrapper.textContent = "SVG #" + i + ": " + (d.id ? "#" + d.id : "") + (d.class ? "." + d.class : ""); var button = document.createElement("button"); buttonWrapper.appendChild(button); button.setAttribute("data-source-id", i); button.style["width"] = "150px"; button.style["font-size"] = "12px"; button.style["line-height"] = "1.4em"; button.style["margin"] = "5px 0 0 0"; button.textContent = "Download"; button.onclick = function(el) { // console.log(el, d, i, sources) download(d); }; }); } function cleanup() { var crowbarElements = document.querySelectorAll(".svg-crowbar"); [].forEach.call(crowbarElements, function(el) { el.parentNode.removeChild(el); }); } function getSources(doc, emptySvgDeclarationComputed) { var svgInfo = [], svgs = doc.querySelectorAll("svg"); [].forEach.call(svgs, function(svg) { svg.setAttribute("version", "1.1"); // removing attributes so they aren't doubled up svg.removeAttribute("xmlns"); svg.removeAttribute("xlink"); // These are needed for the svg if (!svg.hasAttributeNS(prefix.xmlns, "xmlns")) { svg.setAttributeNS(prefix.xmlns, "xmlns", prefix.svg); } if (!svg.hasAttributeNS(prefix.xmlns, "xmlns:xlink")) { svg.setAttributeNS(prefix.xmlns, "xmlns:xlink", prefix.xlink); } setInlineStyles(svg, emptySvgDeclarationComputed); var source = new XMLSerializer().serializeToString(svg); var rect = svg.getBoundingClientRect(); svgInfo.push({ top: rect.top, left: rect.left, width: rect.width, height: rect.height, class: svg.getAttribute("class"), id: svg.getAttribute("id"), childElementCount: svg.childElementCount, source: [doctype + source] }); }); return svgInfo; } function download(source) { var filename = "untitled"; if (source.id) { filename = source.id; } else if (source.class) { filename = source.class; } else if (window.document.title) { filename = window.document.title .replace(/[^a-z0-9]/gi, "-") .toLowerCase(); } var url = window.URL.createObjectURL(new Blob(source.source, { type: "text\/xml" })); var a = document.createElement("a"); body.appendChild(a); a.setAttribute("class", "svg-crowbar"); a.setAttribute("download", filename + ".svg"); a.setAttribute("href", url); a.style["display"] = "none"; a.click(); setTimeout( function() { window.URL.revokeObjectURL(url); }, 10 ); } function setInlineStyles(svg, emptySvgDeclarationComputed) { function explicitlySetStyle(element) { var cSSStyleDeclarationComputed = getComputedStyle(element); var i, len, key, value; var computedStyleStr = ""; for (i = 0, len = cSSStyleDeclarationComputed.length; i < len; i++) { key = cSSStyleDeclarationComputed[i]; value = cSSStyleDeclarationComputed.getPropertyValue(key); if (value !== emptySvgDeclarationComputed.getPropertyValue(key)) { computedStyleStr += key + ":" + value + ";"; } } element.setAttribute("style", computedStyleStr); } function traverse(obj) { var tree = []; tree.push(obj); visit(obj); function visit(node) { if (node && node.hasChildNodes()) { var child = node.firstChild; while (child) { if (child.nodeType === 1 && child.nodeName != "SCRIPT") { tree.push(child); visit(child); } child = child.nextSibling; } } } return tree; } // hardcode computed css styles inside svg var allElements = traverse(svg); var i = allElements.length; while (i--) { explicitlySetStyle(allElements[i]); } } })(); } //////////////////////////////////// // svg crowbar //////////////////////////////////// function savesvg() { (function() { var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; window.URL = window.URL || window.webkitURL; var body = document.body; var prefix = { xmlns: "http://www.w3.org/2000/xmlns/", xlink: "http://www.w3.org/1999/xlink", svg: "http://www.w3.org/2000/svg" }; initialize(); function initialize() { var documents = [window.document], SVGSources = []; iframes = document.querySelectorAll( "iframe" ), objects = document.querySelectorAll("object"); [].forEach.call(iframes, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); [].forEach.call(objects, function(el) { try { if (el.contentDocument) { documents.push(el.contentDocument); } } catch (err) { console.log(err); } }); documents.forEach(function(doc) { var styles = getStyles(doc); var newSources = getSources(doc, styles); // because of prototype on NYT pages for (var i = 0; i < newSources.length; i++) { SVGSources.push(newSources[i]); } }); if (SVGSources.length > 1) { createPopover(SVGSources); } else if (SVGSources.length > 0) { download(SVGSources[0]); } else { alert("The Crowbar couldn’t find any SVG nodes."); } } function createPopover(sources) { cleanup(); sources.forEach(function(s1) { sources.forEach(function(s2) { if (s1 !== s2) { if ( Math.abs(s1.top - s2.top) < 38 && Math.abs(s1.left - s2.left) < 38 ) { s2.top += 38; s2.left += 38; } } }); }); var buttonsContainer = document.createElement("div"); body.appendChild(buttonsContainer); buttonsContainer.setAttribute("class", "svg-crowbar"); buttonsContainer.style["z-index"] = 1e7; buttonsContainer.style["position"] = "absolute"; buttonsContainer.style["top"] = 0; buttonsContainer.style["left"] = 0; var background = document.createElement("div"); body.appendChild(background); background.setAttribute("class", "svg-crowbar"); background.style["background"] = "rgba(255, 255, 255, 0.7)"; background.style["position"] = "fixed"; background.style["left"] = 0; background.style["top"] = 0; background.style["width"] = "100%"; background.style["height"] = "100%"; sources.forEach(function(d, i) { var buttonWrapper = document.createElement("div"); buttonsContainer.appendChild(buttonWrapper); buttonWrapper.setAttribute("class", "svg-crowbar"); buttonWrapper.style["position"] = "absolute"; buttonWrapper.style["top"] = d.top + document.body.scrollTop + "px"; buttonWrapper.style["left"] = document.body.scrollLeft + d.left + "px"; buttonWrapper.style["padding"] = "4px"; buttonWrapper.style["border-radius"] = "3px"; buttonWrapper.style["color"] = "white"; buttonWrapper.style["text-align"] = "center"; buttonWrapper.style["font-family"] = "'Helvetica Neue'"; buttonWrapper.style["background"] = "rgba(0, 0, 0, 0.8)"; buttonWrapper.style["box-shadow"] = "0px 4px 18px rgba(0, 0, 0, 0.4)"; buttonWrapper.style["cursor"] = "move"; buttonWrapper.textContent = "SVG #" + i + ": " + (d.id ? "#" + d.id : "") + (d.class ? "." + d.class : ""); var button = document.createElement("button"); buttonWrapper.appendChild(button); button.setAttribute("data-source-id", i); button.style["width"] = "150px"; button.style["font-size"] = "12px"; button.style["line-height"] = "1.4em"; button.style["margin"] = "5px 0 0 0"; button.textContent = "Download"; button.onclick = function(el) { // console.log(el, d, i, sources) download(d); }; }); } function cleanup() { var crowbarElements = document.querySelectorAll(".svg-crowbar"); [].forEach.call(crowbarElements, function(el) { el.parentNode.removeChild(el); }); } function getSources(doc, styles) { var svgInfo = [], svgs = doc.querySelectorAll("svg"); styles = styles === undefined ? "" : styles; [].forEach.call(svgs, function(svg) { svg.setAttribute("version", "1.1"); var defsEl = document.createElement("defs"); svg.insertBefore(defsEl, svg.firstChild); //TODO .insert("defs", ":first-child") // defsEl.setAttribute("class", "svg-crowbar"); var styleEl = document.createElement("style"); defsEl.appendChild(styleEl); styleEl.setAttribute("type", "text/css"); // removing attributes so they aren't doubled up svg.removeAttribute("xmlns"); svg.removeAttribute("xlink"); // These are needed for the svg if (!svg.hasAttributeNS(prefix.xmlns, "xmlns")) { svg.setAttributeNS(prefix.xmlns, "xmlns", prefix.svg); } if (!svg.hasAttributeNS(prefix.xmlns, "xmlns:xlink")) { svg.setAttributeNS(prefix.xmlns, "xmlns:xlink", prefix.xlink); } var source = new XMLSerializer() .serializeToString(svg) .replace("</style>", "<![CDATA[" + styles + "]]></style>"); var rect = svg.getBoundingClientRect(); svgInfo.push({ top: rect.top, left: rect.left, width: rect.width, height: rect.height, class: svg.getAttribute("class"), id: svg.getAttribute("id"), childElementCount: svg.childElementCount, source: [doctype + source] }); }); return svgInfo; } function download(source) { var filename = "untitled"; if (source.id) { filename = source.id; } else if (source.class) { filename = source.class; } else if (window.document.title) { filename = window.document.title .replace(/[^a-z0-9]/gi, "-") .toLowerCase(); } var url = window.URL.createObjectURL(new Blob(source.source, { type: "text\/xml" })); var a = document.createElement("a"); body.appendChild(a); a.setAttribute("class", "svg-crowbar"); a.setAttribute("download", filename + ".svg"); a.setAttribute("href", url); a.style["display"] = "none"; a.click(); setTimeout( function() { window.URL.revokeObjectURL(url); }, 10 ); } function getStyles(doc) { var styles = "", styleSheets = doc.styleSheets; if (styleSheets) { for (var i = 0; i < styleSheets.length; i++) { processStyleSheet(styleSheets[i]); } } function processStyleSheet(ss) { if (ss.cssRules) { for (var i = 0; i < ss.cssRules.length; i++) { var rule = ss.cssRules[i]; if (rule.type === 3) { // Import Rule processStyleSheet(rule.styleSheet); } else { // hack for illustrator crashing on descendent selectors if (rule.selectorText) { if (rule.selectorText.indexOf(">") === -1) { styles += "\n" + rule.cssText; } } } } } } return styles; } })(); }