Skip to content

Instantly share code, notes, and snippets.

@dpashkevich
Created November 6, 2012 11:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dpashkevich/4024183 to your computer and use it in GitHub Desktop.
Save dpashkevich/4024183 to your computer and use it in GitHub Desktop.
DOM tree to Pre converter
/**
* 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
// output attributes
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 if it's on new line
}
} 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');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment