undom + preact headless active rendering

by amindunited

HTML

<script src="https://npmcdn.com/undom@latest"></script>
<script src="https://npmcdn.com/preact"></script>
<h2>HTML Serialization</h2>
<pre id="html"></pre>

<h2>JSON Serialization</h2>
<pre id="json"></pre>

CSS

pre {
	tab-size: 2;
}

Babel + JSX

/** @jsx preact.h */


// set up _global_ mock document:
var document = undom();
window.document.createElement = document.createElement;
window.document.createTextNode = document.createTextNode;
window.Text = document.Text;
window.Element = document.Element;

console.log('window', window);

// DEMO: active rendering of preact components into an undom document:
/* class Demo extends preact.Component {
  state = { time:Date.now() };
  componentDidMount() {
    setInterval(() => this.setState({ time:Date.now() }), 1000);
  }
  render({ }, { time }) {
    return <div class="clock">{new Date(time).toTimeString()}</div>;
  }
}
preact.render(<Demo />, document.body);



// every half second, show the current document tree:
setInterval( () => {
  console.log(document.body);
  window.document.getElementById('html').textContent = serializeHtml(document.body);
  window.document.getElementById('json').textContent = JSON.stringify(serializeJson(document.body), null, '  ');
}, 500);




// serialize tree to pretty html
function serializeHtml(el) {
    if (el.nodeType===3) return el.nodeValue;
    var name = String(el.nodeName).toLowerCase(),
        str = '<'+name,
        hits = {},
        c, i;
    for (i=0; i<el.attributes.length; i++) {
      hits[el.attributes[i].name] = true;
      str += ' '+el.attributes[i].name+'="'+el.attributes[i].value+'"';
    }
    if (el.className && !hits.class) str += ' class="'+el.className+'"';
    str += '>';
    for (i=0; i<el.childNodes.length; i++) {
        c = serializeHtml(el.childNodes[i]);
        if (c) str += '\n\t'+c.replace(/\n/g,'\n\t');
    }
    return str + (c?'\n':'') + '</'+name+'>';
}

function enc(s) {
    return s.replace(/[&'"<>]/g, function(a){ return `&#${a};` });
}


// serialize tree to json (objects)
function serializeJson(el) {
    if (el.nodeType===3) return el.nodeValue;
    var attributes = {},
      a = el.attributes;
    if (el.className) attributes.class = el.className;
    for (let i=0; i<a.length; i++)...