Created
July 19, 2018 07:14
-
-
Save andreasvirkus/39848323272332988f90c77412e9f20a to your computer and use it in GitHub Desktop.
Get the whole DOM of an element with its styles (defaults excluded) inlined.
This file contains hidden or 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
/** | |
* Usage: | |
* | |
* document.getElementById('app').serializeWithStyles() | |
* | |
* Credits go to https://stackoverflow.com/a/6310120/2803743 | |
*/ | |
Element.prototype.serializeWithStyles = (function () { | |
// Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result. | |
var defaultStylesByTagName = {}; | |
// Styles inherited from style sheets will not be rendered for elements with these tag names | |
var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true}; | |
// This list determines which css default values lookup tables are precomputed at load time | |
// Lookup tables for other tag names will be automatically built at runtime if needed | |
var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"]; | |
// Precompute the lookup tables. | |
for (var i = 0; i < tagNames.length; i++) { | |
if(!noStyleTags[tagNames[i]]) { | |
defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]); | |
} | |
} | |
function computeDefaultStyleByTagName(tagName) { | |
var defaultStyle = {}; | |
var element = document.body.appendChild(document.createElement(tagName)); | |
var computedStyle = getComputedStyle(element); | |
for (var i = 0; i < computedStyle.length; i++) { | |
defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]]; | |
} | |
document.body.removeChild(element); | |
return defaultStyle; | |
} | |
function getDefaultStyleByTagName(tagName) { | |
tagName = tagName.toUpperCase(); | |
if (!defaultStylesByTagName[tagName]) { | |
defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName); | |
} | |
return defaultStylesByTagName[tagName]; | |
} | |
return function serializeWithStyles() { | |
if (this.nodeType !== Node.ELEMENT_NODE) { throw new TypeError(); } | |
var cssTexts = []; | |
var elements = this.querySelectorAll("*"); | |
for ( var i = 0; i < elements.length; i++ ) { | |
var e = elements[i]; | |
if (!noStyleTags[e.tagName]) { | |
var computedStyle = getComputedStyle(e); | |
var defaultStyle = getDefaultStyleByTagName(e.tagName); | |
cssTexts[i] = e.style.cssText; | |
for (var ii = 0; ii < computedStyle.length; ii++) { | |
var cssPropName = computedStyle[ii]; | |
if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) { | |
e.style[cssPropName] = computedStyle[cssPropName]; | |
} | |
} | |
} | |
} | |
var result = this.outerHTML; | |
for ( var i = 0; i < elements.length; i++ ) { | |
elements[i].style.cssText = cssTexts[i]; | |
} | |
return result; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment