JSFiddle - React, Tailwind, and code Playground

by Alex

HTML

<button>Добавить элемент</button>
<pre></pre>
<div id="root"></div>

CSS

body {
  margin: 0;
  font: 16px 'Segoe UI', Arial, Helvetica, sans-serif;
}

#root {
  margin: 20px;
  padding: 10px;
  box-shadow: 0 0 0 5px #333333;
}

#root:empty {
  display: none;
}

p {
  margin: 0;
  margin-bottom: 5px;
}

pre {
  max-height: 240x;
  margin: 0;
  padding: 10px 20px;
  font: 12px Consolas, sans-serif;
  background: #222222;
  color: #ffffff;
  tab-size: 4;
  overflow: auto;
}

pre:empty {
  display: none;
}

button {
  margin: 20px;
  padding: 10px 20px;
  font: inherit;  
}

JavaScript

const root = document.querySelector('#root');
const output = document.querySelector('pre');
const button = document.querySelector('button');

const serializeNode = node => [
  node.tagName.toLowerCase(),
  node.id ? `#${node.id}` : null,
  [...node.classList].join('.')
].filter(entry => entry).join('');

const observer = new MutationObserver((mutations, observer) => {
  const data = mutations.map(entry => ({
    __time: new Date(),
    type: entry.type,
    target: serializeNode(entry.target),
    addedNodes: [...entry.addedNodes].map(entry => serializeNode(entry)),
    removedNodes: [...entry.removedNodes].map(entry => serializeNode(entry))
  }));

  output.textContent = JSON.stringify(data.length > 1 ? data : data[0], null, '\t');
});

observer.observe(root, {
  childList: true,
  attributes: false,
  subtree: false
});

button.addEventListener('click', event => {
  event.preventDefault();
  
  const element = document.createElement('p');
  element.textContent = Math.random().toString(36).slice(2);
  
  root.append(element);
});