Categories
interview

HTMLElement to Virtual DOM and back

/**
 * @param {HTMLElement} 
 * @return {object} object literal presentation
 */
function virtualize(element) {
  // Check if textNode.
  if (element.nodeType === 3) {
    return element.textContent;
  }

  const obj = {
    type: element.tagName.toLowerCase(),
    props: {},
  };

  const children = [];
  for(const node of element.childNodes) {
      children.push(virtualize(node));
  }

  for(const attribute of element.attributes) {
    obj.props[attribute.name === 'class' ? 'className' : attribute.name] = attribute.value; 
  }

  obj.props.children = children.length === 1 ? children[0] : children;

  return obj;
}


/**
 * @param {object} valid object literal presentation
 * @return {HTMLElement} 
 */
function render(obj) {
  if(typeof obj === 'string') {
    return document.createTextNode(obj);
  }

  let {type, props: {children, ...attributes}} = obj;
  const ret = document.createElement(type);

  children = typeof children === 'string'? [children]: children;

  for(const node of children) {
    ret.append(render(node));
  }

  for(const [key, value] of Object.entries(attributes)) {
      ret.setAttribute(key === 'className' ? 'class' : key, value);
  }

  return ret;
}