'use strict';

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const constants = require('./constants.cjs');

// const voidElements = {
//   img: true,
//   image: true,
// };
// const elementTokenizer =
//   /(?:<([a-z][a-z0-9-:]*)( [^<>'"\n=\s]+=(['"])[^>'"\n]*\3)*\s*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|([^&<>]+))/gi;
// const attributeTokenizer = / ([^<>'"\n=\s]+)=(['"])([^>'"\n]*)\2/g;

const elementTokenizer = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^&<>]+))/gi;
const attributeTokenizer = /\s([^<>'"=\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
function parseHtml(html, contextNode) {
  const document = contextNode.ownerDocument;
  const root = document.createDocumentFragment();
  const stack = [root];
  let parent = root;
  let token;
  elementTokenizer.lastIndex = 0;
  while (token = elementTokenizer.exec(html)) {
    const tag = token[1];
    if (tag) {
      const node = document.createElement(tag);
      const attrs = token[2];
      attributeTokenizer.lastIndex = 0;
      let t;
      while (t = attributeTokenizer.exec(attrs)) {
        node.setAttribute(t[1], t[3] || t[4] || '');
      }
      parent.append(node);
      // if (voidElements[tag] === true) continue;
      stack.push(parent);
      parent = node;
    } else if (token[5]) {
      parent = stack.pop() || root;
    } else if (token[6]) {
      parent.append(document.createComment(token[6]));
    } else {
      parent.append(token[7]);
    }
  }
  return root;
}
function serializeChildren(parentNode) {
  let out = '';
  let child = parentNode[constants.CHILD];
  while (child) {
    out += serializeNode(child);
    child = child[constants.NEXT];
  }
  return out;
}
function serializeNode(node) {
  switch (node.nodeType) {
    case constants.NodeType.ELEMENT_NODE:
      {
        const el = node;
        let out = `<${el[constants.NAME]}`;
        let attr = el[constants.ATTRIBUTES]?.[constants.CHILD];
        while (attr) {
          out += ` ${attr[constants.NAME]}`;
          let value = attr[constants.VALUE];
          if (value !== '') {
            value = String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
            out += `="${value}"`;
          }
          attr = attr[constants.NEXT];
        }
        out += '>';
        out += serializeChildren(el);
        // let child = el[CHILD];
        // while (child) {
        //   out += serialize(child);
        //   child = child[NEXT];
        // }
        out += `</${el[constants.NAME]}>`;
        return out;
      }
    case constants.NodeType.TEXT_NODE:
      {
        const text = node;
        return text[constants.DATA].replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      }
    case constants.NodeType.COMMENT_NODE:
      {
        const text = node;
        return `<!--${text[constants.DATA]}-->`;
      }
  }
  return '';
}

exports.parseHtml = parseHtml;
exports.serializeChildren = serializeChildren;
exports.serializeNode = serializeNode;
