/** * See https://github.com/sellside/pre */ /** * References/todos: * http://www.lemoda.net/javascript/dump-dom/dump-dom.html * http://www.howtocreate.co.uk/tutorials/javascript/dombasics * Use treewalker or nodefilter?? * https://developer.mozilla.org/en-US/docs/DOM/NodeFilter * https://developer.mozilla.org/en-US/docs/DOM/treeWalker */ function toPre(el) { "use strict"; var s = '', tagName, classes, id, tabChar = ' ', tabWidth = 2, attrs, attrName, wsRe = /^\s+$/, selector, slice = Array.prototype.slice; (function traverse(el, depth) { depth = depth || 0; var childNodes, indent = Array(depth * tabWidth + 1).join(tabChar), nextIndent = indent + Array(tabWidth + 1).join(tabChar), nodeValue, isEmpty = true; switch(el.nodeType) { case 1: // ELEMENT_NODE classes = slice.call(el.classList).join('.'); id = el.id; tagName = el.tagName.toLowerCase(); // omit 'div' tag name is classes and/or id present if(tagName === 'div' && (classes || id)) { tagName = ''; } selector = tagName + (id ? ('#' + id) : '') + (classes ? ('.' + classes) : ''); break; case 3: // TEXT_NODE nodeValue = el.nodeValue; if(wsRe.test(nodeValue)) { // filter whitespace-only text nodes return; } selector = 'text'; break; case 8: // COMMENT_NODE nodeValue = el.nodeValue; selector = 'comment'; break; default: // skip other kinds of nodes... return; } // selector + opening brace s += indent + selector +' {'; if(el.nodeType === 1) { // ELEMENT_NODE if(el.hasAttributes()) { isEmpty = false; // body not empty attrs = el.attributes; s += '\n'; for(var i = 0, len = attrs.length; i < len; i++) { // normalize attr name attrName = attrs[i].name.replace(/:/g, '-').toLowerCase(); // skip 'id' and 'class' attributes (they are present in the selector) if(attrName !== 'id' && attrName !== 'class') { s += nextIndent + attrName + ': "' + attrs[i].nodeValue + '";\n'; } } } // output child nodes if(el.hasChildNodes()) { isEmpty = false; s += '\n'; childNodes = el.childNodes; for(var i = 0, len = childNodes.length; i < len; i++) { traverse(childNodes[i], depth + 1); } } if(!isEmpty) { s += indent; // add indentation before the closing bracket } } else { // Comment or text nodes... // just put the value directly inside the body if(nodeValue.indexOf('\n') > -1) { // multiline - surround value with newlines nodeValue = '\n' + nodeValue + '\n' + indent; } s += nodeValue; } // closing brace s += '}\n'; })(el); return s; } //console.log(toPre(document.documentElement)); // For executing directly from the console: copy(toPre(document.documentElement)); console.log('Markup copied to clipboard');