Last active
January 5, 2021 21:10
-
-
Save rxhanson/d43a457f1c3370f96f842edb2af64fe5 to your computer and use it in GitHub Desktop.
This is pulled from https://nytimes.github.io/svg-crowbar/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// working one pulled from https://github.com/nytimes/svg-crowbar/issues/31#issuecomment-421054505 | |
// Changing that to ss.hasOwnProperty('cssRules') fixed the issue for me. | |
!function(){var t='<?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 e,n,o=document.body,l={xmlns:"http://www.w3.org/2000/xmlns/",xlink:"http://www.w3.org/1999/xlink",svg:"http://www.w3.org/2000/svg"};function s(t){var e="untitled";t.id?e=t.id:t.class?e=t.class:window.document.title&&(e=window.document.title.replace(/[^a-z0-9]/gi,"-").toLowerCase());var n=window.URL.createObjectURL(new Blob(t.source,{type:"text/xml"})),l=document.createElement("a");o.appendChild(l),l.setAttribute("class","svg-crowbar"),l.setAttribute("download",e+".svg"),l.setAttribute("href",n),l.style.display="none",l.click(),setTimeout(function(){window.URL.revokeObjectURL(n)},10)}e=[window.document],n=[],iframes=document.querySelectorAll("iframe"),objects=document.querySelectorAll("object"),[].forEach.call(iframes,function(t){try{t.contentDocument&&e.push(t.contentDocument)}catch(t){console.log(t)}}),[].forEach.call(objects,function(t){try{t.contentDocument&&e.push(t.contentDocument)}catch(t){console.log(t)}}),e.forEach(function(e){for(var o,s,r,i=function(t){var e="",n=t.styleSheets;if(n)for(var o=0;o<n.length;o++)l(n[o]);function l(t){if(t.hasOwnProperty("cssRules"))for(var n=0;n<t.cssRules.length;n++){var o=t.cssRules[n];3===o.type?l(o.styleSheet):o.selectorText&&-1===o.selectorText.indexOf(">")&&(e+="\n"+o.cssText)}}return e}(e),c=(o=i,s=[],r=e.querySelectorAll("svg"),o=void 0===o?"":o,[].forEach.call(r,function(e){e.setAttribute("version","1.1");var n=document.createElement("defs");e.insertBefore(n,e.firstChild);var r=document.createElement("style");n.appendChild(r),r.setAttribute("type","text/css"),e.removeAttribute("xmlns"),e.removeAttribute("xlink"),e.hasAttributeNS(l.xmlns,"xmlns")||e.setAttributeNS(l.xmlns,"xmlns",l.svg),e.hasAttributeNS(l.xmlns,"xmlns:xlink")||e.setAttributeNS(l.xmlns,"xmlns:xlink",l.xlink);var i=(new XMLSerializer).serializeToString(e).replace("</style>","<![CDATA["+o+"]]></style>"),c=e.getBoundingClientRect();s.push({top:c.top,left:c.left,width:c.width,height:c.height,class:e.getAttribute("class"),id:e.getAttribute("id"),childElementCount:e.childElementCount,source:[t+i]})}),s),a=0;a<c.length;a++)n.push(c[a])}),n.length>1?function(t){var e;e=document.querySelectorAll(".svg-crowbar"),[].forEach.call(e,function(t){t.parentNode.removeChild(t)}),t.forEach(function(e){t.forEach(function(t){e!==t&&Math.abs(e.top-t.top)<38&&Math.abs(e.left-t.left)<38&&(t.top+=38,t.left+=38)})});var n=document.createElement("div");o.appendChild(n),n.setAttribute("class","svg-crowbar"),n.style["z-index"]=1e7,n.style.position="absolute",n.style.top=0,n.style.left=0;var l=document.createElement("div");o.appendChild(l),l.setAttribute("class","svg-crowbar"),l.style.background="rgba(255, 255, 255, 0.7)",l.style.position="fixed",l.style.left=0,l.style.top=0,l.style.width="100%",l.style.height="100%",t.forEach(function(t,e){var o=document.createElement("div");n.appendChild(o),o.setAttribute("class","svg-crowbar"),o.style.position="absolute",o.style.top=t.top+document.body.scrollTop+"px",o.style.left=document.body.scrollLeft+t.left+"px",o.style.padding="4px",o.style["border-radius"]="3px",o.style.color="white",o.style["text-align"]="center",o.style["font-family"]="'Helvetica Neue'",o.style.background="rgba(0, 0, 0, 0.8)",o.style["box-shadow"]="0px 4px 18px rgba(0, 0, 0, 0.4)",o.style.cursor="move",o.textContent="SVG #"+e+": "+(t.id?"#"+t.id:"")+(t.class?"."+t.class:"");var l=document.createElement("button");o.appendChild(l),l.setAttribute("data-source-id",e),l.style.width="150px",l.style["font-size"]="12px",l.style["line-height"]="1.4em",l.style.margin="5px 0 0 0",l.textContent="Download",l.onclick=function(e){s(t)}})}(n):n.length>0?s(n[0]):alert("The Crowbar couldn’t find any SVG nodes.")}(); | |
// original | |
(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; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment