Skip to content

Instantly share code, notes, and snippets.

@zazaulola
Created September 14, 2021 09:21
Show Gist options
  • Save zazaulola/d924cc7f057dc89d2e72d65f7f39a17e to your computer and use it in GitHub Desktop.
Save zazaulola/d924cc7f057dc89d2e72d65f7f39a17e to your computer and use it in GitHub Desktop.
Simple HTML-string beautifier (works in browser)
function beautify(
/* HTML-string */ html,
/* new line chars */ nl = '\n',
/* indent chars */ tab = '\t',
/* disabled format tags */ disabled = /^(code|pre|em|strong|span|b|i|u|sup|sub|a)$/ig,
/* without closed tags */ single = /^(area|base|br|col|command|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/gi
){
return escape(
stringify(
new DOMParser() /* parse HTML */
.parseFromString(html,'text/html')
.documentElement /* <root> element */
)
);
function stringify(el,depth=0){
const name = el.tagName.toLowerCase();
const indent = nl+''.padEnd(depth,'x').replace(/x/g,tab);
const attrNames = el.getAttributeNames();
const attrs = attrNames.map(n=>`${n}="${el.getAttribute(n)}"`).join(' ');
let output = indent+(attrs.length ? `<${name} ${attrs}>` : `<${name}>`);
if(el.childNodes.length){
let prevDisabled=false;
for(let node of el.childNodes){
if(node.nodeType == 1){
if(disabled.test(node.tagName)){
output += node.outerHTML;
prevDisabled = true;
} else {
output += stringify(node,depth+1);
prevDisabled = false;
}
}
else if([3,4,7,8].includes(node.nodeType)){
if(!prevDisabled)
output += indent+tab;
output += node.nodeValue.split(/\n\s*/g).join(indent+tab);
prevDisabled = false;
}
}
output += indent+`</${name}>`;
}
else if(!single.test(name))
output+=`</${name}>`;
return output;
}
function escape(text){ return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
}
// test on current page
document.write('<pre style="tab-size:2;">'+beautify(document.documentElement.innerHTML)+'</pre>');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment