text: 'use strict';
  
  Object.defineProperty(exports, '__esModule', { value: true });
  
  const hydrateAppFileName = 'test-hydrate.js';
  const hydrateAppPackageName = 'web-component-stencil-test/hydrate';
  const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require;
  const vm = requireFunc('vm');
  function createHydrateAppSandbox(win) {
      const appScript = loadHydrateAppScript();
      const sandbox = createSandbox(win);
      const context = vm.createContext(sandbox);
      appScript.runInContext(context);
      return sandbox.StencilHydrateApp;
  }
  let cachedAppScript = null;
  function loadHydrateAppScript() {
      if (cachedAppScript == null) {
          const fs = requireFunc('fs');
          const path = requireFunc('path');
          let hydrateAppFilePath;
          let hydrateAppCode;
          try {
              hydrateAppFilePath = path.join(__dirname, hydrateAppFileName);
              hydrateAppCode = fs.readFileSync(hydrateAppFilePath, 'utf8');
          }
          catch (e) {
              const hydrateAppPackageIndex = requireFunc.resolve(hydrateAppPackageName);
              const hydrateAppPackageDir = path.dirname(hydrateAppPackageIndex);
              hydrateAppFilePath = path.join(hydrateAppPackageDir, hydrateAppFileName);
              hydrateAppCode = fs.readFileSync(hydrateAppFilePath, 'utf8');
          }
          const code = `StencilHydrateApp = (exports => {${hydrateAppCode};return exports; })({});`;
          cachedAppScript = new vm.Script(code, { filename: hydrateAppFilePath });
      }
      return cachedAppScript;
  }
  function createSandbox(win) {
      const sandbox = {
          __filename: __filename,
          __dirname: __dirname,
          Buffer: Buffer,
          exports: exports,
          fetch: win.fetch,
          global: global,
          module: module,
          process: process,
          require: requireFunc,
          window: win
      };
      WINDOW_PROPS.forEach(prop => {
          if (typeof win[prop] === 'function') {
              sandbox[prop] = win[prop].bind(win);
          }
          else {
              Object.defineProperty(sandbox, prop, {
                  get() { return win[prop]; },
                  set(val) { win[prop] = val; },
                  configurable: true,
                  enumerable: true
              });
          }
      });
      win.__clearInterval = clearInterval.bind(win);
      win.__clearTimeout = clearTimeout.bind(win);
      win.__setInterval = setInterval.bind(win);
      win.__setTimeout = setTimeout.bind(win);
      return sandbox;
  }
  const WINDOW_PROPS = [
      'addEventListener',
      'alert',
      'cancelAnimationFrame',
      'cancelIdleCallback',
      'clearInterval',
      'clearTimeout',
      'close',
      'confirm',
      'console',
      'CSS',
      'CustomEvent',
      'customElements',
      'devicePixelRatio',
      'dispatchEvent',
      'Event',
      'document',
      'getComputedStyle',
      'globalThis',
      'history',
      'HTMLElement',
      'innerHeight',
      'innerWidth',
      'localStorage',
      'location',
      'matchMedia',
      'navigator',
      'pageXOffset',
      'pageYOffset',
      'parent',
      'performance',
      'prompt',
      'origin',
      'removeEventListener',
      'requestAnimationFrame',
      'requestIdleCallback',
      'screen',
      'screenLeft',
      'screenTop',
      'screenX',
      'screenY',
      'scrollX',
      'scrollY',
      'self',
      'sessionStorage',
      'setInterval',
      'setTimeout',
      'top',
      'URL'
  ];
  
  function relocateMetaCharset(doc) {
      const head = doc.head;
      let charsetElm = head.querySelector('meta[charset]');
      if (charsetElm == null) {
          charsetElm = doc.createElement('meta');
          charsetElm.setAttribute('charset', 'utf-8');
      }
      else {
          charsetElm.remove();
      }
      head.insertBefore(charsetElm, head.firstChild);
  }
  
  const commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g;
  function parseCss(css, filePath) {
      var lineno = 1;
      var column = 1;
      var srcLines;
      function updatePosition(str) {
          const lines = str.match(/\n/g);
          if (lines)
              lineno += lines.length;
          const i = str.lastIndexOf('\n');
          column = ~i ? str.length - i : column + str.length;
      }
      function position() {
          const start = { line: lineno, column: column };
          return function (node) {
              node.position = new ParsePosition(start);
              whitespace();
              return node;
          };
      }
      class ParsePosition {
          constructor(start) {
              this.start = start;
              this.end = { line: lineno, column: column };
              this.source = filePath;
          }
      }
      ParsePosition.prototype.content = css;
      const diagnostics = [];
      function error(msg) {
          if (!srcLines) {
              srcLines = css.split('\n');
          }
          const d = {
              level: 'error',
              type: 'css',
              language: 'css',
              header: 'CSS Parse',
              messageText: msg,
              absFilePath: filePath,
              lines: [{
                      lineIndex: lineno - 1,
                      lineNumber: lineno,
                      errorCharStart: column,
                      text: css[lineno - 1],
                  }]
          };
          if (lineno > 1) {
              const previousLine = {
                  lineIndex: lineno - 1,
                  lineNumber: lineno - 1,
                  text: css[lineno - 2],
                  errorCharStart: -1,
                  errorLength: -1
              };
              d.lines.unshift(previousLine);
          }
          if (lineno + 2 < srcLines.length) {
              const nextLine = {
                  lineIndex: lineno,
                  lineNumber: lineno + 1,
                  text: srcLines[lineno],
                  errorCharStart: -1,
                  errorLength: -1
              };
              d.lines.push(nextLine);
          }
          diagnostics.push(d);
      }
      function stylesheet() {
          const rulesList = rules();
          return {
              type: 'stylesheet',
              stylesheet: {
                  source: filePath,
                  rules: rulesList,
                  diagnostics: diagnostics
              }
          };
      }
      function open() {
          return match(/^{\s*/);
      }
      function close() {
          return match(/^}/);
      }
      function rules() {
          var node;
          const rules = [];
          whitespace();
          comments(rules);
          while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) {
              if (node !== false) {
                  rules.push(node);
                  comments(rules);
              }
          }
          return rules;
      }
      function match(re) {
          const m = re.exec(css);
          if (!m)
              return;
          const str = m[0];
          updatePosition(str);
          css = css.slice(str.length);
          return m;
      }
      function whitespace() {
          match(/^\s*/);
      }
      function comments(rules) {
          var c;
          rules = rules || [];
          while (c = comment()) {
              if (c !== false) {
                  rules.push(c);
              }
          }
          return rules;
      }
      function comment() {
          const pos = position();
          if ('/' !== css.charAt(0) || '*' !== css.charAt(1))
              return;
          var i = 2;
          while ('' !== css.charAt(i) && ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1)))
              ++i;
          i += 2;
          if ('' === css.charAt(i - 1)) {
              return error('End of comment missing');
          }
          const str = css.slice(2, i - 2);
          column += 2;
          updatePosition(str);
          css = css.slice(i);
          column += 2;
          return pos({
              type: 'comment',
              comment: str
          });
      }
      function selector() {
          const m = match(/^([^{]+)/);
          if (!m)
              return;
          return trim(m[0])
              .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '')
              .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (m) {
              return m.replace(/,/g, '\u200C');
          })
              .split(/\s*(?![^(]*\)),\s*/)
              .map(function (s) {
              return s.replace(/\u200C/g, ',');
          });
      }
      function declaration() {
          const pos = position();
          var prop = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
          if (!prop)
              return;
          prop = trim(prop[0]);
          if (!match(/^:\s*/))
              return error(`property missing ':'`);
          const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/);
          const ret = pos({
              type: 'declaration',
              property: prop.replace(commentre, ''),
              value: val ? trim(val[0]).replace(commentre, '') : ''
          });
          match(/^[;\s]*/);
          return ret;
      }
      function declarations() {
          const decls = [];
          if (!open())
              return error(`missing '{'`);
          comments(decls);
          var decl;
          while (decl = declaration()) {
              if (decl !== false) {
                  decls.push(decl);
                  comments(decls);
              }
          }
          if (!close())
              return error(`missing '}'`);
          return decls;
      }
      function keyframe() {
          var m;
          const vals = [];
          const pos = position();
          while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) {
              vals.push(m[1]);
              match(/^,\s*/);
          }
          if (!vals.length)
              return;
          return pos({
              type: 'keyframe',
              values: vals,
              declarations: declarations()
          });
      }
      function atkeyframes() {
          const pos = position();
          var m = match(/^@([-\w]+)?keyframes\s*/);
          if (!m)
              return;
          const vendor = m[1];
          m = match(/^([-\w]+)\s*/);
          if (!m)
              return error(`@keyframes missing name`);
          const name = m[1];
          if (!open())
              return error(`@keyframes missing '{'`);
          var frame;
          var frames = comments();
          while (frame = keyframe()) {
              frames.push(frame);
              frames = frames.concat(comments());
          }
          if (!close())
              return error(`@keyframes missing '}'`);
          return pos({
              type: 'keyframes',
              name: name,
              vendor: vendor,
              keyframes: frames
          });
      }
      function atsupports() {
          const pos = position();
          const m = match(/^@supports *([^{]+)/);
          if (!m)
              return;
          const supports = trim(m[1]);
          if (!open())
              return error(`@supports missing '{'`);
          const style = comments().concat(rules());
          if (!close())
              return error(`@supports missing '}'`);
          return pos({
              type: 'supports',
              supports: supports,
              rules: style
          });
      }
      function athost() {
          const pos = position();
          const m = match(/^@host\s*/);
          if (!m)
              return;
          if (!open())
              return error(`@host missing '{'`);
          const style = comments().concat(rules());
          if (!close())
              return error(`@host missing '}'`);
          return pos({
              type: 'host',
              rules: style
          });
      }
      function atmedia() {
          const pos = position();
          const m = match(/^@media *([^{]+)/);
          if (!m)
              return;
          const media = trim(m[1]);
          if (!open())
              return error(`@media missing '{'`);
          const style = comments().concat(rules());
          if (!close())
              return error(`@media missing '}'`);
          return pos({
              type: 'media',
              media: media,
              rules: style
          });
      }
      function atcustommedia() {
          const pos = position();
          const m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/);
          if (!m)
              return;
          return pos({
              type: 'custom-media',
              name: trim(m[1]),
              media: trim(m[2])
          });
      }
      function atpage() {
          const pos = position();
          const m = match(/^@page */);
          if (!m)
              return;
          const sel = selector() || [];
          if (!open())
              return error(`@page missing '{'`);
          var decls = comments();
          var decl;
          while (decl = declaration()) {
              decls.push(decl);
              decls = decls.concat(comments());
          }
          if (!close())
              return error(`@page missing '}'`);
          return pos({
              type: 'page',
              selectors: sel,
              declarations: decls
          });
      }
      function atdocument() {
          const pos = position();
          const m = match(/^@([-\w]+)?document *([^{]+)/);
          if (!m)
              return;
          const vendor = trim(m[1]);
          const doc = trim(m[2]);
          if (!open())
              return error(`@document missing '{'`);
          const style = comments().concat(rules());
          if (!close())
              return error(`@document missing '}'`);
          return pos({
              type: 'document',
              document: doc,
              vendor: vendor,
              rules: style
          });
      }
      function atfontface() {
          const pos = position();
          const m = match(/^@font-face\s*/);
          if (!m)
              return;
          if (!open())
              return error(`@font-face missing '{'`);
          var decls = comments();
          var decl;
          while (decl = declaration()) {
              decls.push(decl);
              decls = decls.concat(comments());
          }
          if (!close())
              return error(`@font-face missing '}'`);
          return pos({
              type: 'font-face',
              declarations: decls
          });
      }
      const atimport = _compileAtrule('import');
      const atcharset = _compileAtrule('charset');
      const atnamespace = _compileAtrule('namespace');
      function _compileAtrule(name) {
          const re = new RegExp('^@' + name + '\\s*([^;]+);');
          return function () {
              const pos = position();
              const m = match(re);
              if (!m)
                  return;
              const ret = { type: name };
              ret[name] = m[1].trim();
              return pos(ret);
          };
      }
      function atrule() {
          if (css[0] !== '@')
              return;
          return atkeyframes()
              || atmedia()
              || atcustommedia()
              || atsupports()
              || atimport()
              || atcharset()
              || atnamespace()
              || atdocument()
              || atpage()
              || athost()
              || atfontface();
      }
      function rule() {
          const pos = position();
          const sel = selector();
          if (!sel)
              return error('selector missing');
          comments();
          return pos({
              type: 'rule',
              selectors: sel,
              declarations: declarations()
          });
      }
      return addParent(stylesheet());
  }
  function trim(str) {
      return str ? str.trim() : '';
  }
  function addParent(obj, parent) {
      const isNode = obj && typeof obj.type === 'string';
      const childParent = isNode ? obj : parent;
      for (const k in obj) {
          const value = obj[k];
          if (Array.isArray(value)) {
              value.forEach(function (v) { addParent(v, childParent); });
          }
          else if (value && typeof value === 'object') {
              addParent(value, childParent);
          }
      }
      if (isNode) {
          Object.defineProperty(obj, 'parent', {
              configurable: true,
              writable: true,
              enumerable: false,
              value: parent || null
          });
      }
      return obj;
  }
  
  function getSelectors(sel) {
      SELECTORS.all.length = SELECTORS.tags.length = SELECTORS.classNames.length = SELECTORS.ids.length = SELECTORS.attrs.length = 0;
      sel = sel.replace(/\./g, ' .')
          .replace(/\#/g, ' #')
          .replace(/\[/g, ' [')
          .replace(/\>/g, ' > ')
          .replace(/\+/g, ' + ')
          .replace(/\~/g, ' ~ ')
          .replace(/\*/g, ' * ')
          .replace(/\:not\((.*?)\)/g, ' ');
      const items = sel.split(' ');
      for (var i = 0; i < items.length; i++) {
          items[i] = items[i].split(':')[0];
          if (items[i].length === 0)
              continue;
          if (items[i].charAt(0) === '.') {
              SELECTORS.classNames.push(items[i].substr(1));
          }
          else if (items[i].charAt(0) === '#') {
              SELECTORS.ids.push(items[i].substr(1));
          }
          else if (items[i].charAt(0) === '[') {
              items[i] = items[i].substr(1).split('=')[0].split(']')[0].trim();
              SELECTORS.attrs.push(items[i].toLowerCase());
          }
          else if (/[a-z]/g.test(items[i].charAt(0))) {
              SELECTORS.tags.push(items[i].toLowerCase());
          }
      }
      SELECTORS.classNames = SELECTORS.classNames.sort((a, b) => {
          if (a.length < b.length)
              return -1;
          if (a.length > b.length)
              return 1;
          return 0;
      });
      return SELECTORS;
  }
  const SELECTORS = {
      all: [],
      tags: [],
      classNames: [],
      ids: [],
      attrs: []
  };
  
  class StringifyCss {
      constructor(usedSelectors) {
          this.usedSelectors = usedSelectors;
          this.hasUsedAttrs = usedSelectors.attrs.size > 0;
          this.hasUsedClassNames = usedSelectors.classNames.size > 0;
          this.hasUsedIds = usedSelectors.ids.size > 0;
          this.hasUsedTags = usedSelectors.tags.size > 0;
      }
      visit(node) {
          return this[node.type](node);
      }
      mapVisit(nodes, delim) {
          let buf = '';
          delim = delim || '';
          for (let i = 0, length = nodes.length; i < length; i++) {
              buf += this.visit(nodes[i]);
              if (delim && i < length - 1)
                  buf += delim;
          }
          return buf;
      }
      compile(node) {
          return node.stylesheet
              .rules.map(this.visit, this)
              .join('');
      }
      comment() {
          return '';
      }
      import(node) {
          return '@import ' + node.import + ';';
      }
      media(node) {
          const mediaCss = this.mapVisit(node.rules);
          if (mediaCss === '') {
              return '';
          }
          return '@media ' + node.media + '{' + this.mapVisit(node.rules) + '}';
      }
      document(node) {
          const documentCss = this.mapVisit(node.rules);
          if (documentCss === '') {
              return '';
          }
          const doc = '@' + (node.vendor || '') + 'document ' + node.document;
          return doc + '{' + documentCss + '}';
      }
      charset(node) {
          return '@charset ' + node.charset + ';';
      }
      namespace(node) {
          return '@namespace ' + node.namespace + ';';
      }
      supports(node) {
          const supportsCss = this.mapVisit(node.rules);
          if (supportsCss === '') {
              return '';
          }
          return '@supports ' + node.supports + '{' + supportsCss + '}';
      }
      keyframes(node) {
          const keyframesCss = this.mapVisit(node.keyframes);
          if (keyframesCss === '') {
              return '';
          }
          return '@' + (node.vendor || '') + 'keyframes ' + node.name + '{' + keyframesCss + '}';
      }
      keyframe(node) {
          const decls = node.declarations;
          return node.values.join(',') + '{' + this.mapVisit(decls) + '}';
      }
      page(node) {
          const sel = node.selectors.length
              ? node.selectors.join(', ')
              : '';
          return '@page ' + sel + '{' + this.mapVisit(node.declarations) + '}';
      }
      ['font-face'](node) {
          const fontCss = this.mapVisit(node.declarations);
          if (fontCss === '') {
              return '';
          }
          return '@font-face{' + fontCss + '}';
      }
      host(node) {
          return '@host{' + this.mapVisit(node.rules) + '}';
      }
      ['custom-media'](node) {
          return '@custom-media ' + node.name + ' ' + node.media + ';';
      }
      rule(node) {
          const decls = node.declarations;
          if (decls == null || decls.length === 0) {
              return '';
          }
          const usedSelectors = this.usedSelectors;
          let i;
          let j;
          for (i = node.selectors.length - 1; i >= 0; i--) {
              const sel = getSelectors(node.selectors[i]);
              let include = true;
              let jlen = sel.classNames.length;
              if (jlen > 0 && this.hasUsedClassNames) {
                  for (j = 0; j < jlen; j++) {
                      if (!usedSelectors.classNames.has(sel.classNames[j])) {
                          include = false;
                          break;
                      }
                  }
              }
              if (include && this.hasUsedTags) {
                  jlen = sel.tags.length;
                  if (jlen > 0) {
                      for (j = 0; j < jlen; j++) {
                          if (!usedSelectors.tags.has(sel.tags[j])) {
                              include = false;
                              break;
                          }
                      }
                  }
              }
              if (include && this.hasUsedAttrs) {
                  jlen = sel.attrs.length;
                  if (jlen > 0) {
                      for (j = 0; j < jlen; j++) {
                          if (!usedSelectors.attrs.has(sel.attrs[j])) {
                              include = false;
                              break;
                          }
                      }
                  }
              }
              if (include && this.hasUsedIds) {
                  jlen = sel.ids.length;
                  if (jlen > 0) {
                      for (j = 0; j < jlen; j++) {
                          if (!usedSelectors.ids.has(sel.ids[j])) {
                              include = false;
                              break;
                          }
                      }
                  }
              }
              if (!include) {
                  node.selectors.splice(i, 1);
              }
          }
          if (node.selectors.length === 0) {
              return '';
          }
          return `${node.selectors}{${this.mapVisit(decls)}}`;
      }
      declaration(node) {
          return node.property + ':' + node.value + ';';
      }
  }
  
  class UsedSelectors {
      constructor(elm) {
          this.tags = new Set();
          this.classNames = new Set();
          this.ids = new Set();
          this.attrs = new Set();
          this.collectSelectors(elm);
      }
      collectSelectors(elm) {
          if (elm != null && elm.tagName) {
              const tagName = elm.tagName.toLowerCase();
              this.tags.add(tagName);
              const attributes = elm.attributes;
              for (let i = 0, l = attributes.length; i < l; i++) {
                  const attr = attributes.item(i);
                  const attrName = attr.name.toLowerCase();
                  if (attrName === 'class') {
                      const classList = elm.classList;
                      for (let i = 0, l = classList.length; i < l; i++) {
                          this.classNames.add(classList.item(i));
                      }
                  }
                  else if (attrName === 'style') {
                      continue;
                  }
                  else if (attrName === 'id') {
                      this.ids.add(attr.value);
                  }
                  else {
                      this.attrs.add(attrName);
                  }
              }
              for (let i = 0, l = elm.children.length; i < l; i++) {
                  this.collectSelectors(elm.children[i]);
              }
          }
      }
  }
  
  function removeUnusedStyles(doc, results) {
      const styleElms = doc.head.querySelectorAll(`style[data-styles]`);
      if (styleElms.length > 0) {
          const usedSelectors = new UsedSelectors(doc.body);
          for (let i = 0; i < styleElms.length; i++) {
              removeUnusedStyleText(usedSelectors, results, styleElms[i]);
          }
      }
  }
  function removeUnusedStyleText(usedSelectors, results, styleElm) {
      try {
          const cssAst = parseCss(styleElm.innerHTML);
          if (cssAst.stylesheet.diagnostics.length > 0) {
              results.diagnostics.push(...cssAst.stylesheet.diagnostics);
              return;
          }
          try {
              const stringify = new StringifyCss(usedSelectors);
              styleElm.innerHTML = stringify.compile(cssAst);
          }
          catch (e) {
              results.diagnostics.push({
                  level: 'warn',
                  type: 'css',
                  header: 'CSS Stringify',
                  messageText: e
              });
          }
      }
      catch (e) {
          results.diagnostics.push({
              level: 'warn',
              type: 'css',
              header: 'CSS Parse',
              messageText: e
          });
      }
  }
  
  const URL_ = /*@__PURE__*/(function(){
    if (typeof URL === 'function') {
      return URL;
    }
    const requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require;
    if (typeof requireFunc === 'function') {
      try {
        return requireFunc('url').URL;
      } catch (e) {}
    }
    return function() {}
  })();
  
  function normalizeHydrateOptions(inputOpts) {
      const outputOpts = Object.assign({}, inputOpts);
      if (typeof outputOpts.clientHydrateAnnotations !== 'boolean') {
          outputOpts.clientHydrateAnnotations = true;
      }
      if (typeof outputOpts.constrainTimeouts !== 'boolean') {
          outputOpts.constrainTimeouts = true;
      }
      if (typeof outputOpts.maxHydrateCount !== 'number') {
          outputOpts.maxHydrateCount = 300;
      }
      if (typeof outputOpts.timeout !== 'number') {
          outputOpts.timeout = 15000;
      }
      return outputOpts;
  }
  function generateHydrateResults(opts) {
      if (typeof opts.url !== 'string') {
          opts.url = `https://hydrate.stenciljs.com/`;
      }
      const results = {
          diagnostics: [],
          url: opts.url,
          host: null,
          hostname: null,
          href: null,
          port: null,
          pathname: null,
          search: null,
          hash: null,
          html: null,
          hydratedCount: 0,
          anchors: [],
          components: [],
          imgs: [],
          scripts: [],
          styles: [],
          title: null
      };
      try {
          const url = new URL_(opts.url, `https://hydrate.stenciljs.com/`);
          results.url = url.href;
          results.host = url.host;
          results.hostname = url.hostname;
          results.href = url.href;
          results.port = url.port;
          results.pathname = url.pathname;
          results.search = url.search;
          results.hash = url.hash;
      }
      catch (e) {
          renderCatchError(results, e);
      }
      return results;
  }
  function renderBuildError(results, msg) {
      const diagnostic = {
          level: 'error',
          type: 'build',
          header: 'Hydrate Error',
          messageText: msg,
          relFilePath: null,
          absFilePath: null,
          lines: []
      };
      if (results.pathname) {
          if (results.pathname !== '/') {
              diagnostic.header += ': ' + results.pathname;
          }
      }
      else if (results.url) {
          diagnostic.header += ': ' + results.url;
      }
      results.diagnostics.push(diagnostic);
      return diagnostic;
  }
  function renderCatchError(results, err) {
      const diagnostic = renderBuildError(results, null);
      if (err != null) {
          if (err.stack != null) {
              diagnostic.messageText = err.stack.toString();
          }
          else {
              if (err.message != null) {
                  diagnostic.messageText = err.message.toString();
              }
              else {
                  diagnostic.messageText = err.toString();
              }
          }
      }
      return diagnostic;
  }
  
  function updateCanonicalLink(doc, href) {
      let canonicalLinkElm = doc.head.querySelector('link[rel="canonical"]');
      if (typeof href === 'string') {
          if (canonicalLinkElm == null) {
              canonicalLinkElm = doc.createElement('link');
              canonicalLinkElm.setAttribute('rel', 'canonical');
              doc.head.appendChild(canonicalLinkElm);
          }
          canonicalLinkElm.setAttribute('href', href);
      }
      else {
          if (canonicalLinkElm != null) {
              canonicalLinkElm.parentNode.removeChild(canonicalLinkElm);
          }
      }
  }
  
  function finalizeWindow(doc, opts, results) {
      if (opts.removeUnusedStyles !== false) {
          try {
              removeUnusedStyles(doc, results);
          }
          catch (e) {
              renderCatchError(results, e);
          }
      }
      if (typeof opts.title === 'string') {
          try {
              doc.title = opts.title;
          }
          catch (e) {
              renderCatchError(results, e);
          }
      }
      if (opts.removeScripts) {
          removeScripts(doc.documentElement);
      }
      try {
          updateCanonicalLink(doc, opts.canonicalUrl);
      }
      catch (e) {
          renderCatchError(results, e);
      }
      try {
          relocateMetaCharset(doc);
      }
      catch (e) { }
      try {
          getHttpStatus(doc, results);
      }
      catch (e) { }
      if (opts.clientHydrateAnnotations) {
          doc.documentElement.classList.add('hydrated');
      }
      results.title = doc.title;
  }
  function removeScripts(elm) {
      const children = elm.children;
      for (let i = children.length - 1; i >= 0; i--) {
          const child = children[i];
          removeScripts(child);
          if (child.nodeName === 'SCRIPT') {
              child.remove();
          }
          else if (child.nodeName === 'LINK' && child.getAttribute('rel') === 'modulepreload') {
              child.remove();
          }
      }
  }
  function getHttpStatus(doc, results) {
      const metaStatus = doc.head.querySelector('meta[http-equiv="status"]');
      if (metaStatus != null) {
          const content = metaStatus.getAttribute('content');
          if (content != null) {
              results.httpStatus = parseInt(content, 10);
          }
      }
  }
  
  const CONTENT_REF_ID = 'r';
  const ORG_LOCATION_ID = 'o';
  const SLOT_NODE_ID = 's';
  const TEXT_NODE_ID = 't';
  const XLINK_NS = 'http://www.w3.org/1999/xlink';
  
  class MockAttributeMap {
      constructor(caseInsensitive = false) {
          this.caseInsensitive = caseInsensitive;
          this.items = [];
      }
      get length() {
          return this.items.length;
      }
      item(index) {
          return this.items[index] || null;
      }
      setNamedItem(attr) {
          attr.namespaceURI = null;
          this.setNamedItemNS(attr);
      }
      setNamedItemNS(attr) {
          if (attr != null && attr.value != null) {
              attr.value = String(attr.value);
          }
          const existingAttr = this.items.find(a => a.name === attr.name && a.namespaceURI === attr.namespaceURI);
          if (existingAttr != null) {
              existingAttr.value = attr.value;
          }
          else {
              this.items.push(attr);
          }
      }
      getNamedItem(attrName) {
          if (this.caseInsensitive) {
              attrName = attrName.toLowerCase();
          }
          return this.getNamedItemNS(null, attrName);
      }
      getNamedItemNS(namespaceURI, attrName) {
          namespaceURI = getNamespaceURI(namespaceURI);
          return this.items.find(attr => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null;
      }
      removeNamedItem(attr) {
          this.removeNamedItemNS(attr);
      }
      removeNamedItemNS(attr) {
          for (let i = 0, ii = this.items.length; i < ii; i++) {
              if (this.items[i].name === attr.name && this.items[i].namespaceURI === attr.namespaceURI) {
                  this.items.splice(i, 1);
                  break;
              }
          }
      }
  }
  function getNamespaceURI(namespaceURI) {
      return namespaceURI === XLINK_NS ? null : namespaceURI;
  }
  function cloneAttributes(srcAttrs, sortByName = false) {
      const dstAttrs = new MockAttributeMap(srcAttrs.caseInsensitive);
      if (srcAttrs != null) {
          const attrLen = srcAttrs.length;
          if (sortByName && attrLen > 1) {
              const sortedAttrs = [];
              for (let i = 0; i < attrLen; i++) {
                  const srcAttr = srcAttrs.item(i);
                  const dstAttr = new MockAttr(srcAttr.name, srcAttr.value, srcAttr.namespaceURI);
                  sortedAttrs.push(dstAttr);
              }
              sortedAttrs.sort(sortAttributes).forEach(attr => {
                  dstAttrs.setNamedItemNS(attr);
              });
          }
          else {
              for (let i = 0; i < attrLen; i++) {
                  const srcAttr = srcAttrs.item(i);
                  const dstAttr = new MockAttr(srcAttr.name, srcAttr.value, srcAttr.namespaceURI);
                  dstAttrs.setNamedItemNS(dstAttr);
              }
          }
      }
      return dstAttrs;
  }
  function sortAttributes(a, b) {
      if (a.name < b.name)
          return -1;
      if (a.name > b.name)
          return 1;
      return 0;
  }
  class MockAttr {
      constructor(attrName, attrValue, namespaceURI = null) {
          this._name = attrName;
          this._value = String(attrValue);
          this._namespaceURI = namespaceURI;
      }
      get name() {
          return this._name;
      }
      set name(value) {
          this._name = value;
      }
      get value() {
          return this._value;
      }
      set value(value) {
          this._value = String(value);
      }
      get nodeName() {
          return this._name;
      }
      set nodeName(value) {
          this._name = value;
      }
      get nodeValue() {
          return this._value;
      }
      set nodeValue(value) {
          this._value = String(value);
      }
      get namespaceURI() {
          return this._namespaceURI;
      }
      set namespaceURI(namespaceURI) {
          this._namespaceURI = namespaceURI;
      }
  }
  
  const registryMap = new WeakMap();
  const whenDefinedResolvesMap = new WeakMap();
  class MockCustomElementRegistry {
      constructor(win) {
          this.win = win;
      }
      define(tagName, cstr, options) {
          if (tagName.toLowerCase() !== tagName) {
              throw new Error(`Failed to execute 'define' on 'CustomElementRegistry': "${tagName}" is not a valid custom element name`);
          }
          let registry = registryMap.get(this);
          if (registry == null) {
              registry = new Map();
              registryMap.set(this, registry);
          }
          registry.set(tagName, { cstr, options });
          const whenDefinedResolves = whenDefinedResolvesMap.get(this);
          if (whenDefinedResolves != null) {
              const whenDefinedResolveFns = whenDefinedResolves.get(tagName);
              if (whenDefinedResolveFns != null) {
                  whenDefinedResolveFns.forEach(whenDefinedResolveFn => {
                      whenDefinedResolveFn();
                  });
                  whenDefinedResolveFns.length = 0;
                  whenDefinedResolves.delete(tagName);
              }
          }
          const doc = this.win.document;
          if (doc != null) {
              const hosts = doc.querySelectorAll(tagName);
              hosts.forEach(host => {
                  if (upgradedElements.has(host) === false) {
                      tempDisableCallbacks.add(doc);
                      const upgradedCmp = createCustomElement(this, doc, tagName);
                      for (let i = 0; i < host.childNodes.length; i++) {
                          const childNode = host.childNodes[i];
                          childNode.remove();
                          upgradedCmp.appendChild(childNode);
                      }
                      tempDisableCallbacks.delete(doc);
                      if (proxyElements.has(host)) {
                          proxyElements.set(host, upgradedCmp);
                      }
                  }
                  fireConnectedCallback(host);
              });
          }
      }
      get(tagName) {
          const registry = registryMap.get(this);
          if (registry != null) {
              const def = registry.get(tagName.toLowerCase());
              if (def != null) {
                  return def.cstr;
              }
          }
          return undefined;
      }
      upgrade(_rootNode) {
      }
      whenDefined(tagName) {
          tagName = tagName.toLowerCase();
          const registry = registryMap.get(this);
          if (registry != null && registry.has(tagName) === true) {
              return Promise.resolve();
          }
          return new Promise(resolve => {
              let whenDefinedResolves = whenDefinedResolvesMap.get(this);
              if (whenDefinedResolves == null) {
                  whenDefinedResolves = new Map();
                  whenDefinedResolvesMap.set(this, whenDefinedResolves);
              }
              let whenDefinedResolveFns = whenDefinedResolves.get(tagName);
              if (whenDefinedResolveFns == null) {
                  whenDefinedResolveFns = [];
                  whenDefinedResolves.set(tagName, whenDefinedResolveFns);
              }
              whenDefinedResolveFns.push(resolve);
          });
      }
  }
  function resetCustomElementRegistry(customElements) {
      if (customElements != null) {
          const registry = registryMap.get(customElements);
          if (registry != null) {
              registry.clear();
          }
          const whenDefinedResolves = whenDefinedResolvesMap.get(customElements);
          if (whenDefinedResolves != null) {
              whenDefinedResolves.clear();
          }
      }
  }
  function createCustomElement(customElements, ownerDocument, tagName) {
      const Cstr = customElements.get(tagName);
      if (Cstr != null) {
          const cmp = new Cstr(ownerDocument);
          cmp.nodeName = tagName.toUpperCase();
          upgradedElements.add(cmp);
          return cmp;
      }
      const host = new Proxy({}, {
          get(obj, prop) {
              const elm = proxyElements.get(host);
              if (elm != null) {
                  return elm[prop];
              }
              return obj[prop];
          },
          set(obj, prop, val) {
              const elm = proxyElements.get(host);
              if (elm != null) {
                  elm[prop] = val;
              }
              else {
                  obj[prop] = val;
              }
              return true;
          },
          has(obj, prop) {
              const elm = proxyElements.get(host);
              if (prop in elm) {
                  return true;
              }
              if (prop in obj) {
                  return true;
              }
              return false;
          }
      });
      const elm = new MockHTMLElement(ownerDocument, tagName);
      proxyElements.set(host, elm);
      return host;
  }
  const proxyElements = new WeakMap();
  const upgradedElements = new WeakSet();
  function connectNode(ownerDocument, node) {
      node.ownerDocument = ownerDocument;
      if (node.nodeType === 1) {
          if (ownerDocument != null && node.nodeName.includes('-')) {
              const win = ownerDocument.defaultView;
              if (win != null && win.customElements != null) {
                  if (typeof node.connectedCallback === 'function' && node.isConnected) {
                      fireConnectedCallback(node);
                  }
              }
              const shadowRoot = node.shadowRoot;
              if (shadowRoot != null) {
                  shadowRoot.childNodes.forEach(childNode => {
                      connectNode(ownerDocument, childNode);
                  });
              }
          }
          node.childNodes.forEach(childNode => {
              connectNode(ownerDocument, childNode);
          });
      }
      else {
          node.childNodes.forEach(childNode => {
              childNode.ownerDocument = ownerDocument;
          });
      }
  }
  function fireConnectedCallback(node) {
      if (typeof node.connectedCallback === 'function') {
          if (tempDisableCallbacks.has(node.ownerDocument) === false) {
              try {
                  node.connectedCallback();
              }
              catch (e) {
                  console.error(e);
              }
          }
      }
  }
  function disconnectNode(node) {
      if (node.nodeType === 1) {
          if (node.nodeName.includes('-') === true && typeof node.disconnectedCallback === 'function') {
              if (tempDisableCallbacks.has(node.ownerDocument) === false) {
                  try {
                      node.disconnectedCallback();
                  }
                  catch (e) {
                      console.error(e);
                  }
              }
          }
          node.childNodes.forEach(disconnectNode);
      }
  }
  function attributeChanged(node, attrName, oldValue, newValue) {
      attrName = attrName.toLowerCase();
      const observedAttributes = node.constructor.observedAttributes;
      if (Array.isArray(observedAttributes) === true && observedAttributes.some(obs => obs.toLowerCase() === attrName) === true) {
          try {
              node.attributeChangedCallback(attrName, oldValue, newValue);
          }
          catch (e) {
              console.error(e);
          }
      }
  }
  function checkAttributeChanged(node) {
      return (node.nodeName.includes('-') === true && typeof node.attributeChangedCallback === 'function');
  }
  const tempDisableCallbacks = new Set();
  
  function unwrapExports (x) {
  	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
  }
  
  function createCommonjsModule(fn, module) {
  	return module = { exports: {} }, fn(module, module.exports), module.exports;
  }
  
  var parse_1 = createCommonjsModule(function (module, exports) {
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.default = parse;
  var reName = /^(?:\\.|[\w\-\u00b0-\uFFFF])+/, reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi, 
  //modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
  reAttr = /^\s*((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:(\S?)=\s*(?:(['"])([^]*?)\3|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*(i)?\]/;
  var actionTypes = {
      undefined: "exists",
      "": "equals",
      "~": "element",
      "^": "start",
      $: "end",
      "*": "any",
      "!": "not",
      "|": "hyphen"
  };
  var Traversals = {
      ">": "child",
      "<": "parent",
      "~": "sibling",
      "+": "adjacent"
  };
  var attribSelectors = {
      "#": ["id", "equals"],
      ".": ["class", "element"]
  };
  //pseudos, whose data-property is parsed as well
  var unpackPseudos = new Set(["has", "not", "matches"]);
  var stripQuotesFromPseudos = new Set(["contains", "icontains"]);
  var quotes = new Set(['"', "'"]);
  //unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152
  function funescape(_, escaped, escapedWhitespace) {
      var high = parseInt(escaped, 16) - 0x10000;
      // NaN means non-codepoint
      return high !== high || escapedWhitespace
          ? escaped
          : high < 0
              ? // BMP codepoint
                  String.fromCharCode(high + 0x10000)
              : // Supplemental Plane codepoint (surrogate pair)
                  String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00);
  }
  function unescapeCSS(str) {
      return str.replace(reEscape, funescape);
  }
  function isWhitespace(c) {
      return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r";
  }
  function parse(selector, options) {
      var subselects = [];
      selector = parseSelector(subselects, selector + "", options);
      if (selector !== "") {
          throw new Error("Unmatched selector: " + selector);
      }
      return subselects;
  }
  function parseSelector(subselects, selector, options) {
      var tokens = [], sawWS = false;
      function getName() {
          var match = selector.match(reName);
          if (!match) {
              throw new Error("Expected name, found " + selector);
          }
          var sub = match[0];
          selector = selector.substr(sub.length);
          return unescapeCSS(sub);
      }
      function stripWhitespace(start) {
          while (isWhitespace(selector.charAt(start)))
              start++;
          selector = selector.substr(start);
      }
      function isEscaped(pos) {
          var slashCount = 0;
          while (selector.charAt(--pos) === "\\")
              slashCount++;
          return (slashCount & 1) === 1;
      }
      stripWhitespace(0);
      while (selector !== "") {
          var firstChar = selector.charAt(0);
          if (isWhitespace(firstChar)) {
              sawWS = true;
              stripWhitespace(1);
          }
          else if (firstChar in Traversals) {
              tokens.push({ type: Traversals[firstChar] });
              sawWS = false;
              stripWhitespace(1);
          }
          else if (firstChar === ",") {
              if (tokens.length === 0) {
                  throw new Error("Empty sub-selector");
              }
              subselects.push(tokens);
              tokens = [];
              sawWS = false;
              stripWhitespace(1);
          }
          else {
              if (sawWS) {
                  if (tokens.length > 0) {
                      tokens.push({ type: "descendant" });
                  }
                  sawWS = false;
              }
              if (firstChar === "*") {
                  selector = selector.substr(1);
                  tokens.push({ type: "universal" });
              }
              else if (firstChar in attribSelectors) {
                  var _a = attribSelectors[firstChar], name_1 = _a[0], action = _a[1];
                  selector = selector.substr(1);
                  tokens.push({
                      type: "attribute",
                      name: name_1,
                      action: action,
                      value: getName(),
                      ignoreCase: false
                  });
              }
              else if (firstChar === "[") {
                  selector = selector.substr(1);
                  var data = selector.match(reAttr);
                  if (!data) {
                      throw new Error("Malformed attribute selector: " + selector);
                  }
                  selector = selector.substr(data[0].length);
                  var name_2 = unescapeCSS(data[1]);
                  if (!options ||
                      ("lowerCaseAttributeNames" in options
                          ? options.lowerCaseAttributeNames
                          : !options.xmlMode)) {
                      name_2 = name_2.toLowerCase();
                  }
                  tokens.push({
                      type: "attribute",
                      name: name_2,
                      action: actionTypes[data[2]],
                      value: unescapeCSS(data[4] || data[5] || ""),
                      ignoreCase: !!data[6]
                  });
              }
              else if (firstChar === ":") {
                  if (selector.charAt(1) === ":") {
                      selector = selector.substr(2);
                      tokens.push({
                          type: "pseudo-element",
                          name: getName().toLowerCase()
                      });
                      continue;
                  }
                  selector = selector.substr(1);
                  var name_3 = getName().toLowerCase();
                  var data = null;
                  if (selector.charAt(0) === "(") {
                      if (unpackPseudos.has(name_3)) {
                          var quot = selector.charAt(1);
                          var quoted = quotes.has(quot);
                          selector = selector.substr(quoted ? 2 : 1);
                          data = [];
                          selector = parseSelector(data, selector, options);
                          if (quoted) {
                              if (selector.charAt(0) !== quot) {
                                  throw new Error("Unmatched quotes in :" + name_3);
                              }
                              else {
                                  selector = selector.substr(1);
                              }
                          }
                          if (selector.charAt(0) !== ")") {
                              throw new Error("Missing closing parenthesis in :" + name_3 + " (" + selector + ")");
                          }
                          selector = selector.substr(1);
                      }
                      else {
                          var pos = 1, counter = 1;
                          for (; counter > 0 && pos < selector.length; pos++) {
                              if (selector.charAt(pos) === "(" && !isEscaped(pos))
                                  counter++;
                              else if (selector.charAt(pos) === ")" &&
                                  !isEscaped(pos))
                                  counter--;
                          }
                          if (counter) {
                              throw new Error("Parenthesis not matched");
                          }
                          data = selector.substr(1, pos - 2);
                          selector = selector.substr(pos);
                          if (stripQuotesFromPseudos.has(name_3)) {
                              var quot = data.charAt(0);
                              if (quot === data.slice(-1) && quotes.has(quot)) {
                                  data = data.slice(1, -1);
                              }
                              data = unescapeCSS(data);
                          }
                      }
                  }
                  tokens.push({ type: "pseudo", name: name_3, data: data });
              }
              else if (reName.test(selector)) {
                  var name_4 = getName();
                  if (!options ||
                      ("lowerCaseTags" in options
                          ? options.lowerCaseTags
                          : !options.xmlMode)) {
                      name_4 = name_4.toLowerCase();
                  }
                  tokens.push({ type: "tag", name: name_4 });
              }
              else {
                  if (tokens.length &&
                      tokens[tokens.length - 1].type === "descendant") {
                      tokens.pop();
                  }
                  addToken(subselects, tokens);
                  return selector;
              }
          }
      }
      addToken(subselects, tokens);
      return selector;
  }
  function addToken(subselects, tokens) {
      if (subselects.length > 0 && tokens.length === 0) {
          throw new Error("Empty sub-selector");
      }
      subselects.push(tokens);
  }
  });
  
  unwrapExports(parse_1);
  
  var stringify_1 = createCommonjsModule(function (module, exports) {
  Object.defineProperty(exports, "__esModule", { value: true });
  var actionTypes = {
      equals: "",
      element: "~",
      start: "^",
      end: "$",
      any: "*",
      not: "!",
      hyphen: "|"
  };
  var simpleSelectors = {
      child: " > ",
      parent: " < ",
      sibling: " ~ ",
      adjacent: " + ",
      descendant: " ",
      universal: "*"
  };
  function stringify(token) {
      return token.map(stringifySubselector).join(", ");
  }
  exports.default = stringify;
  function stringifySubselector(token) {
      return token.map(stringifyToken).join("");
  }
  function stringifyToken(token) {
      if (token.type in simpleSelectors)
          return simpleSelectors[token.type];
      if (token.type === "tag")
          return escapeName(token.name);
      if (token.type === "pseudo-element")
          return "::" + escapeName(token.name);
      if (token.type === "attribute") {
          if (token.action === "exists")
              return "[" + escapeName(token.name) + "]";
          if (token.name === "id" &&
              token.action === "equals" &&
              !token.ignoreCase)
              return "#" + escapeName(token.value);
          if (token.name === "class" &&
              token.action === "element" &&
              !token.ignoreCase)
              return "." + escapeName(token.value);
          return ("[" +
              escapeName(token.name) +
              actionTypes[token.action] +
              "='" +
              escapeName(token.value) +
              "'" +
              (token.ignoreCase ? "i" : "") +
              "]");
      }
      if (token.type === "pseudo") {
          if (token.data === null)
              return ":" + escapeName(token.name);
          if (typeof token.data === "string") {
              return ":" + escapeName(token.name) + "(" + token.data + ")";
          }
          return ":" + escapeName(token.name) + "(" + stringify(token.data) + ")";
      }
      throw new Error("Unknown type");
  }
  function escapeName(str) {
      //TODO
      return str;
  }
  });
  
  unwrapExports(stringify_1);
  
  var lib = createCommonjsModule(function (module, exports) {
  function __export(m) {
      for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
  }
  Object.defineProperty(exports, "__esModule", { value: true });
  __export(parse_1);
  var parse_1$1 = parse_1;
  exports.parse = parse_1$1.default;
  
  exports.stringify = stringify_1.default;
  });
  
  unwrapExports(lib);
  var lib_1 = lib.parse;
  var lib_2 = lib.stringify;
  
  function closest(selector, elm) {
      while (elm != null) {
          if (elm.matches(selector)) {
              return elm;
          }
          elm = elm.parentNode;
      }
      return null;
  }
  function matches(selector, elm) {
      const selectors = lib_1(selector);
      return matchesSelectors(selectors, elm);
  }
  function selectOne(selector, elm) {
      const selectors = lib_1(selector);
      return selectOneRecursion(selectors, elm);
  }
  function selectOneRecursion(selectors, elm) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          if (matchesSelectors(selectors, children[i]) === true) {
              return children[i];
          }
          const childMatch = selectOneRecursion(selectors, children[i]);
          if (childMatch != null) {
              return childMatch;
          }
      }
      return null;
  }
  function selectAll(selector, elm) {
      const selectors = lib_1(selector);
      const foundElms = [];
      selectAllRecursion(selectors, elm, foundElms);
      return foundElms;
  }
  function selectAllRecursion(selectors, elm, found) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          if (matchesSelectors(selectors, children[i]) === true) {
              found.push(children[i]);
          }
          selectAllRecursion(selectors, children[i], found);
      }
  }
  function matchesSelectors(selectors, elm) {
      for (let i = 0, ii = selectors.length; i < ii; i++) {
          if (matchesEverySelector(selectors[i], elm) === true) {
              return true;
          }
      }
      return false;
  }
  function matchesEverySelector(selectorData, elm) {
      for (let i = 0, ii = selectorData.length; i < ii; i++) {
          if (matchesSelector(selectorData[i], elm) === false) {
              return false;
          }
      }
      return true;
  }
  function matchesSelector(selectorData, elm) {
      switch (selectorData.type) {
          case 'tag':
              return elm.nodeName.toLowerCase() === selectorData.name.toLowerCase();
          case 'attribute':
              if (selectorData.name === 'class') {
                  return elm.classList.contains(selectorData.value);
              }
              if (selectorData.action === 'exists') {
                  return elm.hasAttribute(selectorData.name);
              }
              if (selectorData.action === 'equals') {
                  return elm.getAttribute(selectorData.name) === selectorData.value;
              }
              return false;
          case 'child':
              return true;
      }
      return false;
  }
  
  class CSSStyleDeclaration {
      constructor() {
          this._styles = new Map();
      }
      setProperty(prop, value) {
          prop = jsCaseToCssCase(prop);
          if (value == null || value === '') {
              this._styles.delete(prop);
          }
          else {
              this._styles.set(prop, String(value));
          }
      }
      getPropertyValue(prop) {
          prop = jsCaseToCssCase(prop);
          return String(this._styles.get(prop) || '');
      }
      removeProperty(prop) {
          prop = jsCaseToCssCase(prop);
          this._styles.delete(prop);
      }
      get length() {
          return this._styles.size;
      }
      get cssText() {
          const cssText = [];
          this._styles.forEach((value, prop) => {
              cssText.push(`${prop}: ${value};`);
          });
          return cssText.join(' ').trim();
      }
      set cssText(cssText) {
          if (cssText == null || cssText === '') {
              this._styles.clear();
              return;
          }
          cssText.split(';').forEach(rule => {
              rule = rule.trim();
              if (rule.length > 0) {
                  const splt = rule.split(':');
                  if (splt.length > 1) {
                      const prop = splt[0].trim();
                      const value = splt[1].trim();
                      if (prop !== '' && value !== '') {
                          this._styles.set(jsCaseToCssCase(prop), value);
                      }
                  }
              }
          });
      }
  }
  function createCSSStyleDeclaration() {
      return new Proxy(new CSSStyleDeclaration(), cssProxyHandler);
  }
  const cssProxyHandler = {
      get(cssStyle, prop) {
          if (prop in cssStyle) {
              return cssStyle[prop];
          }
          prop = cssCaseToJsCase(prop);
          return cssStyle.getPropertyValue(prop);
      },
      set(cssStyle, prop, value) {
          if (prop in cssStyle) {
              cssStyle[prop] = value;
          }
          else {
              cssStyle.setProperty(prop, value);
          }
          return true;
      }
  };
  function cssCaseToJsCase(str) {
      if (str.length > 1 && str.includes('-') === true) {
          str = str.toLowerCase().split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join('');
          str = str.substr(0, 1).toLowerCase() + str.substr(1);
      }
      return str;
  }
  function jsCaseToCssCase(str) {
      if (str.length > 1 && (str.includes('-') === false && /[A-Z]/.test(str) === true)) {
          str = str.replace(/([A-Z])/g, g => ' ' + g[0]).trim().replace(/ /g, '-').toLowerCase();
      }
      return str;
  }
  
  function dataset(elm) {
      const ds = {};
      const attributes = elm.attributes;
      const attrLen = attributes.length;
      for (let i = 0; i < attrLen; i++) {
          const attr = attributes.item(i);
          const nodeName = attr.nodeName;
          if (nodeName.startsWith('data-')) {
              ds[dashToPascalCase(nodeName)] = attr.nodeValue;
          }
      }
      return new Proxy(ds, {
          get(_obj, camelCaseProp) {
              return ds[camelCaseProp];
          },
          set(_obj, camelCaseProp, value) {
              const dataAttr = toDataAttribute(camelCaseProp);
              elm.setAttribute(dataAttr, value);
              return true;
          }
      });
  }
  function toDataAttribute(str) {
      return 'data-' + String(str).replace(/([A-Z0-9])/g, g => ' ' + g[0]).trim().replace(/ /g, '-').toLowerCase();
  }
  function dashToPascalCase(str) {
      str = String(str).substr(5);
      return str.split('-').map((segment, index) => {
          if (index === 0) {
              return segment.charAt(0).toLowerCase() + segment.slice(1);
          }
          return segment.charAt(0).toUpperCase() + segment.slice(1);
      }).join('');
  }
  
  class MockClassList {
      constructor(elm) {
          this.elm = elm;
      }
      add(...classNames) {
          const clsNames = getItems(this.elm);
          let updated = false;
          classNames.forEach(className => {
              className = String(className);
              validateClass(className);
              if (clsNames.includes(className) === false) {
                  clsNames.push(className);
                  updated = true;
              }
          });
          if (updated) {
              this.elm.setAttributeNS(null, 'class', clsNames.join(' '));
          }
      }
      remove(...classNames) {
          const clsNames = getItems(this.elm);
          let updated = false;
          classNames.forEach(className => {
              className = String(className);
              validateClass(className);
              const index = clsNames.indexOf(className);
              if (index > -1) {
                  clsNames.splice(index, 1);
                  updated = true;
              }
          });
          if (updated) {
              this.elm.setAttributeNS(null, 'class', clsNames.filter(c => c.length > 0).join(' '));
          }
      }
      contains(className) {
          className = String(className);
          return getItems(this.elm).includes(className);
      }
      toggle(className) {
          className = String(className);
          if (this.contains(className) === true) {
              this.remove(className);
          }
          else {
              this.add(className);
          }
      }
      get length() {
          return getItems(this.elm).length;
      }
      item(index) {
          return getItems(this.elm)[index];
      }
      toString() {
          return getItems(this.elm).join(' ');
      }
  }
  function validateClass(className) {
      if (className === '') {
          throw new Error('The token provided must not be empty.');
      }
      if (/\s/.test(className)) {
          throw new Error(`The token provided ('${className}') contains HTML space characters, which are not valid in tokens.`);
      }
  }
  function getItems(elm) {
      const className = elm.getAttribute('class');
      if (typeof className === 'string' && className.length > 0) {
          return className.trim().split(' ').filter(c => c.length > 0);
      }
      return [];
  }
  
  class MockEvent {
      constructor(type, eventInitDict) {
          this.bubbles = false;
          this.cancelBubble = false;
          this.cancelable = false;
          this.composed = false;
          this.currentTarget = null;
          this.defaultPrevented = false;
          this.srcElement = null;
          this.target = null;
          if (typeof type !== 'string') {
              throw new Error(`Event type required`);
          }
          this.type = type;
          this.timeStamp = Date.now();
          if (eventInitDict != null) {
              Object.assign(this, eventInitDict);
          }
      }
      preventDefault() {
          this.defaultPrevented = true;
      }
      stopPropagation() {
          this.cancelBubble = true;
      }
      stopImmediatePropagation() {
          this.cancelBubble = true;
      }
  }
  class MockCustomEvent extends MockEvent {
      constructor(type, customEventInitDic) {
          super(type);
          this.detail = null;
          if (customEventInitDic != null) {
              Object.assign(this, customEventInitDic);
          }
      }
  }
  class MockKeyboardEvent extends MockEvent {
      constructor(type, keyboardEventInitDic) {
          super(type);
          this.code = '';
          this.key = '';
          this.altKey = false;
          this.ctrlKey = false;
          this.metaKey = false;
          this.shiftKey = false;
          this.location = 0;
          this.repeat = false;
          if (keyboardEventInitDic != null) {
              Object.assign(this, keyboardEventInitDic);
          }
      }
  }
  class MockMouseEvent extends MockEvent {
      constructor(type, mouseEventInitDic) {
          super(type);
          this.screenX = 0;
          this.screenY = 0;
          this.clientX = 0;
          this.clientY = 0;
          this.ctrlKey = false;
          this.shiftKey = false;
          this.altKey = false;
          this.metaKey = false;
          this.button = 0;
          this.buttons = 0;
          this.relatedTarget = null;
          if (mouseEventInitDic != null) {
              Object.assign(this, mouseEventInitDic);
          }
      }
  }
  class MockEventListener {
      constructor(type, handler) {
          this.type = type;
          this.handler = handler;
      }
  }
  function addEventListener(elm, type, handler) {
      const target = elm;
      if (target.__listeners == null) {
          target.__listeners = [];
      }
      target.__listeners.push(new MockEventListener(type, handler));
  }
  function removeEventListener(elm, type, handler) {
      const target = elm;
      if (target != null && Array.isArray(target.__listeners) === true) {
          const elmListener = target.__listeners.find(e => e.type === type && e.handler === handler);
          if (elmListener != null) {
              const index = target.__listeners.indexOf(elmListener);
              target.__listeners.splice(index, 1);
          }
      }
  }
  function resetEventListeners(target) {
      if (target != null && target.__listeners != null) {
          target.__listeners = null;
      }
  }
  function triggerEventListener(elm, ev) {
      if (elm == null || ev.cancelBubble === true) {
          return;
      }
      const target = elm;
      ev.currentTarget = elm;
      if (Array.isArray(target.__listeners) === true) {
          const listeners = target.__listeners.filter(e => e.type === ev.type);
          listeners.forEach(listener => {
              try {
                  listener.handler.call(target, ev);
              }
              catch (err) {
                  console.error(err);
              }
          });
      }
      if (ev.bubbles === false) {
          return;
      }
      if (elm.nodeName === "#document") {
          triggerEventListener(elm.defaultView, ev);
      }
      else {
          triggerEventListener(elm.parentElement, ev);
      }
  }
  function dispatchEvent(currentTarget, ev) {
      ev.target = currentTarget;
      triggerEventListener(currentTarget, ev);
      return true;
  }
  
  function serializeNodeToHtml(elm, opts = {}) {
      const output = {
          currentLineWidth: 0,
          indent: 0,
          isWithinBody: false,
          text: [],
      };
      if (opts.prettyHtml) {
          if (typeof opts.indentSpaces !== 'number') {
              opts.indentSpaces = 2;
          }
          if (typeof opts.newLines !== 'boolean') {
              opts.newLines = true;
          }
          opts.approximateLineWidth = -1;
      }
      else {
          opts.prettyHtml = false;
          if (typeof opts.newLines !== 'boolean') {
              opts.newLines = false;
          }
          if (typeof opts.indentSpaces !== 'number') {
              opts.indentSpaces = 0;
          }
      }
      if (typeof opts.approximateLineWidth !== 'number') {
          opts.approximateLineWidth = -1;
      }
      if (typeof opts.removeEmptyAttributes !== 'boolean') {
          opts.removeEmptyAttributes = true;
      }
      if (typeof opts.removeAttributeQuotes !== 'boolean') {
          opts.removeAttributeQuotes = false;
      }
      if (typeof opts.removeBooleanAttributeQuotes !== 'boolean') {
          opts.removeBooleanAttributeQuotes = false;
      }
      if (typeof opts.removeHtmlComments !== 'boolean') {
          opts.removeHtmlComments = false;
      }
      if (typeof opts.serializeShadowRoot !== 'boolean') {
          opts.serializeShadowRoot = false;
      }
      if (opts.outerHtml) {
          serializeToHtml(elm, opts, output, false);
      }
      else {
          for (let i = 0, ii = elm.childNodes.length; i < ii; i++) {
              serializeToHtml(elm.childNodes[i], opts, output, false);
          }
      }
      if (output.text[0] === '\n') {
          output.text.shift();
      }
      if (output.text[output.text.length - 1] === '\n') {
          output.text.pop();
      }
      return output.text.join('');
  }
  function serializeToHtml(node, opts, output, isShadowRoot) {
      if (node.nodeType === 1 || isShadowRoot) {
          const tagName = isShadowRoot ? 'mock:shadow-root' : getTagName(node);
          if (tagName === 'body') {
              output.isWithinBody = true;
          }
          const ignoreTag = (opts.excludeTags != null && opts.excludeTags.includes(tagName));
          if (ignoreTag === false) {
              if (opts.newLines) {
                  output.text.push('\n');
                  output.currentLineWidth = 0;
              }
              if (opts.indentSpaces > 0) {
                  for (let i = 0; i < output.indent; i++) {
                      output.text.push(' ');
                  }
                  output.currentLineWidth += output.indent;
              }
              output.text.push('<' + tagName);
              output.currentLineWidth += (tagName.length + 1);
              const attrsLength = node.attributes.length;
              const attributes = (opts.prettyHtml && attrsLength > 1) ?
                  cloneAttributes(node.attributes, true) :
                  node.attributes;
              for (let i = 0; i < attrsLength; i++) {
                  const attr = attributes.item(i);
                  const attrName = attr.name;
                  if (attrName === 'style') {
                      continue;
                  }
                  let attrValue = attr.value;
                  if (opts.removeEmptyAttributes && attrValue === '' && REMOVE_EMPTY_ATTR.has(attrName)) {
                      continue;
                  }
                  const attrNamespaceURI = attr.namespaceURI;
                  if (attrNamespaceURI == null) {
                      output.currentLineWidth += (attrName.length + 1);
                      if (opts.approximateLineWidth > 0 && output.currentLineWidth > opts.approximateLineWidth) {
                          output.text.push('\n' + attrName);
                          output.currentLineWidth = 0;
                      }
                      else {
                          output.text.push(' ' + attrName);
                      }
                  }
                  else if (attrNamespaceURI === 'http://www.w3.org/XML/1998/namespace') {
                      output.text.push(' xml:' + attrName);
                      output.currentLineWidth += (attrName.length + 5);
                  }
                  else if (attrNamespaceURI === 'http://www.w3.org/2000/xmlns/') {
                      if (attrName !== 'xmlns') {
                          output.text.push(' xmlns:' + attrName);
                          output.currentLineWidth += (attrName.length + 7);
                      }
                      else {
                          output.text.push(' ' + attrName);
                          output.currentLineWidth += (attrName.length + 1);
                      }
                  }
                  else if (attrNamespaceURI === XLINK_NS) {
                      output.text.push(' xlink:' + attrName);
                      output.currentLineWidth += (attrName.length + 7);
                  }
                  else {
                      output.text.push(' ' + attrNamespaceURI + ':' + attrName);
                      output.currentLineWidth += (attrNamespaceURI.length + attrName.length + 2);
                  }
                  if (opts.prettyHtml && attrName === 'class') {
                      attrValue = attr.value = attrValue.split(' ').filter(t => t !== '').sort().join(' ').trim();
                  }
                  if (attrValue === '') {
                      if (opts.removeBooleanAttributeQuotes && BOOLEAN_ATTR.has(attrName)) {
                          continue;
                      }
                      if (opts.removeEmptyAttributes && attrName.startsWith('data-')) {
                          continue;
                      }
                  }
                  if (opts.removeAttributeQuotes && CAN_REMOVE_ATTR_QUOTES.test(attrValue)) {
                      output.text.push('=' + escapeString(attrValue, true));
                      output.currentLineWidth += (attrValue.length + 1);
                  }
                  else {
                      output.text.push('="' + escapeString(attrValue, true) + '"');
                      output.currentLineWidth += (attrValue.length + 3);
                  }
              }
              if (node.hasAttribute('style')) {
                  const cssText = node.style.cssText;
                  if (opts.approximateLineWidth > 0 && (output.currentLineWidth + cssText.length + 10) > opts.approximateLineWidth) {
                      output.text.push(`\nstyle="${cssText}">`);
                      output.currentLineWidth = 0;
                  }
                  else {
                      output.text.push(` style="${cssText}">`);
                      output.currentLineWidth += (cssText.length + 10);
                  }
              }
              else {
                  output.text.push('>');
                  output.currentLineWidth += 1;
              }
          }
          if (EMPTY_ELEMENTS.has(tagName) === false) {
              if (opts.serializeShadowRoot && node.shadowRoot != null) {
                  output.indent = output.indent + opts.indentSpaces;
                  serializeToHtml(node.shadowRoot, opts, output, true);
                  output.indent = output.indent - opts.indentSpaces;
                  if (opts.newLines && (node.childNodes.length === 0 || (node.childNodes.length === 1 && node.childNodes[0].nodeType === 3 && node.childNodes[0].nodeValue.trim() === ''))) {
                      output.text.push('\n');
                      output.currentLineWidth = 0;
                      for (let i = 0; i < output.indent; i++) {
                          output.text.push(' ');
                      }
                      output.currentLineWidth += output.indent;
                  }
              }
              if (opts.excludeTagContent == null || opts.excludeTagContent.includes(tagName) === false) {
                  const childNodes = tagName === 'template' ? node.content.childNodes : (node.childNodes);
                  const childNodeLength = childNodes.length;
                  if (childNodeLength > 0) {
                      if (childNodeLength === 1 && childNodes[0].nodeType === 3 && (typeof childNodes[0].nodeValue !== 'string' || childNodes[0].nodeValue.trim() === '')) ;
                      else {
                          if (opts.indentSpaces > 0 && ignoreTag === false) {
                              output.indent = output.indent + opts.indentSpaces;
                          }
                          for (let i = 0; i < childNodeLength; i++) {
                              serializeToHtml(childNodes[i], opts, output, false);
                          }
                          if (ignoreTag === false) {
                              if (opts.newLines) {
                                  output.text.push('\n');
                                  output.currentLineWidth = 0;
                              }
                              if (opts.indentSpaces > 0) {
                                  output.indent = output.indent - opts.indentSpaces;
                                  for (let i = 0; i < output.indent; i++) {
                                      output.text.push(' ');
                                  }
                                  output.currentLineWidth += output.indent;
                              }
                          }
                      }
                  }
                  if (ignoreTag === false) {
                      output.text.push('</' + tagName + '>');
                      output.currentLineWidth += (tagName.length + 3);
                  }
              }
          }
          if (opts.approximateLineWidth > 0 && STRUCTURE_ELEMENTS.has(tagName)) {
              output.text.push('\n');
              output.currentLineWidth = 0;
          }
          if (tagName === 'body') {
              output.isWithinBody = false;
          }
      }
      else if (node.nodeType === 3) {
          let textContent = node.nodeValue;
          if (typeof textContent === 'string') {
              const trimmedTextContent = textContent.trim();
              if (trimmedTextContent === '') {
                  if (isWithinWhitespaceSensitive(node)) {
                      output.text.push(textContent);
                      output.currentLineWidth += textContent.length;
                  }
                  else if (opts.approximateLineWidth > 0 && !output.isWithinBody) ;
                  else if (!opts.prettyHtml) {
                      output.currentLineWidth += 1;
                      if (opts.approximateLineWidth > 0 && output.currentLineWidth > opts.approximateLineWidth) {
                          output.text.push('\n');
                          output.currentLineWidth = 0;
                      }
                      else {
                          output.text.push(' ');
                      }
                  }
              }
              else {
                  if (opts.newLines) {
                      output.text.push('\n');
                      output.currentLineWidth = 0;
                  }
                  if (opts.indentSpaces > 0) {
                      for (let i = 0; i < output.indent; i++) {
                          output.text.push(' ');
                      }
                      output.currentLineWidth += output.indent;
                  }
                  let textContentLength = textContent.length;
                  if (textContentLength > 0) {
                      const parentTagName = (node.parentNode != null && node.parentNode.nodeType === 1 ? node.parentNode.nodeName : null);
                      if (NON_ESCAPABLE_CONTENT.has(parentTagName)) {
                          if (isWithinWhitespaceSensitive(node)) {
                              output.text.push(textContent);
                          }
                          else {
                              output.text.push(trimmedTextContent);
                              textContentLength = trimmedTextContent.length;
                          }
                          output.currentLineWidth += textContentLength;
                      }
                      else {
                          if (opts.prettyHtml) {
                              output.text.push(escapeString(textContent.replace(/\s\s+/g, ' ').trim(), false));
                              output.currentLineWidth += textContentLength;
                          }
                          else {
                              if (isWithinWhitespaceSensitive(node)) {
                                  output.currentLineWidth += textContentLength;
                              }
                              else {
                                  if (/\s/.test(textContent.charAt(0))) {
                                      textContent = ' ' + textContent.trimLeft();
                                  }
                                  textContentLength = textContent.length;
                                  if (textContentLength > 1) {
                                      if (/\s/.test(textContent.charAt(textContentLength - 1))) {
                                          if (opts.approximateLineWidth > 0 && (output.currentLineWidth + textContentLength) > opts.approximateLineWidth) {
                                              textContent = textContent.trimRight() + '\n';
                                              output.currentLineWidth = 0;
                                          }
                                          else {
                                              textContent = textContent.trimRight() + ' ';
                                          }
                                      }
                                  }
                                  output.currentLineWidth += textContentLength;
                              }
                              output.text.push(escapeString(textContent, false));
                          }
                      }
                  }
              }
          }
      }
      else if (node.nodeType === 8) {
          const nodeValue = node.nodeValue;
          if (opts.removeHtmlComments) {
              const isHydrateAnnotation = nodeValue.startsWith(CONTENT_REF_ID + '.') || nodeValue.startsWith(ORG_LOCATION_ID + '.') || nodeValue.startsWith(SLOT_NODE_ID + '.') || nodeValue.startsWith(TEXT_NODE_ID + '.');
              if (!isHydrateAnnotation) {
                  return;
              }
          }
          if (opts.newLines) {
              output.text.push('\n');
              output.currentLineWidth = 0;
          }
          if (opts.indentSpaces > 0) {
              for (let i = 0; i < output.indent; i++) {
                  output.text.push(' ');
              }
              output.currentLineWidth += output.indent;
          }
          output.text.push('<!--' + nodeValue + '-->');
          output.currentLineWidth += (nodeValue.length + 7);
      }
      else if (node.nodeType === 10) {
          output.text.push('<!doctype html>');
      }
  }
  const AMP_REGEX = /&/g;
  const NBSP_REGEX = /\u00a0/g;
  const DOUBLE_QUOTE_REGEX = /"/g;
  const LT_REGEX = /</g;
  const GT_REGEX = />/g;
  const CAN_REMOVE_ATTR_QUOTES = /^[^ \t\n\f\r"'`=<>\/\\-]+$/;
  function getTagName(element) {
      if (element.namespaceURI === 'http://www.w3.org/1999/xhtml') {
          return element.nodeName.toLowerCase();
      }
      else {
          return element.nodeName;
      }
  }
  function escapeString(str, attrMode) {
      str = str.replace(AMP_REGEX, '&amp;').replace(NBSP_REGEX, '&nbsp;');
      if (attrMode) {
          return str.replace(DOUBLE_QUOTE_REGEX, '&quot;');
      }
      return str.replace(LT_REGEX, '&lt;').replace(GT_REGEX, '&gt;');
  }
  function isWithinWhitespaceSensitive(node) {
      while (node != null) {
          if (WHITESPACE_SENSITIVE.has(node.nodeName)) {
              return true;
          }
          node = node.parentNode;
      }
      return false;
  }
  const NON_ESCAPABLE_CONTENT = new Set(['STYLE', 'SCRIPT', 'IFRAME', 'NOSCRIPT', 'XMP', 'NOEMBED', 'NOFRAMES', 'PLAINTEXT']);
  const WHITESPACE_SENSITIVE = new Set(['CODE', 'OUTPUT', 'PLAINTEXT', 'PRE', 'TEMPLATE', 'TEXTAREA']);
  const EMPTY_ELEMENTS = new Set(['area', 'base', 'basefont', 'bgsound', 'br', 'col', 'embed', 'frame', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'trace', 'wbr']);
  const REMOVE_EMPTY_ATTR = new Set(['class', 'dir', 'id', 'lang', 'name', 'title']);
  const BOOLEAN_ATTR = new Set(['allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'compact', 'controls', 'declare', 'default', 'defaultchecked', 'defaultmuted', 'defaultselected', 'defer', 'disabled', 'enabled', 'formnovalidate', 'hidden', 'indeterminate', 'inert', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'nohref', 'nomodule', 'noresize', 'noshade', 'novalidate', 'nowrap', 'open', 'pauseonexit', 'readonly', 'required', 'reversed', 'scoped', 'seamless', 'selected', 'sortable', 'truespeed', 'typemustmatch', 'visible']);
  const STRUCTURE_ELEMENTS = new Set(['html', 'body', 'head', 'iframe', 'meta', 'link', 'base', 'title', 'script', 'style']);
  
  const UNDEFINED_CODE_POINTS = [
      0xfffe,
      0xffff,
      0x1fffe,
      0x1ffff,
      0x2fffe,
      0x2ffff,
      0x3fffe,
      0x3ffff,
      0x4fffe,
      0x4ffff,
      0x5fffe,
      0x5ffff,
      0x6fffe,
      0x6ffff,
      0x7fffe,
      0x7ffff,
      0x8fffe,
      0x8ffff,
      0x9fffe,
      0x9ffff,
      0xafffe,
      0xaffff,
      0xbfffe,
      0xbffff,
      0xcfffe,
      0xcffff,
      0xdfffe,
      0xdffff,
      0xefffe,
      0xeffff,
      0xffffe,
      0xfffff,
      0x10fffe,
      0x10ffff
  ];
  
  var REPLACEMENT_CHARACTER = '\uFFFD';
  
  var CODE_POINTS = {
      EOF: -1,
      NULL: 0x00,
      TABULATION: 0x09,
      CARRIAGE_RETURN: 0x0d,
      LINE_FEED: 0x0a,
      FORM_FEED: 0x0c,
      SPACE: 0x20,
      EXCLAMATION_MARK: 0x21,
      QUOTATION_MARK: 0x22,
      NUMBER_SIGN: 0x23,
      AMPERSAND: 0x26,
      APOSTROPHE: 0x27,
      HYPHEN_MINUS: 0x2d,
      SOLIDUS: 0x2f,
      DIGIT_0: 0x30,
      DIGIT_9: 0x39,
      SEMICOLON: 0x3b,
      LESS_THAN_SIGN: 0x3c,
      EQUALS_SIGN: 0x3d,
      GREATER_THAN_SIGN: 0x3e,
      QUESTION_MARK: 0x3f,
      LATIN_CAPITAL_A: 0x41,
      LATIN_CAPITAL_F: 0x46,
      LATIN_CAPITAL_X: 0x58,
      LATIN_CAPITAL_Z: 0x5a,
      RIGHT_SQUARE_BRACKET: 0x5d,
      GRAVE_ACCENT: 0x60,
      LATIN_SMALL_A: 0x61,
      LATIN_SMALL_F: 0x66,
      LATIN_SMALL_X: 0x78,
      LATIN_SMALL_Z: 0x7a,
      REPLACEMENT_CHARACTER: 0xfffd
  };
  
  var CODE_POINT_SEQUENCES = {
      DASH_DASH_STRING: [0x2d, 0x2d], //--
      DOCTYPE_STRING: [0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45], //DOCTYPE
      CDATA_START_STRING: [0x5b, 0x43, 0x44, 0x41, 0x54, 0x41, 0x5b], //[CDATA[
      SCRIPT_STRING: [0x73, 0x63, 0x72, 0x69, 0x70, 0x74], //script
      PUBLIC_STRING: [0x50, 0x55, 0x42, 0x4c, 0x49, 0x43], //PUBLIC
      SYSTEM_STRING: [0x53, 0x59, 0x53, 0x54, 0x45, 0x4d] //SYSTEM
  };
  
  //Surrogates
  var isSurrogate = function(cp) {
      return cp >= 0xd800 && cp <= 0xdfff;
  };
  
  var isSurrogatePair = function(cp) {
      return cp >= 0xdc00 && cp <= 0xdfff;
  };
  
  var getSurrogatePairCodePoint = function(cp1, cp2) {
      return (cp1 - 0xd800) * 0x400 + 0x2400 + cp2;
  };
  
  //NOTE: excluding NULL and ASCII whitespace
  var isControlCodePoint = function(cp) {
      return (
          (cp !== 0x20 && cp !== 0x0a && cp !== 0x0d && cp !== 0x09 && cp !== 0x0c && cp >= 0x01 && cp <= 0x1f) ||
          (cp >= 0x7f && cp <= 0x9f)
      );
  };
  
  var isUndefinedCodePoint = function(cp) {
      return (cp >= 0xfdd0 && cp <= 0xfdef) || UNDEFINED_CODE_POINTS.indexOf(cp) > -1;
  };
  
  var unicode = {
  	REPLACEMENT_CHARACTER: REPLACEMENT_CHARACTER,
  	CODE_POINTS: CODE_POINTS,
  	CODE_POINT_SEQUENCES: CODE_POINT_SEQUENCES,
  	isSurrogate: isSurrogate,
  	isSurrogatePair: isSurrogatePair,
  	getSurrogatePairCodePoint: getSurrogatePairCodePoint,
  	isControlCodePoint: isControlCodePoint,
  	isUndefinedCodePoint: isUndefinedCodePoint
  };
  
  var errorCodes = {
      controlCharacterInInputStream: 'control-character-in-input-stream',
      noncharacterInInputStream: 'noncharacter-in-input-stream',
      surrogateInInputStream: 'surrogate-in-input-stream',
      nonVoidHtmlElementStartTagWithTrailingSolidus: 'non-void-html-element-start-tag-with-trailing-solidus',
      endTagWithAttributes: 'end-tag-with-attributes',
      endTagWithTrailingSolidus: 'end-tag-with-trailing-solidus',
      unexpectedSolidusInTag: 'unexpected-solidus-in-tag',
      unexpectedNullCharacter: 'unexpected-null-character',
      unexpectedQuestionMarkInsteadOfTagName: 'unexpected-question-mark-instead-of-tag-name',
      invalidFirstCharacterOfTagName: 'invalid-first-character-of-tag-name',
      unexpectedEqualsSignBeforeAttributeName: 'unexpected-equals-sign-before-attribute-name',
      missingEndTagName: 'missing-end-tag-name',
      unexpectedCharacterInAttributeName: 'unexpected-character-in-attribute-name',
      unknownNamedCharacterReference: 'unknown-named-character-reference',
      missingSemicolonAfterCharacterReference: 'missing-semicolon-after-character-reference',
      unexpectedCharacterAfterDoctypeSystemIdentifier: 'unexpected-character-after-doctype-system-identifier',
      unexpectedCharacterInUnquotedAttributeValue: 'unexpected-character-in-unquoted-attribute-value',
      eofBeforeTagName: 'eof-before-tag-name',
      eofInTag: 'eof-in-tag',
      missingAttributeValue: 'missing-attribute-value',
      missingWhitespaceBetweenAttributes: 'missing-whitespace-between-attributes',
      missingWhitespaceAfterDoctypePublicKeyword: 'missing-whitespace-after-doctype-public-keyword',
      missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers:
          'missing-whitespace-between-doctype-public-and-system-identifiers',
      missingWhitespaceAfterDoctypeSystemKeyword: 'missing-whitespace-after-doctype-system-keyword',
      missingQuoteBeforeDoctypePublicIdentifier: 'missing-quote-before-doctype-public-identifier',
      missingQuoteBeforeDoctypeSystemIdentifier: 'missing-quote-before-doctype-system-identifier',
      missingDoctypePublicIdentifier: 'missing-doctype-public-identifier',
      missingDoctypeSystemIdentifier: 'missing-doctype-system-identifier',
      abruptDoctypePublicIdentifier: 'abrupt-doctype-public-identifier',
      abruptDoctypeSystemIdentifier: 'abrupt-doctype-system-identifier',
      cdataInHtmlContent: 'cdata-in-html-content',
      incorrectlyOpenedComment: 'incorrectly-opened-comment',
      eofInScriptHtmlCommentLikeText: 'eof-in-script-html-comment-like-text',
      eofInDoctype: 'eof-in-doctype',
      nestedComment: 'nested-comment',
      abruptClosingOfEmptyComment: 'abrupt-closing-of-empty-comment',
      eofInComment: 'eof-in-comment',
      incorrectlyClosedComment: 'incorrectly-closed-comment',
      eofInCdata: 'eof-in-cdata',
      absenceOfDigitsInNumericCharacterReference: 'absence-of-digits-in-numeric-character-reference',
      nullCharacterReference: 'null-character-reference',
      surrogateCharacterReference: 'surrogate-character-reference',
      characterReferenceOutsideUnicodeRange: 'character-reference-outside-unicode-range',
      controlCharacterReference: 'control-character-reference',
      noncharacterCharacterReference: 'noncharacter-character-reference',
      missingWhitespaceBeforeDoctypeName: 'missing-whitespace-before-doctype-name',
      missingDoctypeName: 'missing-doctype-name',
      invalidCharacterSequenceAfterDoctypeName: 'invalid-character-sequence-after-doctype-name',
      duplicateAttribute: 'duplicate-attribute',
      nonConformingDoctype: 'non-conforming-doctype',
      missingDoctype: 'missing-doctype',
      misplacedDoctype: 'misplaced-doctype',
      endTagWithoutMatchingOpenElement: 'end-tag-without-matching-open-element',
      closingOfElementWithOpenChildElements: 'closing-of-element-with-open-child-elements',
      disallowedContentInNoscriptInHead: 'disallowed-content-in-noscript-in-head',
      openElementsLeftAfterEof: 'open-elements-left-after-eof',
      abandonedHeadElementChild: 'abandoned-head-element-child',
      misplacedStartTagForHeadElement: 'misplaced-start-tag-for-head-element',
      nestedNoscriptInHead: 'nested-noscript-in-head',
      eofInElementThatCanContainOnlyText: 'eof-in-element-that-can-contain-only-text'
  };
  
  //Aliases
  const $ = unicode.CODE_POINTS;
  
  //Const
  const DEFAULT_BUFFER_WATERLINE = 1 << 16;
  
  //Preprocessor
  //NOTE: HTML input preprocessing
  //(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#preprocessing-the-input-stream)
  class Preprocessor {
      constructor() {
          this.html = null;
  
          this.pos = -1;
          this.lastGapPos = -1;
          this.lastCharPos = -1;
  
          this.gapStack = [];
  
          this.skipNextNewLine = false;
  
          this.lastChunkWritten = false;
          this.endOfChunkHit = false;
          this.bufferWaterline = DEFAULT_BUFFER_WATERLINE;
      }
  
      _err() {
          // NOTE: err reporting is noop by default. Enabled by mixin.
      }
  
      _addGap() {
          this.gapStack.push(this.lastGapPos);
          this.lastGapPos = this.pos;
      }
  
      _processSurrogate(cp) {
          //NOTE: try to peek a surrogate pair
          if (this.pos !== this.lastCharPos) {
              const nextCp = this.html.charCodeAt(this.pos + 1);
  
              if (unicode.isSurrogatePair(nextCp)) {
                  //NOTE: we have a surrogate pair. Peek pair character and recalculate code point.
                  this.pos++;
  
                  //NOTE: add gap that should be avoided during retreat
                  this._addGap();
  
                  return unicode.getSurrogatePairCodePoint(cp, nextCp);
              }
          }
  
          //NOTE: we are at the end of a chunk, therefore we can't infer surrogate pair yet.
          else if (!this.lastChunkWritten) {
              this.endOfChunkHit = true;
              return $.EOF;
          }
  
          //NOTE: isolated surrogate
          this._err(errorCodes.surrogateInInputStream);
  
          return cp;
      }
  
      dropParsedChunk() {
          if (this.pos > this.bufferWaterline) {
              this.lastCharPos -= this.pos;
              this.html = this.html.substring(this.pos);
              this.pos = 0;
              this.lastGapPos = -1;
              this.gapStack = [];
          }
      }
  
      write(chunk, isLastChunk) {
          if (this.html) {
              this.html += chunk;
          } else {
              this.html = chunk;
          }
  
          this.lastCharPos = this.html.length - 1;
          this.endOfChunkHit = false;
          this.lastChunkWritten = isLastChunk;
      }
  
      insertHtmlAtCurrentPos(chunk) {
          this.html = this.html.substring(0, this.pos + 1) + chunk + this.html.substring(this.pos + 1, this.html.length);
  
          this.lastCharPos = this.html.length - 1;
          this.endOfChunkHit = false;
      }
  
      advance() {
          this.pos++;
  
          if (this.pos > this.lastCharPos) {
              this.endOfChunkHit = !this.lastChunkWritten;
              return $.EOF;
          }
  
          let cp = this.html.charCodeAt(this.pos);
  
          //NOTE: any U+000A LINE FEED (LF) characters that immediately follow a U+000D CARRIAGE RETURN (CR) character
          //must be ignored.
          if (this.skipNextNewLine && cp === $.LINE_FEED) {
              this.skipNextNewLine = false;
              this._addGap();
              return this.advance();
          }
  
          //NOTE: all U+000D CARRIAGE RETURN (CR) characters must be converted to U+000A LINE FEED (LF) characters
          if (cp === $.CARRIAGE_RETURN) {
              this.skipNextNewLine = true;
              return $.LINE_FEED;
          }
  
          this.skipNextNewLine = false;
  
          if (unicode.isSurrogate(cp)) {
              cp = this._processSurrogate(cp);
          }
  
          //OPTIMIZATION: first check if code point is in the common allowed
          //range (ASCII alphanumeric, whitespaces, big chunk of BMP)
          //before going into detailed performance cost validation.
          const isCommonValidRange =
              (cp > 0x1f && cp < 0x7f) || cp === $.LINE_FEED || cp === $.CARRIAGE_RETURN || (cp > 0x9f && cp < 0xfdd0);
  
          if (!isCommonValidRange) {
              this._checkForProblematicCharacters(cp);
          }
  
          return cp;
      }
  
      _checkForProblematicCharacters(cp) {
          if (unicode.isControlCodePoint(cp)) {
              this._err(errorCodes.controlCharacterInInputStream);
          } else if (unicode.isUndefinedCodePoint(cp)) {
              this._err(errorCodes.noncharacterInInputStream);
          }
      }
  
      retreat() {
          if (this.pos === this.lastGapPos) {
              this.lastGapPos = this.gapStack.pop();
              this.pos--;
          }
  
          this.pos--;
      }
  }
  
  var preprocessor = Preprocessor;
  
  //NOTE: this file contains auto-generated array mapped radix tree that is used for the named entity references consumption
  //(details: https://github.com/inikulin/parse5/tree/master/scripts/generate-named-entity-data/README.md)
  var namedEntityData = new Uint16Array([4,52,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,106,303,412,810,1432,1701,1796,1987,2114,2360,2420,2484,3170,3251,4140,4393,4575,4610,5106,5512,5728,6117,6274,6315,6345,6427,6516,7002,7910,8733,9323,9870,10170,10631,10893,11318,11386,11467,12773,13092,14474,14922,15448,15542,16419,17666,18166,18611,19004,19095,19298,19397,4,16,69,77,97,98,99,102,103,108,109,110,111,112,114,115,116,117,140,150,158,169,176,194,199,210,216,222,226,242,256,266,283,294,108,105,103,5,198,1,59,148,1,198,80,5,38,1,59,156,1,38,99,117,116,101,5,193,1,59,167,1,193,114,101,118,101,59,1,258,4,2,105,121,182,191,114,99,5,194,1,59,189,1,194,59,1,1040,114,59,3,55349,56580,114,97,118,101,5,192,1,59,208,1,192,112,104,97,59,1,913,97,99,114,59,1,256,100,59,1,10835,4,2,103,112,232,237,111,110,59,1,260,102,59,3,55349,56632,112,108,121,70,117,110,99,116,105,111,110,59,1,8289,105,110,103,5,197,1,59,264,1,197,4,2,99,115,272,277,114,59,3,55349,56476,105,103,110,59,1,8788,105,108,100,101,5,195,1,59,292,1,195,109,108,5,196,1,59,301,1,196,4,8,97,99,101,102,111,114,115,117,321,350,354,383,388,394,400,405,4,2,99,114,327,336,107,115,108,97,115,104,59,1,8726,4,2,118,119,342,345,59,1,10983,101,100,59,1,8966,121,59,1,1041,4,3,99,114,116,362,369,379,97,117,115,101,59,1,8757,110,111,117,108,108,105,115,59,1,8492,97,59,1,914,114,59,3,55349,56581,112,102,59,3,55349,56633,101,118,101,59,1,728,99,114,59,1,8492,109,112,101,113,59,1,8782,4,14,72,79,97,99,100,101,102,104,105,108,111,114,115,117,442,447,456,504,542,547,569,573,577,616,678,784,790,796,99,121,59,1,1063,80,89,5,169,1,59,454,1,169,4,3,99,112,121,464,470,497,117,116,101,59,1,262,4,2,59,105,476,478,1,8914,116,97,108,68,105,102,102,101,114,101,110,116,105,97,108,68,59,1,8517,108,101,121,115,59,1,8493,4,4,97,101,105,111,514,520,530,535,114,111,110,59,1,268,100,105,108,5,199,1,59,528,1,199,114,99,59,1,264,110,105,110,116,59,1,8752,111,116,59,1,266,4,2,100,110,553,560,105,108,108,97,59,1,184,116,101,114,68,111,116,59,1,183,114,59,1,8493,105,59,1,935,114,99,108,101,4,4,68,77,80,84,591,596,603,609,111,116,59,1,8857,105,110,117,115,59,1,8854,108,117,115,59,1,8853,105,109,101,115,59,1,8855,111,4,2,99,115,623,646,107,119,105,115,101,67,111,110,116,111,117,114,73,110,116,101,103,114,97,108,59,1,8754,101,67,117,114,108,121,4,2,68,81,658,671,111,117,98,108,101,81,117,111,116,101,59,1,8221,117,111,116,101,59,1,8217,4,4,108,110,112,117,688,701,736,753,111,110,4,2,59,101,696,698,1,8759,59,1,10868,4,3,103,105,116,709,717,722,114,117,101,110,116,59,1,8801,110,116,59,1,8751,111,117,114,73,110,116,101,103,114,97,108,59,1,8750,4,2,102,114,742,745,59,1,8450,111,100,117,99,116,59,1,8720,110,116,101,114,67,108,111,99,107,119,105,115,101,67,111,110,116,111,117,114,73,110,116,101,103,114,97,108,59,1,8755,111,115,115,59,1,10799,99,114,59,3,55349,56478,112,4,2,59,67,803,805,1,8915,97,112,59,1,8781,4,11,68,74,83,90,97,99,101,102,105,111,115,834,850,855,860,865,888,903,916,921,1011,1415,4,2,59,111,840,842,1,8517,116,114,97,104,100,59,1,10513,99,121,59,1,1026,99,121,59,1,1029,99,121,59,1,1039,4,3,103,114,115,873,879,883,103,101,114,59,1,8225,114,59,1,8609,104,118,59,1,10980,4,2,97,121,894,900,114,111,110,59,1,270,59,1,1044,108,4,2,59,116,910,912,1,8711,97,59,1,916,114,59,3,55349,56583,4,2,97,102,927,998,4,2,99,109,933,992,114,105,116,105,99,97,108,4,4,65,68,71,84,950,957,978,985,99,117,116,101,59,1,180,111,4,2,116,117,964,967,59,1,729,98,108,101,65,99,117,116,101,59,1,733,114,97,118,101,59,1,96,105,108,100,101,59,1,732,111,110,100,59,1,8900,102,101,114,101,110,116,105,97,108,68,59,1,8518,4,4,112,116,117,119,1021,1026,1048,1249,102,59,3,55349,56635,4,3,59,68,69,1034,1036,1041,1,168,111,116,59,1,8412,113,117,97,108,59,1,8784,98,108,101,4,6,67,68,76,82,85,86,1065,1082,1101,1189,1211,1236,111,110,116,111,117,114,73,110,116,101,103,114,97,108,59,1,8751,111,4,2,116,119,1089,1092,59,1,168,110,65,114,114,111,119,59,1,8659,4,2,101,111,1107,1141,102,116,4,3,65,82,84,1117,1124,1136,114,114,111,119,59,1,8656,105,103,104,116,65,114,114,111,119,59,1,8660,101,101,59,1,10980,110,103,4,2,76,82,1149,1177,101,102,116,4,2,65,82,1158,1165,114,114,111,119,59,1,10232,105,103,104,116,65,114,114,111,119,59,1,10234,105,103,104,116,65,114,114,111,119,59,1,10233,105,103,104,116,4,2,65,84,1199,1206,114,114,111,119,59,1,8658,101,101,59,1,8872,112,4,2,65,68,1218,1225,114,114,111,119,59,1,8657,111,119,110,65,114,114,111,119,59,1,8661,101,114,116,105,99,97,108,66,97,114,59,1,8741,110,4,6,65,66,76,82,84,97,1264,1292,1299,1352,1391,1408,114,114,111,119,4,3,59,66,85,1276,1278,1283,1,8595,97,114,59,1,10515,112,65,114,114,111,119,59,1,8693,114,101,118,101,59,1,785,101,102,116,4,3,82,84,86,1310,1323,1334,105,103,104,116,86,101,99,116,111,114,59,1,10576,101,101,86,101,99,116,111,114,59,1,10590,101,99,116,111,114,4,2,59,66,1345,1347,1,8637,97,114,59,1,10582,105,103,104,116,4,2,84,86,1362,1373,101,101,86,101,99,116,111,114,59,1,10591,101,99,116,111,114,4,2,59,66,1384,1386,1,8641,97,114,59,1,10583,101,101,4,2,59,65,1399,1401,1,8868,114,114,111,119,59,1,8615,114,114,111,119,59,1,8659,4,2,99,116,1421,1426,114,59,3,55349,56479,114,111,107,59,1,272,4,16,78,84,97,99,100,102,103,108,109,111,112,113,115,116,117,120,1466,1470,1478,1489,1515,1520,1525,1536,1544,1593,1609,1617,1650,1664,1668,1677,71,59,1,330,72,5,208,1,59,1476,1,208,99,117,116,101,5,201,1,59,1487,1,201,4,3,97,105,121,1497,1503,1512,114,111,110,59,1,282,114,99,5,202,1,59,1510,1,202,59,1,1069,111,116,59,1,278,114,59,3,55349,56584,114,97,118,101,5,200,1,59,1534,1,200,101,109,101,110,116,59,1,8712,4,2,97,112,1550,1555,99,114,59,1,274,116,121,4,2,83,86,1563,1576,109,97,108,108,83,113,117,97,114,101,59,1,9723,101,114,121,83,109,97,108,108,83,113,117,97,114,101,59,1,9643,4,2,103,112,1599,1604,111,110,59,1,280,102,59,3,55349,56636,115,105,108,111,110,59,1,917,117,4,2,97,105,1624,1640,108,4,2,59,84,1631,1633,1,10869,105,108,100,101,59,1,8770,108,105,98,114,105,117,109,59,1,8652,4,2,99,105,1656,1660,114,59,1,8496,109,59,1,10867,97,59,1,919,109,108,5,203,1,59,1675,1,203,4,2,105,112,1683,1689,115,116,115,59,1,8707,111,110,101,110,116,105,97,108,69,59,1,8519,4,5,99,102,105,111,115,1713,1717,1722,1762,1791,121,59,1,1060,114,59,3,55349,56585,108,108,101,100,4,2,83,86,1732,1745,109,97,108,108,83,113,117,97,114,101,59,1,9724,101,114,121,83,109,97,108,108,83,113,117,97,114,101,59,1,9642,4,3,112,114,117,1770,1775,1781,102,59,3,55349,56637,65,108,108,59,1,8704,114,105,101,114,116,114,102,59,1,8497,99,114,59,1,8497,4,12,74,84,97,98,99,100,102,103,111,114,115,116,1822,1827,1834,1848,1855,1877,1882,1887,1890,1896,1978,1984,99,121,59,1,1027,5,62,1,59,1832,1,62,109,109,97,4,2,59,100,1843,1845,1,915,59,1,988,114,101,118,101,59,1,286,4,3,101,105,121,1863,1869,1874,100,105,108,59,1,290,114,99,59,1,284,59,1,1043,111,116,59,1,288,114,59,3,55349,56586,59,1,8921,112,102,59,3,55349,56638,101,97,116,101,114,4,6,69,70,71,76,83,84,1915,1933,1944,1953,1959,1971,113,117,97,108,4,2,59,76,1925,1927,1,8805,101,115,115,59,1,8923,117,108,108,69,113,117,97,108,59,1,8807,114,101,97,116,101,114,59,1,10914,101,115,115,59,1,8823,108,97,110,116,69,113,117,97,108,59,1,10878,105,108,100,101,59,1,8819,99,114,59,3,55349,56482,59,1,8811,4,8,65,97,99,102,105,111,115,117,2005,2012,2026,2032,2036,2049,2073,2089,82,68,99,121,59,1,1066,4,2,99,116,2018,2023,101,107,59,1,711,59,1,94,105,114,99,59,1,292,114,59,1,8460,108,98,101,114,116,83,112,97,99,101,59,1,8459,4,2,112,114,2055,2059,102,59,1,8461,105,122,111,110,116,97,108,76,105,110,101,59,1,9472,4,2,99,116,2079,2083,114,59,1,8459,114,111,107,59,1,294,109,112,4,2,68,69,2097,2107,111,119,110,72,117,109,112,59,1,8782,113,117,97,108,59,1,8783,4,14,69,74,79,97,99,100,102,103,109,110,111,115,116,117,2144,2149,2155,2160,2171,2189,2194,2198,2209,2245,2307,2329,2334,2341,99,121,59,1,1045,108,105,103,59,1,306,99,121,59,1,1025,99,117,116,101,5,205,1,59,2169,1,205,4,2,105,121,2177,2186,114,99,5,206,1,59,2184,1,206,59,1,1048,111,116,59,1,304,114,59,1,8465,114,97,118,101,5,204,1,59,2207,1,204,4,3,59,97,112,2217,2219,2238,1,8465,4,2,99,103,2225,2229,114,59,1,298,105,110,97,114,121,73,59,1,8520,108,105,101,115,59,1,8658,4,2,116,118,2251,2281,4,2,59,101,2257,2259,1,8748,4,2,103,114,2265,2271,114,97,108,59,1,8747,115,101,99,116,105,111,110,59,1,8898,105,115,105,98,108,101,4,2,67,84,2293,2300,111,109,109,97,59,1,8291,105,109,101,115,59,1,8290,4,3,103,112,116,2315,2320,2325,111,110,59,1,302,102,59,3,55349,56640,97,59,1,921,99,114,59,1,8464,105,108,100,101,59,1,296,4,2,107,109,2347,2352,99,121,59,1,1030,108,5,207,1,59,2358,1,207,4,5,99,102,111,115,117,2372,2386,2391,2397,2414,4,2,105,121,2378,2383,114,99,59,1,308,59,1,1049,114,59,3,55349,56589,112,102,59,3,55349,56641,4,2,99,101,2403,2408,114,59,3,55349,56485,114,99,121,59,1,1032,107,99,121,59,1,1028,4,7,72,74,97,99,102,111,115,2436,2441,2446,2452,2467,2472,2478,99,121,59,1,1061,99,121,59,1,1036,112,112,97,59,1,922,4,2,101,121,2458,2464,100,105,108,59,1,310,59,1,1050,114,59,3,55349,56590,112,102,59,3,55349,56642,99,114,59,3,55349,56486,4,11,74,84,97,99,101,102,108,109,111,115,116,2508,2513,2520,2562,2585,2981,2986,3004,3011,3146,3167,99,121,59,1,1033,5,60,1,59,2518,1,60,4,5,99,109,110,112,114,2532,2538,2544,2548,2558,117,116,101,59,1,313,98,100,97,59,1,923,103,59,1,10218,108,97,99,101,116,114,102,59,1,8466,114,59,1,8606,4,3,97,101,121,2570,2576,2582,114,111,110,59,1,317,100,105,108,59,1,315,59,1,1051,4,2,102,115,2591,2907,116,4,10,65,67,68,70,82,84,85,86,97,114,2614,2663,2672,2728,2735,2760,2820,2870,2888,2895,4,2,110,114,2620,2633,103,108,101,66,114,97,99,107,101,116,59,1,10216,114,111,119,4,3,59,66,82,2644,2646,2651,1,8592,97,114,59,1,8676,105,103,104,116,65,114,114,111,119,59,1,8646,101,105,108,105,110,103,59,1,8968,111,4,2,117,119,2679,2692,98,108,101,66,114,97,99,107,101,116,59,1,10214,110,4,2,84,86,2699,2710,101,101,86,101,99,116,111,114,59,1,10593,101,99,116,111,114,4,2,59,66,2721,2723,1,8643,97,114,59,1,10585,108,111,111,114,59,1,8970,105,103,104,116,4,2,65,86,2745,2752,114,114,111,119,59,1,8596,101,99,116,111,114,59,1,10574,4,2,101,114,2766,2792,101,4,3,59,65,86,2775,2777,2784,1,8867,114,114,111,119,59,1,8612,101,99,116,111,114,59,1,10586,105,97,110,103,108,101,4,3,59,66,69,2806,2808,2813,1,8882,97,114,59,1,10703,113,117,97,108,59,1,8884,112,4,3,68,84,86,2829,2841,2852,111,119,110,86,101,99,116,111,114,59,1,10577,101,101,86,101,99,116,111,114,59,1,10592,101,99,116,111,114,4,2,59,66,2863,2865,1,8639,97,114,59,1,10584,101,99,116,111,114,4,2,59,66,2881,2883,1,8636,97,114,59,1,10578,114,114,111,119,59,1,8656,105,103,104,116,97,114,114,111,119,59,1,8660,115,4,6,69,70,71,76,83,84,2922,2936,2947,2956,2962,2974,113,117,97,108,71,114,101,97,116,101,114,59,1,8922,117,108,108,69,113,117,97,108,59,1,8806,114,101,97,116,101,114,59,1,8822,101,115,115,59,1,10913,108,97,110,116,69,113,117,97,108,59,1,10877,105,108,100,101,59,1,8818,114,59,3,55349,56591,4,2,59,101,2992,2994,1,8920,102,116,97,114,114,111,119,59,1,8666,105,100,111,116,59,1,319,4,3,110,112,119,3019,3110,3115,103,4,4,76,82,108,114,3030,3058,3070,3098,101,102,116,4,2,65,82,3039,3046,114,114,111,119,59,1,10229,105,103,104,116,65,114,114,111,119,59,1,10231,105,103,104,116,65,114,114,111,119,59,1,10230,101,102,116,4,2,97,114,3079,3086,114,114,111,119,59,1,10232,105,103,104,116,97,114,114,111,119,59,1,10234,105,103,104,116,97,114,114,111,119,59,1,10233,102,59,3,55349,56643,101,114,4,2,76,82,3123,3134,101,102,116,65,114,114,111,119,59,1,8601,105,103,104,116,65,114,114,111,119,59,1,8600,4,3,99,104,116,3154,3158,3161,114,59,1,8466,59,1,8624,114,111,107,59,1,321,59,1,8810,4,8,97,99,101,102,105,111,115,117,3188,3192,3196,3222,3227,3237,3243,3248,112,59,1,10501,121,59,1,1052,4,2,100,108,3202,3213,105,117,109,83,112,97,99,101,59,1,8287,108,105,110,116,114,102,59,1,8499,114,59,3,55349,56592,110,117,115,80,108,117,115,59,1,8723,112,102,59,3,55349,56644,99,114,59,1,8499,59,1,924,4,9,74,97,99,101,102,111,115,116,117,3271,3276,3283,3306,3422,3427,4120,4126,4137,99,121,59,1,1034,99,117,116,101,59,1,323,4,3,97,101,121,3291,3297,3303,114,111,110,59,1,327,100,105,108,59,1,325,59,1,1053,4,3,103,115,119,3314,3380,3415,97,116,105,118,101,4,3,77,84,86,3327,3340,3365,101,100,105,117,109,83,112,97,99,101,59,1,8203,104,105,4,2,99,110,3348,3357,107,83,112,97,99,101,59,1,8203,83,112,97,99,101,59,1,8203,101,114,121,84,104,105,110,83,112,97,99,101,59,1,8203,116,101,100,4,2,71,76,3389,3405,114,101,97,116,101,114,71,114,101,97,116,101,114,59,1,8811,101,115,115,76,101,115,115,59,1,8810,76,105,110,101,59,1,10,114,59,3,55349,56593,4,4,66,110,112,116,3437,3444,3460,3464,114,101,97,107,59,1,8288,66,114,101,97,107,105,110,103,83,112,97,99,101,59,1,160,102,59,1,8469,4,13,59,67,68,69,71,72,76,78,80,82,83,84,86,3492,3494,3517,3536,3578,3657,3685,3784,3823,3860,3915,4066,4107,1,10988,4,2,111,117,3500,3510,110,103,114,117,101,110,116,59,1,8802,112,67,97,112,59,1,8813,111,117,98,108,101,86,101,114,116,105,99,97,108,66,97,114,59,1,8742,4,3,108,113,120,3544,3552,3571,101,109,101,110,116,59,1,8713,117,97,108,4,2,59,84,3561,3563,1,8800,105,108,100,101,59,3,8770,824,105,115,116,115,59,1,8708,114,101,97,116,101,114,4,7,59,69,70,71,76,83,84,3600,3602,3609,3621,3631,3637,3650,1,8815,113,117,97,108,59,1,8817,117,108,108,69,113,117,97,108,59,3,8807,824,114,101,97,116,101,114,59,3,8811,824,101,115,115,59,1,8825,108,97,110,116,69,113,117,97,108,59,3,10878,824,105,108,100,101,59,1,8821,117,109,112,4,2,68,69,3666,3677,111,119,110,72,117,109,112,59,3,8782,824,113,117,97,108,59,3,8783,824,101,4,2,102,115,3692,3724,116,84,114,105,97,110,103,108,101,4,3,59,66,69,3709,3711,3717,1,8938,97,114,59,3,10703,824,113,117,97,108,59,1,8940,115,4,6,59,69,71,76,83,84,3739,3741,3748,3757,3764,3777,1,8814,113,117,97,108,59,1,8816,114,101,97,116,101,114,59,1,8824,101,115,115,59,3,8810,824,108,97,110,116,69,113,117,97,108,59,3,10877,824,105,108,100,101,59,1,8820,101,115,116,101,100,4,2,71,76,3795,3812,114,101,97,116,101,114,71,114,101,97,116,101,114,59,3,10914,824,101,115,115,76,101,115,115,59,3,10913,824,114,101,99,101,100,101,115,4,3,59,69,83,3838,3840,3848,1,8832,113,117,97,108,59,3,10927,824,108,97,110,116,69,113,117,97,108,59,1,8928,4,2,101,105,3866,3881,118,101,114,115,101,69,108,101,109,101,110,116,59,1,8716,103,104,116,84,114,105,97,110,103,108,101,4,3,59,66,69,3900,3902,3908,1,8939,97,114,59,3,10704,824,113,117,97,108,59,1,8941,4,2,113,117,3921,3973,117,97,114,101,83,117,4,2,98,112,3933,3952,115,101,116,4,2,59,69,3942,3945,3,8847,824,113,117,97,108,59,1,8930,101,114,115,101,116,4,2,59,69,3963,3966,3,8848,824,113,117,97,108,59,1,8931,4,3,98,99,112,3981,4000,4045,115,101,116,4,2,59,69,3990,3993,3,8834,8402,113,117,97,108,59,1,8840,99,101,101,100,115,4,4,59,69,83,84,4015,4017,4025,4037,1,8833,113,117,97,108,59,3,10928,824,108,97,110,116,69,113,117,97,108,59,1,8929,105,108,100,101,59,3,8831,824,101,114,115,101,116,4,2,59,69,4056,4059,3,8835,8402,113,117,97,108,59,1,8841,105,108,100,101,4,4,59,69,70,84,4080,4082,4089,4100,1,8769,113,117,97,108,59,1,8772,117,108,108,69,113,117,97,108,59,1,8775,105,108,100,101,59,1,8777,101,114,116,105,99,97,108,66,97,114,59,1,8740,99,114,59,3,55349,56489,105,108,100,101,5,209,1,59,4135,1,209,59,1,925,4,14,69,97,99,100,102,103,109,111,112,114,115,116,117,118,4170,4176,4187,4205,4212,4217,4228,4253,4259,4292,4295,4316,4337,4346,108,105,103,59,1,338,99,117,116,101,5,211,1,59,4185,1,211,4,2,105,121,4193,4202,114,99,5,212,1,59,4200,1,212,59,1,1054,98,108,97,99,59,1,336,114,59,3,55349,56594,114,97,118,101,5,210,1,59,4226,1,210,4,3,97,101,105,4236,4241,4246,99,114,59,1,332,103,97,59,1,937,99,114,111,110,59,1,927,112,102,59,3,55349,56646,101,110,67,117,114,108,121,4,2,68,81,4272,4285,111,117,98,108,101,81,117,111,116,101,59,1,8220,117,111,116,101,59,1,8216,59,1,10836,4,2,99,108,4301,4306,114,59,3,55349,56490,97,115,104,5,216,1,59,4314,1,216,105,4,2,108,109,4323,4332,100,101,5,213,1,59,4330,1,213,101,115,59,1,10807,109,108,5,214,1,59,4344,1,214,101,114,4,2,66,80,4354,4380,4,2,97,114,4360,4364,114,59,1,8254,97,99,4,2,101,107,4372,4375,59,1,9182,101,116,59,1,9140,97,114,101,110,116,104,101,115,105,115,59,1,9180,4,9,97,99,102,104,105,108,111,114,115,4413,4422,4426,4431,4435,4438,4448,4471,4561,114,116,105,97,108,68,59,1,8706,121,59,1,1055,114,59,3,55349,56595,105,59,1,934,59,1,928,117,115,77,105,110,117,115,59,1,177,4,2,105,112,4454,4467,110,99,97,114,101,112,108,97,110,101,59,1,8460,102,59,1,8473,4,4,59,101,105,111,4481,4483,4526,4531,1,10939,99,101,100,101,115,4,4,59,69,83,84,4498,4500,4507,4519,1,8826,113,117,97,108,59,1,10927,108,97,110,116,69,113,117,97,108,59,1,8828,105,108,100,101,59,1,8830,109,101,59,1,8243,4,2,100,112,4537,4543,117,99,116,59,1,8719,111,114,116,105,111,110,4,2,59,97,4555,4557,1,8759,108,59,1,8733,4,2,99,105,4567,4572,114,59,3,55349,56491,59,1,936,4,4,85,102,111,115,4585,4594,4599,4604,79,84,5,34,1,59,4592,1,34,114,59,3,55349,56596,112,102,59,1,8474,99,114,59,3,55349,56492,4,12,66,69,97,99,101,102,104,105,111,114,115,117,4636,4642,4650,4681,4704,4763,4767,4771,5047,5069,5081,5094,97,114,114,59,1,10512,71,5,174,1,59,4648,1,174,4,3,99,110,114,4658,4664,4668,117,116,101,59,1,340,103,59,1,10219,114,4,2,59,116,4675,4677,1,8608,108,59,1,10518,4,3,97,101,121,4689,4695,4701,114,111,110,59,1,344,100,105,108,59,1,342,59,1,1056,4,2,59,118,4710,4712,1,8476,101,114,115,101,4,2,69,85,4722,4748,4,2,108,113,4728,4736,101,109,101,110,116,59,1,8715,117,105,108,105,98,114,105,117,109,59,1,8651,112,69,113,117,105,108,105,98,114,105,117,109,59,1,10607,114,59,1,8476,111,59,1,929,103,104,116,4,8,65,67,68,70,84,85,86,97,4792,4840,4849,4905,4912,4972,5022,5040,4,2,110,114,4798,4811,103,108,101,66,114,97,99,107,101,116,59,1,10217,114,111,119,4,3,59,66,76,4822,4824,4829,1,8594,97,114,59,1,8677,101,102,116,65,114,114,111,119,59,1,8644,101,105,108,105,110,103,59,1,8969,111,4,2,117,119,4856,4869,98,108,101,66,114,97,99,107,101,116,59,1,10215,110,4,2,84,86,4876,4887,101,101,86,101,99,116,111,114,59,1,10589,101,99,116,111,114,4,2,59,66,4898,4900,1,8642,97,114,59,1,10581,108,111,111,114,59,1,8971,4,2,101,114,4918,4944,101,4,3,59,65,86,4927,4929,4936,1,8866,114,114,111,119,59,1,8614,101,99,116,111,114,59,1,10587,105,97,110,103,108,101,4,3,59,66,69,4958,4960,4965,1,8883,97,114,59,1,10704,113,117,97,108,59,1,8885,112,4,3,68,84,86,4981,4993,5004,111,119,110,86,101,99,116,111,114,59,1,10575,101,101,86,101,99,116,111,114,59,1,10588,101,99,116,111,114,4,2,59,66,5015,5017,1,8638,97,114,59,1,10580,101,99,116,111,114,4,2,59,66,5033,5035,1,8640,97,114,59,1,10579,114,114,111,119,59,1,8658,4,2,112,117,5053,5057,102,59,1,8477,110,100,73,109,112,108,105,101,115,59,1,10608,105,103,104,116,97,114,114,111,119,59,1,8667,4,2,99,104,5087,5091,114,59,1,8475,59,1,8625,108,101,68,101,108,97,121,101,100,59,1,10740,4,13,72,79,97,99,102,104,105,109,111,113,115,116,117,5134,5150,5157,5164,5198,5203,5259,5265,5277,5283,5374,5380,5385,4,2,67,99,5140,5146,72,99,121,59,1,1065,121,59,1,1064,70,84,99,121,59,1,1068,99,117,116,101,59,1,346,4,5,59,97,101,105,121,5176,5178,5184,5190,5195,1,10940,114,111,110,59,1,352,100,105,108,59,1,350,114,99,59,1,348,59,1,1057,114,59,3,55349,56598,111,114,116,4,4,68,76,82,85,5216,5227,5238,5250,111,119,110,65,114,114,111,119,59,1,8595,101,102,116,65,114,114,111,119,59,1,8592,105,103,104,116,65,114,114,111,119,59,1,8594,112,65,114,114,111,119,59,1,8593,103,109,97,59,1,931,97,108,108,67,105,114,99,108,101,59,1,8728,112,102,59,3,55349,56650,4,2,114,117,5289,5293,116,59,1,8730,97,114,101,4,4,59,73,83,85,5306,5308,5322,5367,1,9633,110,116,101,114,115,101,99,116,105,111,110,59,1,8851,117,4,2,98,112,5329,5347,115,101,116,4,2,59,69,5338,5340,1,8847,113,117,97,108,59,1,8849,101,114,115,101,116,4,2,59,69,5358,5360,1,8848,113,117,97,108,59,1,8850,110,105,111,110,59,1,8852,99,114,59,3,55349,56494,97,114,59,1,8902,4,4,98,99,109,112,5395,5420,5475,5478,4,2,59,115,5401,5403,1,8912,101,116,4,2,59,69,5411,5413,1,8912,113,117,97,108,59,1,8838,4,2,99,104,5426,5468,101,101,100,115,4,4,59,69,83,84,5440,5442,5449,5461,1,8827,113,117,97,108,59,1,10928,108,97,110,116,69,113,117,97,108,59,1,8829,105,108,100,101,59,1,8831,84,104,97,116,59,1,8715,59,1,8721,4,3,59,101,115,5486,5488,5507,1,8913,114,115,101,116,4,2,59,69,5498,5500,1,8835,113,117,97,108,59,1,8839,101,116,59,1,8913,4,11,72,82,83,97,99,102,104,105,111,114,115,5536,5546,5552,5567,5579,5602,5607,5655,5695,5701,5711,79,82,78,5,222,1,59,5544,1,222,65,68,69,59,1,8482,4,2,72,99,5558,5563,99,121,59,1,1035,121,59,1,1062,4,2,98,117,5573,5576,59,1,9,59,1,932,4,3,97,101,121,5587,5593,5599,114,111,110,59,1,356,100,105,108,59,1,354,59,1,1058,114,59,3,55349,56599,4,2,101,105,5613,5631,4,2,114,116,5619,5627,101,102,111,114,101,59,1,8756,97,59,1,920,4,2,99,110,5637,5647,107,83,112,97,99,101,59,3,8287,8202,83,112,97,99,101,59,1,8201,108,100,101,4,4,59,69,70,84,5668,5670,5677,5688,1,8764,113,117,97,108,59,1,8771,117,108,108,69,113,117,97,108,59,1,8773,105,108,100,101,59,1,8776,112,102,59,3,55349,56651,105,112,108,101,68,111,116,59,1,8411,4,2,99,116,5717,5722,114,59,3,55349,56495,114,111,107,59,1,358,4,14,97,98,99,100,102,103,109,110,111,112,114,115,116,117,5758,5789,5805,5823,5830,5835,5846,5852,5921,5937,6089,6095,6101,6108,4,2,99,114,5764,5774,117,116,101,5,218,1,59,5772,1,218,114,4,2,59,111,5781,5783,1,8607,99,105,114,59,1,10569,114,4,2,99,101,5796,5800,121,59,1,1038,118,101,59,1,364,4,2,105,121,5811,5820,114,99,5,219,1,59,5818,1,219,59,1,1059,98,108,97,99,59,1,368,114,59,3,55349,56600,114,97,118,101,5,217,1,59,5844,1,217,97,99,114,59,1,362,4,2,100,105,5858,5905,101,114,4,2,66,80,5866,5892,4,2,97,114,5872,5876,114,59,1,95,97,99,4,2,101,107,5884,5887,59,1,9183,101,116,59,1,9141,97,114,101,110,116,104,101,115,105,115,59,1,9181,111,110,4,2,59,80,5913,5915,1,8899,108,117,115,59,1,8846,4,2,103,112,5927,5932,111,110,59,1,370,102,59,3,55349,56652,4,8,65,68,69,84,97,100,112,115,5955,5985,5996,6009,6026,6033,6044,6075,114,114,111,119,4,3,59,66,68,5967,5969,5974,1,8593,97,114,59,1,10514,111,119,110,65,114,114,111,119,59,1,8645,111,119,110,65,114,114,111,119,59,1,8597,113,117,105,108,105,98,114,105,117,109,59,1,10606,101,101,4,2,59,65,6017,6019,1,8869,114,114,111,119,59,1,8613,114,114,111,119,59,1,8657,111,119,110,97,114,114,111,119,59,1,8661,101,114,4,2,76,82,6052,6063,101,102,116,65,114,114,111,119,59,1,8598,105,103,104,116,65,114,114,111,119,59,1,8599,105,4,2,59,108,6082,6084,1,978,111,110,59,1,933,105,110,103,59,1,366,99,114,59,3,55349,56496,105,108,100,101,59,1,360,109,108,5,220,1,59,6115,1,220,4,9,68,98,99,100,101,102,111,115,118,6137,6143,6148,6152,6166,6250,6255,6261,6267,97,115,104,59,1,8875,97,114,59,1,10987,121,59,1,1042,97,115,104,4,2,59,108,6161,6163,1,8873,59,1,10982,4,2,101,114,6172,6175,59,1,8897,4,3,98,116,121,6183,6188,6238,97,114,59,1,8214,4,2,59,105,6194,6196,1,8214,99,97,108,4,4,66,76,83,84,6209,6214,6220,6231,97,114,59,1,8739,105,110,101,59,1,124,101,112,97,114,97,116,111,114,59,1,10072,105,108,100,101,59,1,8768,84,104,105,110,83,112,97,99,101,59,1,8202,114,59,3,55349,56601,112,102,59,3,55349,56653,99,114,59,3,55349,56497,100,97,115,104,59,1,8874,4,5,99,101,102,111,115,6286,6292,6298,6303,6309,105,114,99,59,1,372,100,103,101,59,1,8896,114,59,3,55349,56602,112,102,59,3,55349,56654,99,114,59,3,55349,56498,4,4,102,105,111,115,6325,6330,6333,6339,114,59,3,55349,56603,59,1,926,112,102,59,3,55349,56655,99,114,59,3,55349,56499,4,9,65,73,85,97,99,102,111,115,117,6365,6370,6375,6380,6391,6405,6410,6416,6422,99,121,59,1,1071,99,121,59,1,1031,99,121,59,1,1070,99,117,116,101,5,221,1,59,6389,1,221,4,2,105,121,6397,6402,114,99,59,1,374,59,1,1067,114,59,3,55349,56604,112,102,59,3,55349,56656,99,114,59,3,55349,56500,109,108,59,1,376,4,8,72,97,99,100,101,102,111,115,6445,6450,6457,6472,6477,6501,6505,6510,99,121,59,1,1046,99,117,116,101,59,1,377,4,2,97,121,6463,6469,114,111,110,59,1,381,59,1,1047,111,116,59,1,379,4,2,114,116,6483,6497,111,87,105,100,116,104,83,112,97,99,101,59,1,8203,97,59,1,918,114,59,1,8488,112,102,59,1,8484,99,114,59,3,55349,56501,4,16,97,98,99,101,102,103,108,109,110,111,112,114,115,116,117,119,6550,6561,6568,6612,6622,6634,6645,6672,6699,6854,6870,6923,6933,6963,6974,6983,99,117,116,101,5,225,1,59,6559,1,225,114,101,118,101,59,1,259,4,6,59,69,100,105,117,121,6582,6584,6588,6591,6600,6609,1,8766,59,3,8766,819,59,1,8767,114,99,5,226,1,59,6598,1,226,116,101,5,180,1,59,6607,1,180,59,1,1072,108,105,103,5,230,1,59,6620,1,230,4,2,59,114,6628,6630,1,8289,59,3,55349,56606,114,97,118,101,5,224,1,59,6643,1,224,4,2,101,112,6651,6667,4,2,102,112,6657,6663,115,121,109,59,1,8501,104,59,1,8501,104,97,59,1,945,4,2,97,112,6678,6692,4,2,99,108,6684,6688,114,59,1,257,103,59,1,10815,5,38,1,59,6697,1,38,4,2,100,103,6705,6737,4,5,59,97,100,115,118,6717,6719,6724,6727,6734,1,8743,110,100,59,1,10837,59,1,10844,108,111,112,101,59,1,10840,59,1,10842,4,7,59,101,108,109,114,115,122,6753,6755,6758,6762,6814,6835,6848,1,8736,59,1,10660,101,59,1,8736,115,100,4,2,59,97,6770,6772,1,8737,4,8,97,98,99,100,101,102,103,104,6790,6793,6796,6799,6802,6805,6808,6811,59,1,10664,59,1,10665,59,1,10666,59,1,10667,59,1,10668,59,1,10669,59,1,10670,59,1,10671,116,4,2,59,118,6821,6823,1,8735,98,4,2,59,100,6830,6832,1,8894,59,1,10653,4,2,112,116,6841,6845,104,59,1,8738,59,1,197,97,114,114,59,1,9084,4,2,103,112,6860,6865,111,110,59,1,261,102,59,3,55349,56658,4,7,59,69,97,101,105,111,112,6886,6888,6891,6897,6900,6904,6908,1,8776,59,1,10864,99,105,114,59,1,10863,59,1,8778,100,59,1,8779,115,59,1,39,114,111,120,4,2,59,101,6917,6919,1,8776,113,59,1,8778,105,110,103,5,229,1,59,6931,1,229,4,3,99,116,121,6941,6946,6949,114,59,3,55349,56502,59,1,42,109,112,4,2,59,101,6957,6959,1,8776,113,59,1,8781,105,108,100,101,5,227,1,59,6972,1,227,109,108,5,228,1,59,6981,1,228,4,2,99,105,6989,6997,111,110,105,110,116,59,1,8755,110,116,59,1,10769,4,16,78,97,98,99,100,101,102,105,107,108,110,111,112,114,115,117,7036,7041,7119,7135,7149,7155,7219,7224,7347,7354,7463,7489,7786,7793,7814,7866,111,116,59,1,10989,4,2,99,114,7047,7094,107,4,4,99,101,112,115,7058,7064,7073,7080,111,110,103,59,1,8780,112,115,105,108,111,110,59,1,1014,114,105,109,101,59,1,8245,105,109,4,2,59,101,7088,7090,1,8765,113,59,1,8909,4,2,118,119,7100,7105,101,101,59,1,8893,101,100,4,2,59,103,7113,7115,1,8965,101,59,1,8965,114,107,4,2,59,116,7127,7129,1,9141,98,114,107,59,1,9142,4,2,111,121,7141,7146,110,103,59,1,8780,59,1,1073,113,117,111,59,1,8222,4,5,99,109,112,114,116,7167,7181,7188,7193,7199,97,117,115,4,2,59,101,7176,7178,1,8757,59,1,8757,112,116,121,118,59,1,10672,115,105,59,1,1014,110,111,117,59,1,8492,4,3,97,104,119,7207,7210,7213,59,1,946,59,1,8502,101,101,110,59,1,8812,114,59,3,55349,56607,103,4,7,99,111,115,116,117,118,119,7241,7262,7288,7305,7328,7335,7340,4,3,97,105,117,7249,7253,7258,112,59,1,8898,114,99,59,1,9711,112,59,1,8899,4,3,100,112,116,7270,7275,7281,111,116,59,1,10752,108,117,115,59,1,10753,105,109,101,115,59,1,10754,4,2,113,116,7294,7300,99,117,112,59,1,10758,97,114,59,1,9733,114,105,97,110,103,108,101,4,2,100,117,7318,7324,111,119,110,59,1,9661,112,59,1,9651,112,108,117,115,59,1,10756,101,101,59,1,8897,101,100,103,101,59,1,8896,97,114,111,119,59,1,10509,4,3,97,107,111,7362,7436,7458,4,2,99,110,7368,7432,107,4,3,108,115,116,7377,7386,7394,111,122,101,110,103,101,59,1,10731,113,117,97,114,101,59,1,9642,114,105,97,110,103,108,101,4,4,59,100,108,114,7411,7413,7419,7425,1,9652,111,119,110,59,1,9662,101,102,116,59,1,9666,105,103,104,116,59,1,9656,107,59,1,9251,4,2,49,51,7442,7454,4,2,50,52,7448,7451,59,1,9618,59,1,9617,52,59,1,9619,99,107,59,1,9608,4,2,101,111,7469,7485,4,2,59,113,7475,7478,3,61,8421,117,105,118,59,3,8801,8421,116,59,1,8976,4,4,112,116,119,120,7499,7504,7517,7523,102,59,3,55349,56659,4,2,59,116,7510,7512,1,8869,111,109,59,1,8869,116,105,101,59,1,8904,4,12,68,72,85,86,98,100,104,109,112,116,117,118,7549,7571,7597,7619,7655,7660,7682,7708,7715,7721,7728,7750,4,4,76,82,108,114,7559,7562,7565,7568,59,1,9559,59,1,9556,59,1,9558,59,1,9555,4,5,59,68,85,100,117,7583,7585,7588,7591,7594,1,9552,59,1,9574,59,1,9577,59,1,9572,59,1,9575,4,4,76,82,108,114,7607,7610,7613,7616,59,1,9565,59,1,9562,59,1,9564,59,1,9561,4,7,59,72,76,82,104,108,114,7635,7637,7640,7643,7646,7649,7652,1,9553,59,1,9580,59,1,9571,59,1,9568,59,1,9579,59,1,9570,59,1,9567,111,120,59,1,10697,4,4,76,82,108,114,7670,7673,7676,7679,59,1,9557,59,1,9554,59,1,9488,59,1,9484,4,5,59,68,85,100,117,7694,7696,7699,7702,7705,1,9472,59,1,9573,59,1,9576,59,1,9516,59,1,9524,105,110,117,115,59,1,8863,108,117,115,59,1,8862,105,109,101,115,59,1,8864,4,4,76,82,108,114,7738,7741,7744,7747,59,1,9563,59,1,9560,59,1,9496,59,1,9492,4,7,59,72,76,82,104,108,114,7766,7768,7771,7774,7777,7780,7783,1,9474,59,1,9578,59,1,9569,59,1,9566,59,1,9532,59,1,9508,59,1,9500,114,105,109,101,59,1,8245,4,2,101,118,7799,7804,118,101,59,1,728,98,97,114,5,166,1,59,7812,1,166,4,4,99,101,105,111,7824,7829,7834,7846,114,59,3,55349,56503,109,105,59,1,8271,109,4,2,59,101,7841,7843,1,8765,59,1,8909,108,4,3,59,98,104,7855,7857,7860,1,92,59,1,10693,115,117,98,59,1,10184,4,2,108,109,7872,7885,108,4,2,59,101,7879,7881,1,8226,116,59,1,8226,112,4,3,59,69,101,7894,7896,7899,1,8782,59,1,10926,4,2,59,113,7905,7907,1,8783,59,1,8783,4,15,97,99,100,101,102,104,105,108,111,114,115,116,117,119,121,7942,8021,8075,8080,8121,8126,8157,8279,8295,8430,8446,8485,8491,8707,8726,4,3,99,112,114,7950,7956,8007,117,116,101,59,1,263,4,6,59,97,98,99,100,115,7970,7972,7977,7984,7998,8003,1,8745,110,100,59,1,10820,114,99,117,112,59,1,10825,4,2,97,117,7990,7994,112,59,1,10827,112,59,1,10823,111,116,59,1,10816,59,3,8745,65024,4,2,101,111,8013,8017,116,59,1,8257,110,59,1,711,4,4,97,101,105,117,8031,8046,8056,8061,4,2,112,114,8037,8041,115,59,1,10829,111,110,59,1,269,100,105,108,5,231,1,59,8054,1,231,114,99,59,1,265,112,115,4,2,59,115,8069,8071,1,10828,109,59,1,10832,111,116,59,1,267,4,3,100,109,110,8088,8097,8104,105,108,5,184,1,59,8095,1,184,112,116,121,118,59,1,10674,116,5,162,2,59,101,8112,8114,1,162,114,100,111,116,59,1,183,114,59,3,55349,56608,4,3,99,101,105,8134,8138,8154,121,59,1,1095,99,107,4,2,59,109,8146,8148,1,10003,97,114,107,59,1,10003,59,1,967,114,4,7,59,69,99,101,102,109,115,8174,8176,8179,8258,8261,8268,8273,1,9675,59,1,10691,4,3,59,101,108,8187,8189,8193,1,710,113,59,1,8791,101,4,2,97,100,8200,8223,114,114,111,119,4,2,108,114,8210,8216,101,102,116,59,1,8634,105,103,104,116,59,1,8635,4,5,82,83,97,99,100,8235,8238,8241,8246,8252,59,1,174,59,1,9416,115,116,59,1,8859,105,114,99,59,1,8858,97,115,104,59,1,8861,59,1,8791,110,105,110,116,59,1,10768,105,100,59,1,10991,99,105,114,59,1,10690,117,98,115,4,2,59,117,8288,8290,1,9827,105,116,59,1,9827,4,4,108,109,110,112,8305,8326,8376,8400,111,110,4,2,59,101,8313,8315,1,58,4,2,59,113,8321,8323,1,8788,59,1,8788,4,2,109,112,8332,8344,97,4,2,59,116,8339,8341,1,44,59,1,64,4,3,59,102,108,8352,8354,8358,1,8705,110,59,1,8728,101,4,2,109,120,8365,8371,101,110,116,59,1,8705,101,115,59,1,8450,4,2,103,105,8382,8395,4,2,59,100,8388,8390,1,8773,111,116,59,1,10861,110,116,59,1,8750,4,3,102,114,121,8408,8412,8417,59,3,55349,56660,111,100,59,1,8720,5,169,2,59,115,8424,8426,1,169,114,59,1,8471,4,2,97,111,8436,8441,114,114,59,1,8629,115,115,59,1,10007,4,2,99,117,8452,8457,114,59,3,55349,56504,4,2,98,112,8463,8474,4,2,59,101,8469,8471,1,10959,59,1,10961,4,2,59,101,8480,8482,1,10960,59,1,10962,100,111,116,59,1,8943,4,7,100,101,108,112,114,118,119,8507,8522,8536,8550,8600,8697,8702,97,114,114,4,2,108,114,8516,8519,59,1,10552,59,1,10549,4,2,112,115,8528,8532,114,59,1,8926,99,59,1,8927,97,114,114,4,2,59,112,8545,8547,1,8630,59,1,10557,4,6,59,98,99,100,111,115,8564,8566,8573,8587,8592,8596,1,8746,114,99,97,112,59,1,10824,4,2,97,117,8579,8583,112,59,1,10822,112,59,1,10826,111,116,59,1,8845,114,59,1,10821,59,3,8746,65024,4,4,97,108,114,118,8610,8623,8663,8672,114,114,4,2,59,109,8618,8620,1,8631,59,1,10556,121,4,3,101,118,119,8632,8651,8656,113,4,2,112,115,8639,8645,114,101,99,59,1,8926,117,99,99,59,1,8927,101,101,59,1,8910,101,100,103,101,59,1,8911,101,110,5,164,1,59,8670,1,164,101,97,114,114,111,119,4,2,108,114,8684,8690,101,102,116,59,1,8630,105,103,104,116,59,1,8631,101,101,59,1,8910,101,100,59,1,8911,4,2,99,105,8713,8721,111,110,105,110,116,59,1,8754,110,116,59,1,8753,108,99,116,121,59,1,9005,4,19,65,72,97,98,99,100,101,102,104,105,106,108,111,114,115,116,117,119,122,8773,8778,8783,8821,8839,8854,8887,8914,8930,8944,9036,9041,9058,9197,9227,9258,9281,9297,9305,114,114,59,1,8659,97,114,59,1,10597,4,4,103,108,114,115,8793,8799,8805,8809,103,101,114,59,1,8224,101,116,104,59,1,8504,114,59,1,8595,104,4,2,59,118,8816,8818,1,8208,59,1,8867,4,2,107,108,8827,8834,97,114,111,119,59,1,10511,97,99,59,1,733,4,2,97,121,8845,8851,114,111,110,59,1,271,59,1,1076,4,3,59,97,111,8862,8864,8880,1,8518,4,2,103,114,8870,8876,103,101,114,59,1,8225,114,59,1,8650,116,115,101,113,59,1,10871,4,3,103,108,109,8895,8902,8907,5,176,1,59,8900,1,176,116,97,59,1,948,112,116,121,118,59,1,10673,4,2,105,114,8920,8926,115,104,116,59,1,10623,59,3,55349,56609,97,114,4,2,108,114,8938,8941,59,1,8643,59,1,8642,4,5,97,101,103,115,118,8956,8986,8989,8996,9001,109,4,3,59,111,115,8965,8967,8983,1,8900,110,100,4,2,59,115,8975,8977,1,8900,117,105,116,59,1,9830,59,1,9830,59,1,168,97,109,109,97,59,1,989,105,110,59,1,8946,4,3,59,105,111,9009,9011,9031,1,247,100,101,5,247,2,59,111,9020,9022,1,247,110,116,105,109,101,115,59,1,8903,110,120,59,1,8903,99,121,59,1,1106,99,4,2,111,114,9048,9053,114,110,59,1,8990,111,112,59,1,8973,4,5,108,112,116,117,119,9070,9076,9081,9130,9144,108,97,114,59,1,36,102,59,3,55349,56661,4,5,59,101,109,112,115,9093,9095,9109,9116,9122,1,729,113,4,2,59,100,9102,9104,1,8784,111,116,59,1,8785,105,110,117,115,59,1,8760,108,117,115,59,1,8724,113,117,97,114,101,59,1,8865,98,108,101,98,97,114,119,101,100,103,101,59,1,8966,110,4,3,97,100,104,9153,9160,9172,114,114,111,119,59,1,8595,111,119,110,97,114,114,111,119,115,59,1,8650,97,114,112,111,111,110,4,2,108,114,9184,9190,101,102,116,59,1,8643,105,103,104,116,59,1,8642,4,2,98,99,9203,9211,107,97,114,111,119,59,1,10512,4,2,111,114,9217,9222,114,110,59,1,8991,111,112,59,1,8972,4,3,99,111,116,9235,9248,9252,4,2,114,121,9241,9245,59,3,55349,56505,59,1,1109,108,59,1,10742,114,111,107,59,1,273,4,2,100,114,9264,9269,111,116,59,1,8945,105,4,2,59,102,9276,9278,1,9663,59,1,9662,4,2,97,104,9287,9292,114,114,59,1,8693,97,114,59,1,10607,97,110,103,108,101,59,1,10662,4,2,99,105,9311,9315,121,59,1,1119,103,114,97,114,114,59,1,10239,4,18,68,97,99,100,101,102,103,108,109,110,111,112,113,114,115,116,117,120,9361,9376,9398,9439,9444,9447,9462,9495,9531,9585,9598,9614,9659,9755,9771,9792,9808,9826,4,2,68,111,9367,9372,111,116,59,1,10871,116,59,1,8785,4,2,99,115,9382,9392,117,116,101,5,233,1,59,9390,1,233,116,101,114,59,1,10862,4,4,97,105,111,121,9408,9414,9430,9436,114,111,110,59,1,283,114,4,2,59,99,9421,9423,1,8790,5,234,1,59,9428,1,234,108,111,110,59,1,8789,59,1,1101,111,116,59,1,279,59,1,8519,4,2,68,114,9453,9458,111,116,59,1,8786,59,3,55349,56610,4,3,59,114,115,9470,9472,9482,1,10906,97,118,101,5,232,1,59,9480,1,232,4,2,59,100,9488,9490,1,10902,111,116,59,1,10904,4,4,59,105,108,115,9505,9507,9515,9518,1,10905,110,116,101,114,115,59,1,9191,59,1,8467,4,2,59,100,9524,9526,1,10901,111,116,59,1,10903,4,3,97,112,115,9539,9544,9564,99,114,59,1,275,116,121,4,3,59,115,118,9554,9556,9561,1,8709,101,116,59,1,8709,59,1,8709,112,4,2,49,59,9571,9583,4,2,51,52,9577,9580,59,1,8196,59,1,8197,1,8195,4,2,103,115,9591,9594,59,1,331,112,59,1,8194,4,2,103,112,9604,9609,111,110,59,1,281,102,59,3,55349,56662,4,3,97,108,115,9622,9635,9640,114,4,2,59,115,9629,9631,1,8917,108,59,1,10723,117,115,59,1,10865,105,4,3,59,108,118,9649,9651,9656,1,949,111,110,59,1,949,59,1,1013,4,4,99,115,117,118,9669,9686,9716,9747,4,2,105,111,9675,9680,114,99,59,1,8790,108,111,110,59,1,8789,4,2,105,108,9692,9696,109,59,1,8770,97,110,116,4,2,103,108,9705,9710,116,114,59,1,10902,101,115,115,59,1,10901,4,3,97,101,105,9724,9729,9734,108,115,59,1,61,115,116,59,1,8799,118,4,2,59,68,9741,9743,1,8801,68,59,1,10872,112,97,114,115,108,59,1,10725,4,2,68,97,9761,9766,111,116,59,1,8787,114,114,59,1,10609,4,3,99,100,105,9779,9783,9788,114,59,1,8495,111,116,59,1,8784,109,59,1,8770,4,2,97,104,9798,9801,59,1,951,5,240,1,59,9806,1,240,4,2,109,114,9814,9822,108,5,235,1,59,9820,1,235,111,59,1,8364,4,3,99,105,112,9834,9838,9843,108,59,1,33,115,116,59,1,8707,4,2,101,111,9849,9859,99,116,97,116,105,111,110,59,1,8496,110,101,110,116,105,97,108,101,59,1,8519,4,12,97,99,101,102,105,106,108,110,111,112,114,115,9896,9910,9914,9921,9954,9960,9967,9989,9994,10027,10036,10164,108,108,105,110,103,100,111,116,115,101,113,59,1,8786,121,59,1,1092,109,97,108,101,59,1,9792,4,3,105,108,114,9929,9935,9950,108,105,103,59,1,64259,4,2,105,108,9941,9945,103,59,1,64256,105,103,59,1,64260,59,3,55349,56611,108,105,103,59,1,64257,108,105,103,59,3,102,106,4,3,97,108,116,9975,9979,9984,116,59,1,9837,105,103,59,1,64258,110,115,59,1,9649,111,102,59,1,402,4,2,112,114,10000,10005,102,59,3,55349,56663,4,2,97,107,10011,10016,108,108,59,1,8704,4,2,59,118,10022,10024,1,8916,59,1,10969,97,114,116,105,110,116,59,1,10765,4,2,97,111,10042,10159,4,2,99,115,10048,10155,4,6,49,50,51,52,53,55,10062,10102,10114,10135,10139,10151,4,6,50,51,52,53,54,56,10076,10083,10086,10093,10096,10099,5,189,1,59,10081,1,189,59,1,8531,5,188,1,59,10091,1,188,59,1,8533,59,1,8537,59,1,8539,4,2,51,53,10108,10111,59,1,8532,59,1,8534,4,3,52,53,56,10122,10129,10132,5,190,1,59,10127,1,190,59,1,8535,59,1,8540,53,59,1,8536,4,2,54,56,10145,10148,59,1,8538,59,1,8541,56,59,1,8542,108,59,1,8260,119,110,59,1,8994,99,114,59,3,55349,56507,4,17,69,97,98,99,100,101,102,103,105,106,108,110,111,114,115,116,118,10206,10217,10247,10254,10268,10273,10358,10363,10374,10380,10385,10406,10458,10464,10470,10497,10610,4,2,59,108,10212,10214,1,8807,59,1,10892,4,3,99,109,112,10225,10231,10244,117,116,101,59,1,501,109,97,4,2,59,100,10239,10241,1,947,59,1,989,59,1,10886,114,101,118,101,59,1,287,4,2,105,121,10260,10265,114,99,59,1,285,59,1,1075,111,116,59,1,289,4,4,59,108,113,115,10283,10285,10288,10308,1,8805,59,1,8923,4,3,59,113,115,10296,10298,10301,1,8805,59,1,8807,108,97,110,116,59,1,10878,4,4,59,99,100,108,10318,10320,10324,10345,1,10878,99,59,1,10921,111,116,4,2,59,111,10332,10334,1,10880,4,2,59,108,10340,10342,1,10882,59,1,10884,4,2,59,101,10351,10354,3,8923,65024,115,59,1,10900,114,59,3,55349,56612,4,2,59,103,10369,10371,1,8811,59,1,8921,109,101,108,59,1,8503,99,121,59,1,1107,4,4,59,69,97,106,10395,10397,10400,10403,1,8823,59,1,10898,59,1,10917,59,1,10916,4,4,69,97,101,115,10416,10419,10434,10453,59,1,8809,112,4,2,59,112,10426,10428,1,10890,114,111,120,59,1,10890,4,2,59,113,10440,10442,1,10888,4,2,59,113,10448,10450,1,10888,59,1,8809,105,109,59,1,8935,112,102,59,3,55349,56664,97,118,101,59,1,96,4,2,99,105,10476,10480,114,59,1,8458,109,4,3,59,101,108,10489,10491,10494,1,8819,59,1,10894,59,1,10896,5,62,6,59,99,100,108,113,114,10512,10514,10527,10532,10538,10545,1,62,4,2,99,105,10520,10523,59,1,10919,114,59,1,10874,111,116,59,1,8919,80,97,114,59,1,10645,117,101,115,116,59,1,10876,4,5,97,100,101,108,115,10557,10574,10579,10599,10605,4,2,112,114,10563,10570,112,114,111,120,59,1,10886,114,59,1,10616,111,116,59,1,8919,113,4,2,108,113,10586,10592,101,115,115,59,1,8923,108,101,115,115,59,1,10892,101,115,115,59,1,8823,105,109,59,1,8819,4,2,101,110,10616,10626,114,116,110,101,113,113,59,3,8809,65024,69,59,3,8809,65024,4,10,65,97,98,99,101,102,107,111,115,121,10653,10658,10713,10718,10724,10760,10765,10786,10850,10875,114,114,59,1,8660,4,4,105,108,109,114,10668,10674,10678,10684,114,115,112,59,1,8202,102,59,1,189,105,108,116,59,1,8459,4,2,100,114,10690,10695,99,121,59,1,1098,4,3,59,99,119,10703,10705,10710,1,8596,105,114,59,1,10568,59,1,8621,97,114,59,1,8463,105,114,99,59,1,293,4,3,97,108,114,10732,10748,10754,114,116,115,4,2,59,117,10741,10743,1,9829,105,116,59,1,9829,108,105,112,59,1,8230,99,111,110,59,1,8889,114,59,3,55349,56613,115,4,2,101,119,10772,10779,97,114,111,119,59,1,10533,97,114,111,119,59,1,10534,4,5,97,109,111,112,114,10798,10803,10809,10839,10844,114,114,59,1,8703,116,104,116,59,1,8763,107,4,2,108,114,10816,10827,101,102,116,97,114,114,111,119,59,1,8617,105,103,104,116,97,114,114,111,119,59,1,8618,102,59,3,55349,56665,98,97,114,59,1,8213,4,3,99,108,116,10858,10863,10869,114,59,3,55349,56509,97,115,104,59,1,8463,114,111,107,59,1,295,4,2,98,112,10881,10887,117,108,108,59,1,8259,104,101,110,59,1,8208,4,15,97,99,101,102,103,105,106,109,110,111,112,113,115,116,117,10925,10936,10958,10977,10990,11001,11039,11045,11101,11192,11220,11226,11237,11285,11299,99,117,116,101,5,237,1,59,10934,1,237,4,3,59,105,121,10944,10946,10955,1,8291,114,99,5,238,1,59,10953,1,238,59,1,1080,4,2,99,120,10964,10968,121,59,1,1077,99,108,5,161,1,59,10975,1,161,4,2,102,114,10983,10986,59,1,8660,59,3,55349,56614,114,97,118,101,5,236,1,59,10999,1,236,4,4,59,105,110,111,11011,11013,11028,11034,1,8520,4,2,105,110,11019,11024,110,116,59,1,10764,116,59,1,8749,102,105,110,59,1,10716,116,97,59,1,8489,108,105,103,59,1,307,4,3,97,111,112,11053,11092,11096,4,3,99,103,116,11061,11065,11088,114,59,1,299,4,3,101,108,112,11073,11076,11082,59,1,8465,105,110,101,59,1,8464,97,114,116,59,1,8465,104,59,1,305,102,59,1,8887,101,100,59,1,437,4,5,59,99,102,111,116,11113,11115,11121,11136,11142,1,8712,97,114,101,59,1,8453,105,110,4,2,59,116,11129,11131,1,8734,105,101,59,1,10717,100,111,116,59,1,305,4,5,59,99,101,108,112,11154,11156,11161,11179,11186,1,8747,97,108,59,1,8890,4,2,103,114,11167,11173,101,114,115,59,1,8484,99,97,108,59,1,8890,97,114,104,107,59,1,10775,114,111,100,59,1,10812,4,4,99,103,112,116,11202,11206,11211,11216,121,59,1,1105,111,110,59,1,303,102,59,3,55349,56666,97,59,1,953,114,111,100,59,1,10812,117,101,115,116,5,191,1,59,11235,1,191,4,2,99,105,11243,11248,114,59,3,55349,56510,110,4,5,59,69,100,115,118,11261,11263,11266,11271,11282,1,8712,59,1,8953,111,116,59,1,8949,4,2,59,118,11277,11279,1,8948,59,1,8947,59,1,8712,4,2,59,105,11291,11293,1,8290,108,100,101,59,1,297,4,2,107,109,11305,11310,99,121,59,1,1110,108,5,239,1,59,11316,1,239,4,6,99,102,109,111,115,117,11332,11346,11351,11357,11363,11380,4,2,105,121,11338,11343,114,99,59,1,309,59,1,1081,114,59,3,55349,56615,97,116,104,59,1,567,112,102,59,3,55349,56667,4,2,99,101,11369,11374,114,59,3,55349,56511,114,99,121,59,1,1112,107,99,121,59,1,1108,4,8,97,99,102,103,104,106,111,115,11404,11418,11433,11438,11445,11450,11455,11461,112,112,97,4,2,59,118,11413,11415,1,954,59,1,1008,4,2,101,121,11424,11430,100,105,108,59,1,311,59,1,1082,114,59,3,55349,56616,114,101,101,110,59,1,312,99,121,59,1,1093,99,121,59,1,1116,112,102,59,3,55349,56668,99,114,59,3,55349,56512,4,23,65,66,69,72,97,98,99,100,101,102,103,104,106,108,109,110,111,112,114,115,116,117,118,11515,11538,11544,11555,11560,11721,11780,11818,11868,12136,12160,12171,12203,12208,12246,12275,12327,12509,12523,12569,12641,12732,12752,4,3,97,114,116,11523,11528,11532,114,114,59,1,8666,114,59,1,8656,97,105,108,59,1,10523,97,114,114,59,1,10510,4,2,59,103,11550,11552,1,8806,59,1,10891,97,114,59,1,10594,4,9,99,101,103,109,110,112,113,114,116,11580,11586,11594,11600,11606,11624,11627,11636,11694,117,116,101,59,1,314,109,112,116,121,118,59,1,10676,114,97,110,59,1,8466,98,100,97,59,1,955,103,4,3,59,100,108,11615,11617,11620,1,10216,59,1,10641,101,59,1,10216,59,1,10885,117,111,5,171,1,59,11634,1,171,114,4,8,59,98,102,104,108,112,115,116,11655,11657,11669,11673,11677,11681,11685,11690,1,8592,4,2,59,102,11663,11665,1,8676,115,59,1,10527,115,59,1,10525,107,59,1,8617,112,59,1,8619,108,59,1,10553,105,109,59,1,10611,108,59,1,8610,4,3,59,97,101,11702,11704,11709,1,10923,105,108,59,1,10521,4,2,59,115,11715,11717,1,10925,59,3,10925,65024,4,3,97,98,114,11729,11734,11739,114,114,59,1,10508,114,107,59,1,10098,4,2,97,107,11745,11758,99,4,2,101,107,11752,11755,59,1,123,59,1,91,4,2,101,115,11764,11767,59,1,10635,108,4,2,100,117,11774,11777,59,1,10639,59,1,10637,4,4,97,101,117,121,11790,11796,11811,11815,114,111,110,59,1,318,4,2,100,105,11802,11807,105,108,59,1,316,108,59,1,8968,98,59,1,123,59,1,1083,4,4,99,113,114,115,11828,11832,11845,11864,97,59,1,10550,117,111,4,2,59,114,11840,11842,1,8220,59,1,8222,4,2,100,117,11851,11857,104,97,114,59,1,10599,115,104,97,114,59,1,10571,104,59,1,8626,4,5,59,102,103,113,115,11880,11882,12008,12011,12031,1,8804,116,4,5,97,104,108,114,116,11895,11913,11935,11947,11996,114,114,111,119,4,2,59,116,11905,11907,1,8592,97,105,108,59,1,8610,97,114,112,111,111,110,4,2,100,117,11925,11931,111,119,110,59,1,8637,112,59,1,8636,101,102,116,97,114,114,111,119,115,59,1,8647,105,103,104,116,4,3,97,104,115,11959,11974,11984,114,114,111,119,4,2,59,115,11969,11971,1,8596,59,1,8646,97,114,112,111,111,110,115,59,1,8651,113,117,105,103,97,114,114,111,119,59,1,8621,104,114,101,101,116,105,109,101,115,59,1,8907,59,1,8922,4,3,59,113,115,12019,12021,12024,1,8804,59,1,8806,108,97,110,116,59,1,10877,4,5,59,99,100,103,115,12043,12045,12049,12070,12083,1,10877,99,59,1,10920,111,116,4,2,59,111,12057,12059,1,10879,4,2,59,114,12065,12067,1,10881,59,1,10883,4,2,59,101,12076,12079,3,8922,65024,115,59,1,10899,4,5,97,100,101,103,115,12095,12103,12108,12126,12131,112,112,114,111,120,59,1,10885,111,116,59,1,8918,113,4,2,103,113,12115,12120,116,114,59,1,8922,103,116,114,59,1,10891,116,114,59,1,8822,105,109,59,1,8818,4,3,105,108,114,12144,12150,12156,115,104,116,59,1,10620,111,111,114,59,1,8970,59,3,55349,56617,4,2,59,69,12166,12168,1,8822,59,1,10897,4,2,97,98,12177,12198,114,4,2,100,117,12184,12187,59,1,8637,4,2,59,108,12193,12195,1,8636,59,1,10602,108,107,59,1,9604,99,121,59,1,1113,4,5,59,97,99,104,116,12220,12222,12227,12235,12241,1,8810,114,114,59,1,8647,111,114,110,101,114,59,1,8990,97,114,100,59,1,10603,114,105,59,1,9722,4,2,105,111,12252,12258,100,111,116,59,1,320,117,115,116,4,2,59,97,12267,12269,1,9136,99,104,101,59,1,9136,4,4,69,97,101,115,12285,12288,12303,12322,59,1,8808,112,4,2,59,112,12295,12297,1,10889,114,111,120,59,1,10889,4,2,59,113,12309,12311,1,10887,4,2,59,113,12317,12319,1,10887,59,1,8808,105,109,59,1,8934,4,8,97,98,110,111,112,116,119,122,12345,12359,12364,12421,12446,12467,12474,12490,4,2,110,114,12351,12355,103,59,1,10220,114,59,1,8701,114,107,59,1,10214,103,4,3,108,109,114,12373,12401,12409,101,102,116,4,2,97,114,12382,12389,114,114,111,119,59,1,10229,105,103,104,116,97,114,114,111,119,59,1,10231,97,112,115,116,111,59,1,10236,105,103,104,116,97,114,114,111,119,59,1,10230,112,97,114,114,111,119,4,2,108,114,12433,12439,101,102,116,59,1,8619,105,103,104,116,59,1,8620,4,3,97,102,108,12454,12458,12462,114,59,1,10629,59,3,55349,56669,117,115,59,1,10797,105,109,101,115,59,1,10804,4,2,97,98,12480,12485,115,116,59,1,8727,97,114,59,1,95,4,3,59,101,102,12498,12500,12506,1,9674,110,103,101,59,1,9674,59,1,10731,97,114,4,2,59,108,12517,12519,1,40,116,59,1,10643,4,5,97,99,104,109,116,12535,12540,12548,12561,12564,114,114,59,1,8646,111,114,110,101,114,59,1,8991,97,114,4,2,59,100,12556,12558,1,8651,59,1,10605,59,1,8206,114,105,59,1,8895,4,6,97,99,104,105,113,116,12583,12589,12594,12597,12614,12635,113,117,111,59,1,8249,114,59,3,55349,56513,59,1,8624,109,4,3,59,101,103,12606,12608,12611,1,8818,59,1,10893,59,1,10895,4,2,98,117,12620,12623,59,1,91,111,4,2,59,114,12630,12632,1,8216,59,1,8218,114,111,107,59,1,322,5,60,8,59,99,100,104,105,108,113,114,12660,12662,12675,12680,12686,12692,12698,12705,1,60,4,2,99,105,12668,12671,59,1,10918,114,59,1,10873,111,116,59,1,8918,114,101,101,59,1,8907,109,101,115,59,1,8905,97,114,114,59,1,10614,117,101,115,116,59,1,10875,4,2,80,105,12711,12716,97,114,59,1,10646,4,3,59,101,102,12724,12726,12729,1,9667,59,1,8884,59,1,9666,114,4,2,100,117,12739,12746,115,104,97,114,59,1,10570,104,97,114,59,1,10598,4,2,101,110,12758,12768,114,116,110,101,113,113,59,3,8808,65024,69,59,3,8808,65024,4,14,68,97,99,100,101,102,104,105,108,110,111,112,115,117,12803,12809,12893,12908,12914,12928,12933,12937,13011,13025,13032,13049,13052,13069,68,111,116,59,1,8762,4,4,99,108,112,114,12819,12827,12849,12887,114,5,175,1,59,12825,1,175,4,2,101,116,12833,12836,59,1,9794,4,2,59,101,12842,12844,1,10016,115,101,59,1,10016,4,2,59,115,12855,12857,1,8614,116,111,4,4,59,100,108,117,12869,12871,12877,12883,1,8614,111,119,110,59,1,8615,101,102,116,59,1,8612,112,59,1,8613,107,101,114,59,1,9646,4,2,111,121,12899,12905,109,109,97,59,1,10793,59,1,1084,97,115,104,59,1,8212,97,115,117,114,101,100,97,110,103,108,101,59,1,8737,114,59,3,55349,56618,111,59,1,8487,4,3,99,100,110,12945,12954,12985,114,111,5,181,1,59,12952,1,181,4,4,59,97,99,100,12964,12966,12971,12976,1,8739,115,116,59,1,42,105,114,59,1,10992,111,116,5,183,1,59,12983,1,183,117,115,4,3,59,98,100,12995,12997,13000,1,8722,59,1,8863,4,2,59,117,13006,13008,1,8760,59,1,10794,4,2,99,100,13017,13021,112,59,1,10971,114,59,1,8230,112,108,117,115,59,1,8723,4,2,100,112,13038,13044,101,108,115,59,1,8871,102,59,3,55349,56670,59,1,8723,4,2,99,116,13058,13063,114,59,3,55349,56514,112,111,115,59,1,8766,4,3,59,108,109,13077,13079,13087,1,956,116,105,109,97,112,59,1,8888,97,112,59,1,8888,4,24,71,76,82,86,97,98,99,100,101,102,103,104,105,106,108,109,111,112,114,115,116,117,118,119,13142,13165,13217,13229,13247,13330,13359,13414,13420,13508,13513,13579,13602,13626,13631,13762,13767,13855,13936,13995,14214,14285,14312,14432,4,2,103,116,13148,13152,59,3,8921,824,4,2,59,118,13158,13161,3,8811,8402,59,3,8811,824,4,3,101,108,116,13173,13200,13204,102,116,4,2,97,114,13181,13188,114,114,111,119,59,1,8653,105,103,104,116,97,114,114,111,119,59,1,8654,59,3,8920,824,4,2,59,118,13210,13213,3,8810,8402,59,3,8810,824,105,103,104,116,97,114,114,111,119,59,1,8655,4,2,68,100,13235,13241,97,115,104,59,1,8879,97,115,104,59,1,8878,4,5,98,99,110,112,116,13259,13264,13270,13275,13308,108,97,59,1,8711,117,116,101,59,1,324,103,59,3,8736,8402,4,5,59,69,105,111,112,13287,13289,13293,13298,13302,1,8777,59,3,10864,824,100,59,3,8779,824,115,59,1,329,114,111,120,59,1,8777,117,114,4,2,59,97,13316,13318,1,9838,108,4,2,59,115,13325,13327,1,9838,59,1,8469,4,2,115,117,13336,13344,112,5,160,1,59,13342,1,160,109,112,4,2,59,101,13352,13355,3,8782,824,59,3,8783,824,4,5,97,101,111,117,121,13371,13385,13391,13407,13411,4,2,112,114,13377,13380,59,1,10819,111,110,59,1,328,100,105,108,59,1,326,110,103,4,2,59,100,13399,13401,1,8775,111,116,59,3,10861,824,112,59,1,10818,59,1,1085,97,115,104,59,1,8211,4,7,59,65,97,100,113,115,120,13436,13438,13443,13466,13472,13478,13494,1,8800,114,114,59,1,8663,114,4,2,104,114,13450,13454,107,59,1,10532,4,2,59,111,13460,13462,1,8599,119,59,1,8599,111,116,59,3,8784,824,117,105,118,59,1,8802,4,2,101,105,13484,13489,97,114,59,1,10536,109,59,3,8770,824,105,115,116,4,2,59,115,13503,13505,1,8708,59,1,8708,114,59,3,55349,56619,4,4,69,101,115,116,13523,13527,13563,13568,59,3,8807,824,4,3,59,113,115,13535,13537,13559,1,8817,4,3,59,113,115,13545,13547,13551,1,8817,59,3,8807,824,108,97,110,116,59,3,10878,824,59,3,10878,824,105,109,59,1,8821,4,2,59,114,13574,13576,1,8815,59,1,8815,4,3,65,97,112,13587,13592,13597,114,114,59,1,8654,114,114,59,1,8622,97,114,59,1,10994,4,3,59,115,118,13610,13612,13623,1,8715,4,2,59,100,13618,13620,1,8956,59,1,8954,59,1,8715,99,121,59,1,1114,4,7,65,69,97,100,101,115,116,13647,13652,13656,13661,13665,13737,13742,114,114,59,1,8653,59,3,8806,824,114,114,59,1,8602,114,59,1,8229,4,4,59,102,113,115,13675,13677,13703,13725,1,8816,116,4,2,97,114,13684,13691,114,114,111,119,59,1,8602,105,103,104,116,97,114,114,111,119,59,1,8622,4,3,59,113,115,13711,13713,13717,1,8816,59,3,8806,824,108,97,110,116,59,3,10877,824,4,2,59,115,13731,13734,3,10877,824,59,1,8814,105,109,59,1,8820,4,2,59,114,13748,13750,1,8814,105,4,2,59,101,13757,13759,1,8938,59,1,8940,105,100,59,1,8740,4,2,112,116,13773,13778,102,59,3,55349,56671,5,172,3,59,105,110,13787,13789,13829,1,172,110,4,4,59,69,100,118,13800,13802,13806,13812,1,8713,59,3,8953,824,111,116,59,3,8949,824,4,3,97,98,99,13820,13823,13826,59,1,8713,59,1,8951,59,1,8950,105,4,2,59,118,13836,13838,1,8716,4,3,97,98,99,13846,13849,13852,59,1,8716,59,1,8958,59,1,8957,4,3,97,111,114,13863,13892,13899,114,4,4,59,97,115,116,13874,13876,13883,13888,1,8742,108,108,101,108,59,1,8742,108,59,3,11005,8421,59,3,8706,824,108,105,110,116,59,1,10772,4,3,59,99,101,13907,13909,13914,1,8832,117,101,59,1,8928,4,2,59,99,13920,13923,3,10927,824,4,2,59,101,13929,13931,1,8832,113,59,3,10927,824,4,4,65,97,105,116,13946,13951,13971,13982,114,114,59,1,8655,114,114,4,3,59,99,119,13961,13963,13967,1,8603,59,3,10547,824,59,3,8605,824,103,104,116,97,114,114,111,119,59,1,8603,114,105,4,2,59,101,13990,13992,1,8939,59,1,8941,4,7,99,104,105,109,112,113,117,14011,14036,14060,14080,14085,14090,14106,4,4,59,99,101,114,14021,14023,14028,14032,1,8833,117,101,59,1,8929,59,3,10928,824,59,3,55349,56515,111,114,116,4,2,109,112,14045,14050,105,100,59,1,8740,97,114,97,108,108,101,108,59,1,8742,109,4,2,59,101,14067,14069,1,8769,4,2,59,113,14075,14077,1,8772,59,1,8772,105,100,59,1,8740,97,114,59,1,8742,115,117,4,2,98,112,14098,14102,101,59,1,8930,101,59,1,8931,4,3,98,99,112,14114,14157,14171,4,4,59,69,101,115,14124,14126,14130,14133,1,8836,59,3,10949,824,59,1,8840,101,116,4,2,59,101,14141,14144,3,8834,8402,113,4,2,59,113,14151,14153,1,8840,59,3,10949,824,99,4,2,59,101,14164,14166,1,8833,113,59,3,10928,824,4,4,59,69,101,115,14181,14183,14187,14190,1,8837,59,3,10950,824,59,1,8841,101,116,4,2,59,101,14198,14201,3,8835,8402,113,4,2,59,113,14208,14210,1,8841,59,3,10950,824,4,4,103,105,108,114,14224,14228,14238,14242,108,59,1,8825,108,100,101,5,241,1,59,14236,1,241,103,59,1,8824,105,97,110,103,108,101,4,2,108,114,14254,14269,101,102,116,4,2,59,101,14263,14265,1,8938,113,59,1,8940,105,103,104,116,4,2,59,101,14279,14281,1,8939,113,59,1,8941,4,2,59,109,14291,14293,1,957,4,3,59,101,115,14301,14303,14308,1,35,114,111,59,1,8470,112,59,1,8199,4,9,68,72,97,100,103,105,108,114,115,14332,14338,14344,14349,14355,14369,14376,14408,14426,97,115,104,59,1,8877,97,114,114,59,1,10500,112,59,3,8781,8402,97,115,104,59,1,8876,4,2,101,116,14361,14365,59,3,8805,8402,59,3,62,8402,110,102,105,110,59,1,10718,4,3,65,101,116,14384,14389,14393,114,114,59,1,10498,59,3,8804,8402,4,2,59,114,14399,14402,3,60,8402,105,101,59,3,8884,8402,4,2,65,116,14414,14419,114,114,59,1,10499,114,105,101,59,3,8885,8402,105,109,59,3,8764,8402,4,3,65,97,110,14440,14445,14468,114,114,59,1,8662,114,4,2,104,114,14452,14456,107,59,1,10531,4,2,59,111,14462,14464,1,8598,119,59,1,8598,101,97,114,59,1,10535,4,18,83,97,99,100,101,102,103,104,105,108,109,111,112,114,115,116,117,118,14512,14515,14535,14560,14597,14603,14618,14643,14657,14662,14701,14741,14747,14769,14851,14877,14907,14916,59,1,9416,4,2,99,115,14521,14531,117,116,101,5,243,1,59,14529,1,243,116,59,1,8859,4,2,105,121,14541,14557,114,4,2,59,99,14548,14550,1,8858,5,244,1,59,14555,1,244,59,1,1086,4,5,97,98,105,111,115,14572,14577,14583,14587,14591,115,104,59,1,8861,108,97,99,59,1,337,118,59,1,10808,116,59,1,8857,111,108,100,59,1,10684,108,105,103,59,1,339,4,2,99,114,14609,14614,105,114,59,1,10687,59,3,55349,56620,4,3,111,114,116,14626,14630,14640,110,59,1,731,97,118,101,5,242,1,59,14638,1,242,59,1,10689,4,2,98,109,14649,14654,97,114,59,1,10677,59,1,937,110,116,59,1,8750,4,4,97,99,105,116,14672,14677,14693,14698,114,114,59,1,8634,4,2,105,114,14683,14687,114,59,1,10686,111,115,115,59,1,10683,110,101,59,1,8254,59,1,10688,4,3,97,101,105,14709,14714,14719,99,114,59,1,333,103,97,59,1,969,4,3,99,100,110,14727,14733,14736,114,111,110,59,1,959,59,1,10678,117,115,59,1,8854,112,102,59,3,55349,56672,4,3,97,101,108,14755,14759,14764,114,59,1,10679,114,112,59,1,10681,117,115,59,1,8853,4,7,59,97,100,105,111,115,118,14785,14787,14792,14831,14837,14841,14848,1,8744,114,114,59,1,8635,4,4,59,101,102,109,14802,14804,14817,14824,1,10845,114,4,2,59,111,14811,14813,1,8500,102,59,1,8500,5,170,1,59,14822,1,170,5,186,1,59,14829,1,186,103,111,102,59,1,8886,114,59,1,10838,108,111,112,101,59,1,10839,59,1,10843,4,3,99,108,111,14859,14863,14873,114,59,1,8500,97,115,104,5,248,1,59,14871,1,248,108,59,1,8856,105,4,2,108,109,14884,14893,100,101,5,245,1,59,14891,1,245,101,115,4,2,59,97,14901,14903,1,8855,115,59,1,10806,109,108,5,246,1,59,14914,1,246,98,97,114,59,1,9021,4,12,97,99,101,102,104,105,108,109,111,114,115,117,14948,14992,14996,15033,15038,15068,15090,15189,15192,15222,15427,15441,114,4,4,59,97,115,116,14959,14961,14976,14989,1,8741,5,182,2,59,108,14968,14970,1,182,108,101,108,59,1,8741,4,2,105,108,14982,14986,109,59,1,10995,59,1,11005,59,1,8706,121,59,1,1087,114,4,5,99,105,109,112,116,15009,15014,15019,15024,15027,110,116,59,1,37,111,100,59,1,46,105,108,59,1,8240,59,1,8869,101,110,107,59,1,8241,114,59,3,55349,56621,4,3,105,109,111,15046,15057,15063,4,2,59,118,15052,15054,1,966,59,1,981,109,97,116,59,1,8499,110,101,59,1,9742,4,3,59,116,118,15076,15078,15087,1,960,99,104,102,111,114,107,59,1,8916,59,1,982,4,2,97,117,15096,15119,110,4,2,99,107,15103,15115,107,4,2,59,104,15110,15112,1,8463,59,1,8462,118,59,1,8463,115,4,9,59,97,98,99,100,101,109,115,116,15140,15142,15148,15151,15156,15168,15171,15179,15184,1,43,99,105,114,59,1,10787,59,1,8862,105,114,59,1,10786,4,2,111,117,15162,15165,59,1,8724,59,1,10789,59,1,10866,110,5,177,1,59,15177,1,177,105,109,59,1,10790,119,111,59,1,10791,59,1,177,4,3,105,112,117,15200,15208,15213,110,116,105,110,116,59,1,10773,102,59,3,55349,56673,110,100,5,163,1,59,15220,1,163,4,10,59,69,97,99,101,105,110,111,115,117,15244,15246,15249,15253,15258,15334,15347,15367,15416,15421,1,8826,59,1,10931,112,59,1,10935,117,101,59,1,8828,4,2,59,99,15264,15266,1,10927,4,6,59,97,99,101,110,115,15280,15282,15290,15299,15303,15329,1,8826,112,112,114,111,120,59,1,10935,117,114,108,121,101,113,59,1,8828,113,59,1,10927,4,3,97,101,115,15311,15319,15324,112,112,114,111,120,59,1,10937,113,113,59,1,10933,105,109,59,1,8936,105,109,59,1,8830,109,101,4,2,59,115,15342,15344,1,8242,59,1,8473,4,3,69,97,115,15355,15358,15362,59,1,10933,112,59,1,10937,105,109,59,1,8936,4,3,100,102,112,15375,15378,15404,59,1,8719,4,3,97,108,115,15386,15392,15398,108,97,114,59,1,9006,105,110,101,59,1,8978,117,114,102,59,1,8979,4,2,59,116,15410,15412,1,8733,111,59,1,8733,105,109,59,1,8830,114,101,108,59,1,8880,4,2,99,105,15433,15438,114,59,3,55349,56517,59,1,968,110,99,115,112,59,1,8200,4,6,102,105,111,112,115,117,15462,15467,15472,15478,15485,15491,114,59,3,55349,56622,110,116,59,1,10764,112,102,59,3,55349,56674,114,105,109,101,59,1,8279,99,114,59,3,55349,56518,4,3,97,101,111,15499,15520,15534,116,4,2,101,105,15506,15515,114,110,105,111,110,115,59,1,8461,110,116,59,1,10774,115,116,4,2,59,101,15528,15530,1,63,113,59,1,8799,116,5,34,1,59,15540,1,34,4,21,65,66,72,97,98,99,100,101,102,104,105,108,109,110,111,112,114,115,116,117,120,15586,15609,15615,15620,15796,15855,15893,15931,15977,16001,16039,16183,16204,16222,16228,16285,16312,16318,16363,16408,16416,4,3,97,114,116,15594,15599,15603,114,114,59,1,8667,114,59,1,8658,97,105,108,59,1,10524,97,114,114,59,1,10511,97,114,59,1,10596,4,7,99,100,101,110,113,114,116,15636,15651,15656,15664,15687,15696,15770,4,2,101,117,15642,15646,59,3,8765,817,116,101,59,1,341,105,99,59,1,8730,109,112,116,121,118,59,1,10675,103,4,4,59,100,101,108,15675,15677,15680,15683,1,10217,59,1,10642,59,1,10661,101,59,1,10217,117,111,5,187,1,59,15694,1,187,114,4,11,59,97,98,99,102,104,108,112,115,116,119,15721,15723,15727,15739,15742,15746,15750,15754,15758,15763,15767,1,8594,112,59,1,10613,4,2,59,102,15733,15735,1,8677,115,59,1,10528,59,1,10547,115,59,1,10526,107,59,1,8618,112,59,1,8620,108,59,1,10565,105,109,59,1,10612,108,59,1,8611,59,1,8605,4,2,97,105,15776,15781,105,108,59,1,10522,111,4,2,59,110,15788,15790,1,8758,97,108,115,59,1,8474,4,3,97,98,114,15804,15809,15814,114,114,59,1,10509,114,107,59,1,10099,4,2,97,107,15820,15833,99,4,2,101,107,15827,15830,59,1,125,59,1,93,4,2,101,115,15839,15842,59,1,10636,108,4,2,100,117,15849,15852,59,1,10638,59,1,10640,4,4,97,101,117,121,15865,15871,15886,15890,114,111,110,59,1,345,4,2,100,105,15877,15882,105,108,59,1,343,108,59,1,8969,98,59,1,125,59,1,1088,4,4,99,108,113,115,15903,15907,15914,15927,97,59,1,10551,100,104,97,114,59,1,10601,117,111,4,2,59,114,15922,15924,1,8221,59,1,8221,104,59,1,8627,4,3,97,99,103,15939,15966,15970,108,4,4,59,105,112,115,15950,15952,15957,15963,1,8476,110,101,59,1,8475,97,114,116,59,1,8476,59,1,8477,116,59,1,9645,5,174,1,59,15975,1,174,4,3,105,108,114,15985,15991,15997,115,104,116,59,1,10621,111,111,114,59,1,8971,59,3,55349,56623,4,2,97,111,16007,16028,114,4,2,100,117,16014,16017,59,1,8641,4,2,59,108,16023,16025,1,8640,59,1,10604,4,2,59,118,16034,16036,1,961,59,1,1009,4,3,103,110,115,16047,16167,16171,104,116,4,6,97,104,108,114,115,116,16063,16081,16103,16130,16143,16155,114,114,111,119,4,2,59,116,16073,16075,1,8594,97,105,108,59,1,8611,97,114,112,111,111,110,4,2,100,117,16093,16099,111,119,110,59,1,8641,112,59,1,8640,101,102,116,4,2,97,104,16112,16120,114,114,111,119,115,59,1,8644,97,114,112,111,111,110,115,59,1,8652,105,103,104,116,97,114,114,111,119,115,59,1,8649,113,117,105,103,97,114,114,111,119,59,1,8605,104,114,101,101,116,105,109,101,115,59,1,8908,103,59,1,730,105,110,103,100,111,116,115,101,113,59,1,8787,4,3,97,104,109,16191,16196,16201,114,114,59,1,8644,97,114,59,1,8652,59,1,8207,111,117,115,116,4,2,59,97,16214,16216,1,9137,99,104,101,59,1,9137,109,105,100,59,1,10990,4,4,97,98,112,116,16238,16252,16257,16278,4,2,110,114,16244,16248,103,59,1,10221,114,59,1,8702,114,107,59,1,10215,4,3,97,102,108,16265,16269,16273,114,59,1,10630,59,3,55349,56675,117,115,59,1,10798,105,109,101,115,59,1,10805,4,2,97,112,16291,16304,114,4,2,59,103,16298,16300,1,41,116,59,1,10644,111,108,105,110,116,59,1,10770,97,114,114,59,1,8649,4,4,97,99,104,113,16328,16334,16339,16342,113,117,111,59,1,8250,114,59,3,55349,56519,59,1,8625,4,2,98,117,16348,16351,59,1,93,111,4,2,59,114,16358,16360,1,8217,59,1,8217,4,3,104,105,114,16371,16377,16383,114,101,101,59,1,8908,109,101,115,59,1,8906,105,4,4,59,101,102,108,16394,16396,16399,16402,1,9657,59,1,8885,59,1,9656,116,114,105,59,1,10702,108,117,104,97,114,59,1,10600,59,1,8478,4,19,97,98,99,100,101,102,104,105,108,109,111,112,113,114,115,116,117,119,122,16459,16466,16472,16572,16590,16672,16687,16746,16844,16850,16924,16963,16988,17115,17121,17154,17206,17614,17656,99,117,116,101,59,1,347,113,117,111,59,1,8218,4,10,59,69,97,99,101,105,110,112,115,121,16494,16496,16499,16513,16518,16531,16536,16556,16564,16569,1,8827,59,1,10932,4,2,112,114,16505,16508,59,1,10936,111,110,59,1,353,117,101,59,1,8829,4,2,59,100,16524,16526,1,10928,105,108,59,1,351,114,99,59,1,349,4,3,69,97,115,16544,16547,16551,59,1,10934,112,59,1,10938,105,109,59,1,8937,111,108,105,110,116,59,1,10771,105,109,59,1,8831,59,1,1089,111,116,4,3,59,98,101,16582,16584,16587,1,8901,59,1,8865,59,1,10854,4,7,65,97,99,109,115,116,120,16606,16611,16634,16642,16646,16652,16668,114,114,59,1,8664,114,4,2,104,114,16618,16622,107,59,1,10533,4,2,59,111,16628,16630,1,8600,119,59,1,8600,116,5,167,1,59,16640,1,167,105,59,1,59,119,97,114,59,1,10537,109,4,2,105,110,16659,16665,110,117,115,59,1,8726,59,1,8726,116,59,1,10038,114,4,2,59,111,16679,16682,3,55349,56624,119,110,59,1,8994,4,4,97,99,111,121,16697,16702,16716,16739,114,112,59,1,9839,4,2,104,121,16708,16713,99,121,59,1,1097,59,1,1096,114,116,4,2,109,112,16724,16729,105,100,59,1,8739,97,114,97,108,108,101,108,59,1,8741,5,173,1,59,16744,1,173,4,2,103,109,16752,16770,109,97,4,3,59,102,118,16762,16764,16767,1,963,59,1,962,59,1,962,4,8,59,100,101,103,108,110,112,114,16788,16790,16795,16806,16817,16828,16832,16838,1,8764,111,116,59,1,10858,4,2,59,113,16801,16803,1,8771,59,1,8771,4,2,59,69,16812,16814,1,10910,59,1,10912,4,2,59,69,16823,16825,1,10909,59,1,10911,101,59,1,8774,108,117,115,59,1,10788,97,114,114,59,1,10610,97,114,114,59,1,8592,4,4,97,101,105,116,16860,16883,16891,16904,4,2,108,115,16866,16878,108,115,101,116,109,105,110,117,115,59,1,8726,104,112,59,1,10803,112,97,114,115,108,59,1,10724,4,2,100,108,16897,16900,59,1,8739,101,59,1,8995,4,2,59,101,16910,16912,1,10922,4,2,59,115,16918,16920,1,10924,59,3,10924,65024,4,3,102,108,112,16932,16938,16958,116,99,121,59,1,1100,4,2,59,98,16944,16946,1,47,4,2,59,97,16952,16954,1,10692,114,59,1,9023,102,59,3,55349,56676,97,4,2,100,114,16970,16985,101,115,4,2,59,117,16978,16980,1,9824,105,116,59,1,9824,59,1,8741,4,3,99,115,117,16996,17028,17089,4,2,97,117,17002,17015,112,4,2,59,115,17009,17011,1,8851,59,3,8851,65024,112,4,2,59,115,17022,17024,1,8852,59,3,8852,65024,117,4,2,98,112,17035,17062,4,3,59,101,115,17043,17045,17048,1,8847,59,1,8849,101,116,4,2,59,101,17056,17058,1,8847,113,59,1,8849,4,3,59,101,115,17070,17072,17075,1,8848,59,1,8850,101,116,4,2,59,101,17083,17085,1,8848,113,59,1,8850,4,3,59,97,102,17097,17099,17112,1,9633,114,4,2,101,102,17106,17109,59,1,9633,59,1,9642,59,1,9642,97,114,114,59,1,8594,4,4,99,101,109,116,17131,17136,17142,17148,114,59,3,55349,56520,116,109,110,59,1,8726,105,108,101,59,1,8995,97,114,102,59,1,8902,4,2,97,114,17160,17172,114,4,2,59,102,17167,17169,1,9734,59,1,9733,4,2,97,110,17178,17202,105,103,104,116,4,2,101,112,17188,17197,112,115,105,108,111,110,59,1,1013,104,105,59,1,981,115,59,1,175,4,5,98,99,109,110,112,17218,17351,17420,17423,17427,4,9,59,69,100,101,109,110,112,114,115,17238,17240,17243,17248,17261,17267,17279,17285,17291,1,8834,59,1,10949,111,116,59,1,10941,4,2,59,100,17254,17256,1,8838,111,116,59,1,10947,117,108,116,59,1,10945,4,2,69,101,17273,17276,59,1,10955,59,1,8842,108,117,115,59,1,10943,97,114,114,59,1,10617,4,3,101,105,117,17299,17335,17339,116,4,3,59,101,110,17308,17310,17322,1,8834,113,4,2,59,113,17317,17319,1,8838,59,1,10949,101,113,4,2,59,113,17330,17332,1,8842,59,1,10955,109,59,1,10951,4,2,98,112,17345,17348,59,1,10965,59,1,10963,99,4,6,59,97,99,101,110,115,17366,17368,17376,17385,17389,17415,1,8827,112,112,114,111,120,59,1,10936,117,114,108,121,101,113,59,1,8829,113,59,1,10928,4,3,97,101,115,17397,17405,17410,112,112,114,111,120,59,1,10938,113,113,59,1,10934,105,109,59,1,8937,105,109,59,1,8831,59,1,8721,103,59,1,9834,4,13,49,50,51,59,69,100,101,104,108,109,110,112,115,17455,17462,17469,17476,17478,17481,17496,17509,17524,17530,17536,17548,17554,5,185,1,59,17460,1,185,5,178,1,59,17467,1,178,5,179,1,59,17474,1,179,1,8835,59,1,10950,4,2,111,115,17487,17491,116,59,1,10942,117,98,59,1,10968,4,2,59,100,17502,17504,1,8839,111,116,59,1,10948,115,4,2,111,117,17516,17520,108,59,1,10185,98,59,1,10967,97,114,114,59,1,10619,117,108,116,59,1,10946,4,2,69,101,17542,17545,59,1,10956,59,1,8843,108,117,115,59,1,10944,4,3,101,105,117,17562,17598,17602,116,4,3,59,101,110,17571,17573,17585,1,8835,113,4,2,59,113,17580,17582,1,8839,59,1,10950,101,113,4,2,59,113,17593,17595,1,8843,59,1,10956,109,59,1,10952,4,2,98,112,17608,17611,59,1,10964,59,1,10966,4,3,65,97,110,17622,17627,17650,114,114,59,1,8665,114,4,2,104,114,17634,17638,107,59,1,10534,4,2,59,111,17644,17646,1,8601,119,59,1,8601,119,97,114,59,1,10538,108,105,103,5,223,1,59,17664,1,223,4,13,97,98,99,100,101,102,104,105,111,112,114,115,119,17694,17709,17714,17737,17742,17749,17754,17860,17905,17957,17964,18090,18122,4,2,114,117,17700,17706,103,101,116,59,1,8982,59,1,964,114,107,59,1,9140,4,3,97,101,121,17722,17728,17734,114,111,110,59,1,357,100,105,108,59,1,355,59,1,1090,111,116,59,1,8411,108,114,101,99,59,1,8981,114,59,3,55349,56625,4,4,101,105,107,111,17764,17805,17836,17851,4,2,114,116,17770,17786,101,4,2,52,102,17777,17780,59,1,8756,111,114,101,59,1,8756,97,4,3,59,115,118,17795,17797,17802,1,952,121,109,59,1,977,59,1,977,4,2,99,110,17811,17831,107,4,2,97,115,17818,17826,112,112,114,111,120,59,1,8776,105,109,59,1,8764,115,112,59,1,8201,4,2,97,115,17842,17846,112,59,1,8776,105,109,59,1,8764,114,110,5,254,1,59,17858,1,254,4,3,108,109,110,17868,17873,17901,100,101,59,1,732,101,115,5,215,3,59,98,100,17884,17886,17898,1,215,4,2,59,97,17892,17894,1,8864,114,59,1,10801,59,1,10800,116,59,1,8749,4,3,101,112,115,17913,17917,17953,97,59,1,10536,4,4,59,98,99,102,17927,17929,17934,17939,1,8868,111,116,59,1,9014,105,114,59,1,10993,4,2,59,111,17945,17948,3,55349,56677,114,107,59,1,10970,97,59,1,10537,114,105,109,101,59,1,8244,4,3,97,105,112,17972,17977,18082,100,101,59,1,8482,4,7,97,100,101,109,112,115,116,17993,18051,18056,18059,18066,18072,18076,110,103,108,101,4,5,59,100,108,113,114,18009,18011,18017,18032,18035,1,9653,111,119,110,59,1,9663,101,102,116,4,2,59,101,18026,18028,1,9667,113,59,1,8884,59,1,8796,105,103,104,116,4,2,59,101,18045,18047,1,9657,113,59,1,8885,111,116,59,1,9708,59,1,8796,105,110,117,115,59,1,10810,108,117,115,59,1,10809,98,59,1,10701,105,109,101,59,1,10811,101,122,105,117,109,59,1,9186,4,3,99,104,116,18098,18111,18116,4,2,114,121,18104,18108,59,3,55349,56521,59,1,1094,99,121,59,1,1115,114,111,107,59,1,359,4,2,105,111,18128,18133,120,116,59,1,8812,104,101,97,100,4,2,108,114,18143,18154,101,102,116,97,114,114,111,119,59,1,8606,105,103,104,116,97,114,114,111,119,59,1,8608,4,18,65,72,97,98,99,100,102,103,104,108,109,111,112,114,115,116,117,119,18204,18209,18214,18234,18250,18268,18292,18308,18319,18343,18379,18397,18413,18504,18547,18553,18584,18603,114,114,59,1,8657,97,114,59,1,10595,4,2,99,114,18220,18230,117,116,101,5,250,1,59,18228,1,250,114,59,1,8593,114,4,2,99,101,18241,18245,121,59,1,1118,118,101,59,1,365,4,2,105,121,18256,18265,114,99,5,251,1,59,18263,1,251,59,1,1091,4,3,97,98,104,18276,18281,18287,114,114,59,1,8645,108,97,99,59,1,369,97,114,59,1,10606,4,2,105,114,18298,18304,115,104,116,59,1,10622,59,3,55349,56626,114,97,118,101,5,249,1,59,18317,1,249,4,2,97,98,18325,18338,114,4,2,108,114,18332,18335,59,1,8639,59,1,8638,108,107,59,1,9600,4,2,99,116,18349,18374,4,2,111,114,18355,18369,114,110,4,2,59,101,18363,18365,1,8988,114,59,1,8988,111,112,59,1,8975,114,105,59,1,9720,4,2,97,108,18385,18390,99,114,59,1,363,5,168,1,59,18395,1,168,4,2,103,112,18403,18408,111,110,59,1,371,102,59,3,55349,56678,4,6,97,100,104,108,115,117,18427,18434,18445,18470,18475,18494,114,114,111,119,59,1,8593,111,119,110,97,114,114,111,119,59,1,8597,97,114,112,111,111,110,4,2,108,114,18457,18463,101,102,116,59,1,8639,105,103,104,116,59,1,8638,117,115,59,1,8846,105,4,3,59,104,108,18484,18486,18489,1,965,59,1,978,111,110,59,1,965,112,97,114,114,111,119,115,59,1,8648,4,3,99,105,116,18512,18537,18542,4,2,111,114,18518,18532,114,110,4,2,59,101,18526,18528,1,8989,114,59,1,8989,111,112,59,1,8974,110,103,59,1,367,114,105,59,1,9721,99,114,59,3,55349,56522,4,3,100,105,114,18561,18566,18572,111,116,59,1,8944,108,100,101,59,1,361,105,4,2,59,102,18579,18581,1,9653,59,1,9652,4,2,97,109,18590,18595,114,114,59,1,8648,108,5,252,1,59,18601,1,252,97,110,103,108,101,59,1,10663,4,15,65,66,68,97,99,100,101,102,108,110,111,112,114,115,122,18643,18648,18661,18667,18847,18851,18857,18904,18909,18915,18931,18937,18943,18949,18996,114,114,59,1,8661,97,114,4,2,59,118,18656,18658,1,10984,59,1,10985,97,115,104,59,1,8872,4,2,110,114,18673,18679,103,114,116,59,1,10652,4,7,101,107,110,112,114,115,116,18695,18704,18711,18720,18742,18754,18810,112,115,105,108,111,110,59,1,1013,97,112,112,97,59,1,1008,111,116,104,105,110,103,59,1,8709,4,3,104,105,114,18728,18732,18735,105,59,1,981,59,1,982,111,112,116,111,59,1,8733,4,2,59,104,18748,18750,1,8597,111,59,1,1009,4,2,105,117,18760,18766,103,109,97,59,1,962,4,2,98,112,18772,18791,115,101,116,110,101,113,4,2,59,113,18784,18787,3,8842,65024,59,3,10955,65024,115,101,116,110,101,113,4,2,59,113,18803,18806,3,8843,65024,59,3,10956,65024,4,2,104,114,18816,18822,101,116,97,59,1,977,105,97,110,103,108,101,4,2,108,114,18834,18840,101,102,116,59,1,8882,105,103,104,116,59,1,8883,121,59,1,1074,97,115,104,59,1,8866,4,3,101,108,114,18865,18884,18890,4,3,59,98,101,18873,18875,18880,1,8744,97,114,59,1,8891,113,59,1,8794,108,105,112,59,1,8942,4,2,98,116,18896,18901,97,114,59,1,124,59,1,124,114,59,3,55349,56627,116,114,105,59,1,8882,115,117,4,2,98,112,18923,18927,59,3,8834,8402,59,3,8835,8402,112,102,59,3,55349,56679,114,111,112,59,1,8733,116,114,105,59,1,8883,4,2,99,117,18955,18960,114,59,3,55349,56523,4,2,98,112,18966,18981,110,4,2,69,101,18973,18977,59,3,10955,65024,59,3,8842,65024,110,4,2,69,101,18988,18992,59,3,10956,65024,59,3,8843,65024,105,103,122,97,103,59,1,10650,4,7,99,101,102,111,112,114,115,19020,19026,19061,19066,19072,19075,19089,105,114,99,59,1,373,4,2,100,105,19032,19055,4,2,98,103,19038,19043,97,114,59,1,10847,101,4,2,59,113,19050,19052,1,8743,59,1,8793,101,114,112,59,1,8472,114,59,3,55349,56628,112,102,59,3,55349,56680,59,1,8472,4,2,59,101,19081,19083,1,8768,97,116,104,59,1,8768,99,114,59,3,55349,56524,4,14,99,100,102,104,105,108,109,110,111,114,115,117,118,119,19125,19146,19152,19157,19173,19176,19192,19197,19202,19236,19252,19269,19286,19291,4,3,97,105,117,19133,19137,19142,112,59,1,8898,114,99,59,1,9711,112,59,1,8899,116,114,105,59,1,9661,114,59,3,55349,56629,4,2,65,97,19163,19168,114,114,59,1,10234,114,114,59,1,10231,59,1,958,4,2,65,97,19182,19187,114,114,59,1,10232,114,114,59,1,10229,97,112,59,1,10236,105,115,59,1,8955,4,3,100,112,116,19210,19215,19230,111,116,59,1,10752,4,2,102,108,19221,19225,59,3,55349,56681,117,115,59,1,10753,105,109,101,59,1,10754,4,2,65,97,19242,19247,114,114,59,1,10233,114,114,59,1,10230,4,2,99,113,19258,19263,114,59,3,55349,56525,99,117,112,59,1,10758,4,2,112,116,19275,19281,108,117,115,59,1,10756,114,105,59,1,9651,101,101,59,1,8897,101,100,103,101,59,1,8896,4,8,97,99,101,102,105,111,115,117,19316,19335,19349,19357,19362,19367,19373,19379,99,4,2,117,121,19323,19332,116,101,5,253,1,59,19330,1,253,59,1,1103,4,2,105,121,19341,19346,114,99,59,1,375,59,1,1099,110,5,165,1,59,19355,1,165,114,59,3,55349,56630,99,121,59,1,1111,112,102,59,3,55349,56682,99,114,59,3,55349,56526,4,2,99,109,19385,19389,121,59,1,1102,108,5,255,1,59,19395,1,255,4,10,97,99,100,101,102,104,105,111,115,119,19419,19426,19441,19446,19462,19467,19472,19480,19486,19492,99,117,116,101,59,1,378,4,2,97,121,19432,19438,114,111,110,59,1,382,59,1,1079,111,116,59,1,380,4,2,101,116,19452,19458,116,114,102,59,1,8488,97,59,1,950,114,59,3,55349,56631,99,121,59,1,1078,103,114,97,114,114,59,1,8669,112,102,59,3,55349,56683,99,114,59,3,55349,56527,4,2,106,110,19498,19501,59,1,8205,106,59,1,8204]);
  
  //Aliases
  const $$1 = unicode.CODE_POINTS;
  const $$ = unicode.CODE_POINT_SEQUENCES;
  
  //C1 Unicode control character reference replacements
  const C1_CONTROLS_REFERENCE_REPLACEMENTS = {
      0x80: 0x20ac,
      0x82: 0x201a,
      0x83: 0x0192,
      0x84: 0x201e,
      0x85: 0x2026,
      0x86: 0x2020,
      0x87: 0x2021,
      0x88: 0x02c6,
      0x89: 0x2030,
      0x8a: 0x0160,
      0x8b: 0x2039,
      0x8c: 0x0152,
      0x8e: 0x017d,
      0x91: 0x2018,
      0x92: 0x2019,
      0x93: 0x201c,
      0x94: 0x201d,
      0x95: 0x2022,
      0x96: 0x2013,
      0x97: 0x2014,
      0x98: 0x02dc,
      0x99: 0x2122,
      0x9a: 0x0161,
      0x9b: 0x203a,
      0x9c: 0x0153,
      0x9e: 0x017e,
      0x9f: 0x0178
  };
  
  // Named entity tree flags
  const HAS_DATA_FLAG = 1 << 0;
  const DATA_DUPLET_FLAG = 1 << 1;
  const HAS_BRANCHES_FLAG = 1 << 2;
  const MAX_BRANCH_MARKER_VALUE = HAS_DATA_FLAG | DATA_DUPLET_FLAG | HAS_BRANCHES_FLAG;
  
  //States
  const DATA_STATE = 'DATA_STATE';
  const RCDATA_STATE = 'RCDATA_STATE';
  const RAWTEXT_STATE = 'RAWTEXT_STATE';
  const SCRIPT_DATA_STATE = 'SCRIPT_DATA_STATE';
  const PLAINTEXT_STATE = 'PLAINTEXT_STATE';
  const TAG_OPEN_STATE = 'TAG_OPEN_STATE';
  const END_TAG_OPEN_STATE = 'END_TAG_OPEN_STATE';
  const TAG_NAME_STATE = 'TAG_NAME_STATE';
  const RCDATA_LESS_THAN_SIGN_STATE = 'RCDATA_LESS_THAN_SIGN_STATE';
  const RCDATA_END_TAG_OPEN_STATE = 'RCDATA_END_TAG_OPEN_STATE';
  const RCDATA_END_TAG_NAME_STATE = 'RCDATA_END_TAG_NAME_STATE';
  const RAWTEXT_LESS_THAN_SIGN_STATE = 'RAWTEXT_LESS_THAN_SIGN_STATE';
  const RAWTEXT_END_TAG_OPEN_STATE = 'RAWTEXT_END_TAG_OPEN_STATE';
  const RAWTEXT_END_TAG_NAME_STATE = 'RAWTEXT_END_TAG_NAME_STATE';
  const SCRIPT_DATA_LESS_THAN_SIGN_STATE = 'SCRIPT_DATA_LESS_THAN_SIGN_STATE';
  const SCRIPT_DATA_END_TAG_OPEN_STATE = 'SCRIPT_DATA_END_TAG_OPEN_STATE';
  const SCRIPT_DATA_END_TAG_NAME_STATE = 'SCRIPT_DATA_END_TAG_NAME_STATE';
  const SCRIPT_DATA_ESCAPE_START_STATE = 'SCRIPT_DATA_ESCAPE_START_STATE';
  const SCRIPT_DATA_ESCAPE_START_DASH_STATE = 'SCRIPT_DATA_ESCAPE_START_DASH_STATE';
  const SCRIPT_DATA_ESCAPED_STATE = 'SCRIPT_DATA_ESCAPED_STATE';
  const SCRIPT_DATA_ESCAPED_DASH_STATE = 'SCRIPT_DATA_ESCAPED_DASH_STATE';
  const SCRIPT_DATA_ESCAPED_DASH_DASH_STATE = 'SCRIPT_DATA_ESCAPED_DASH_DASH_STATE';
  const SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE = 'SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE';
  const SCRIPT_DATA_ESCAPED_END_TAG_OPEN_STATE = 'SCRIPT_DATA_ESCAPED_END_TAG_OPEN_STATE';
  const SCRIPT_DATA_ESCAPED_END_TAG_NAME_STATE = 'SCRIPT_DATA_ESCAPED_END_TAG_NAME_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPE_START_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPE_START_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPED_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPED_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPED_DASH_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPED_DASH_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE';
  const SCRIPT_DATA_DOUBLE_ESCAPE_END_STATE = 'SCRIPT_DATA_DOUBLE_ESCAPE_END_STATE';
  const BEFORE_ATTRIBUTE_NAME_STATE = 'BEFORE_ATTRIBUTE_NAME_STATE';
  const ATTRIBUTE_NAME_STATE = 'ATTRIBUTE_NAME_STATE';
  const AFTER_ATTRIBUTE_NAME_STATE = 'AFTER_ATTRIBUTE_NAME_STATE';
  const BEFORE_ATTRIBUTE_VALUE_STATE = 'BEFORE_ATTRIBUTE_VALUE_STATE';
  const ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE = 'ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE';
  const ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE = 'ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE';
  const ATTRIBUTE_VALUE_UNQUOTED_STATE = 'ATTRIBUTE_VALUE_UNQUOTED_STATE';
  const AFTER_ATTRIBUTE_VALUE_QUOTED_STATE = 'AFTER_ATTRIBUTE_VALUE_QUOTED_STATE';
  const SELF_CLOSING_START_TAG_STATE = 'SELF_CLOSING_START_TAG_STATE';
  const BOGUS_COMMENT_STATE = 'BOGUS_COMMENT_STATE';
  const MARKUP_DECLARATION_OPEN_STATE = 'MARKUP_DECLARATION_OPEN_STATE';
  const COMMENT_START_STATE = 'COMMENT_START_STATE';
  const COMMENT_START_DASH_STATE = 'COMMENT_START_DASH_STATE';
  const COMMENT_STATE = 'COMMENT_STATE';
  const COMMENT_LESS_THAN_SIGN_STATE = 'COMMENT_LESS_THAN_SIGN_STATE';
  const COMMENT_LESS_THAN_SIGN_BANG_STATE = 'COMMENT_LESS_THAN_SIGN_BANG_STATE';
  const COMMENT_LESS_THAN_SIGN_BANG_DASH_STATE = 'COMMENT_LESS_THAN_SIGN_BANG_DASH_STATE';
  const COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH_STATE = 'COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH_STATE';
  const COMMENT_END_DASH_STATE = 'COMMENT_END_DASH_STATE';
  const COMMENT_END_STATE = 'COMMENT_END_STATE';
  const COMMENT_END_BANG_STATE = 'COMMENT_END_BANG_STATE';
  const DOCTYPE_STATE = 'DOCTYPE_STATE';
  const BEFORE_DOCTYPE_NAME_STATE = 'BEFORE_DOCTYPE_NAME_STATE';
  const DOCTYPE_NAME_STATE = 'DOCTYPE_NAME_STATE';
  const AFTER_DOCTYPE_NAME_STATE = 'AFTER_DOCTYPE_NAME_STATE';
  const AFTER_DOCTYPE_PUBLIC_KEYWORD_STATE = 'AFTER_DOCTYPE_PUBLIC_KEYWORD_STATE';
  const BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE = 'BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE';
  const DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE = 'DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE';
  const DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE = 'DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE';
  const AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE = 'AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE';
  const BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS_STATE = 'BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS_STATE';
  const AFTER_DOCTYPE_SYSTEM_KEYWORD_STATE = 'AFTER_DOCTYPE_SYSTEM_KEYWORD_STATE';
  const BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE = 'BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE';
  const DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE = 'DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE';
  const DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE = 'DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE';
  const AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE = 'AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE';
  const BOGUS_DOCTYPE_STATE = 'BOGUS_DOCTYPE_STATE';
  const CDATA_SECTION_STATE = 'CDATA_SECTION_STATE';
  const CDATA_SECTION_BRACKET_STATE = 'CDATA_SECTION_BRACKET_STATE';
  const CDATA_SECTION_END_STATE = 'CDATA_SECTION_END_STATE';
  const CHARACTER_REFERENCE_STATE = 'CHARACTER_REFERENCE_STATE';
  const NAMED_CHARACTER_REFERENCE_STATE = 'NAMED_CHARACTER_REFERENCE_STATE';
  const AMBIGUOUS_AMPERSAND_STATE = 'AMBIGUOS_AMPERSAND_STATE';
  const NUMERIC_CHARACTER_REFERENCE_STATE = 'NUMERIC_CHARACTER_REFERENCE_STATE';
  const HEXADEMICAL_CHARACTER_REFERENCE_START_STATE = 'HEXADEMICAL_CHARACTER_REFERENCE_START_STATE';
  const DECIMAL_CHARACTER_REFERENCE_START_STATE = 'DECIMAL_CHARACTER_REFERENCE_START_STATE';
  const HEXADEMICAL_CHARACTER_REFERENCE_STATE = 'HEXADEMICAL_CHARACTER_REFERENCE_STATE';
  const DECIMAL_CHARACTER_REFERENCE_STATE = 'DECIMAL_CHARACTER_REFERENCE_STATE';
  const NUMERIC_CHARACTER_REFERENCE_END_STATE = 'NUMERIC_CHARACTER_REFERENCE_END_STATE';
  
  //Utils
  
  //OPTIMIZATION: these utility functions should not be moved out of this module. V8 Crankshaft will not inline
  //this functions if they will be situated in another module due to context switch.
  //Always perform inlining check before modifying this functions ('node --trace-inlining').
  function isWhitespace(cp) {
      return cp === $$1.SPACE || cp === $$1.LINE_FEED || cp === $$1.TABULATION || cp === $$1.FORM_FEED;
  }
  
  function isAsciiDigit(cp) {
      return cp >= $$1.DIGIT_0 && cp <= $$1.DIGIT_9;
  }
  
  function isAsciiUpper(cp) {
      return cp >= $$1.LATIN_CAPITAL_A && cp <= $$1.LATIN_CAPITAL_Z;
  }
  
  function isAsciiLower(cp) {
      return cp >= $$1.LATIN_SMALL_A && cp <= $$1.LATIN_SMALL_Z;
  }
  
  function isAsciiLetter(cp) {
      return isAsciiLower(cp) || isAsciiUpper(cp);
  }
  
  function isAsciiAlphaNumeric(cp) {
      return isAsciiLetter(cp) || isAsciiDigit(cp);
  }
  
  function isAsciiUpperHexDigit(cp) {
      return cp >= $$1.LATIN_CAPITAL_A && cp <= $$1.LATIN_CAPITAL_F;
  }
  
  function isAsciiLowerHexDigit(cp) {
      return cp >= $$1.LATIN_SMALL_A && cp <= $$1.LATIN_SMALL_F;
  }
  
  function isAsciiHexDigit(cp) {
      return isAsciiDigit(cp) || isAsciiUpperHexDigit(cp) || isAsciiLowerHexDigit(cp);
  }
  
  function toAsciiLowerCodePoint(cp) {
      return cp + 0x0020;
  }
  
  //NOTE: String.fromCharCode() function can handle only characters from BMP subset.
  //So, we need to workaround this manually.
  //(see: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/fromCharCode#Getting_it_to_work_with_higher_values)
  function toChar(cp) {
      if (cp <= 0xffff) {
          return String.fromCharCode(cp);
      }
  
      cp -= 0x10000;
      return String.fromCharCode(((cp >>> 10) & 0x3ff) | 0xd800) + String.fromCharCode(0xdc00 | (cp & 0x3ff));
  }
  
  function toAsciiLowerChar(cp) {
      return String.fromCharCode(toAsciiLowerCodePoint(cp));
  }
  
  function findNamedEntityTreeBranch(nodeIx, cp) {
      const branchCount = namedEntityData[++nodeIx];
      let lo = ++nodeIx;
      let hi = lo + branchCount - 1;
  
      while (lo <= hi) {
          const mid = (lo + hi) >>> 1;
          const midCp = namedEntityData[mid];
  
          if (midCp < cp) {
              lo = mid + 1;
          } else if (midCp > cp) {
              hi = mid - 1;
          } else {
              return namedEntityData[mid + branchCount];
          }
      }
  
      return -1;
  }
  
  //Tokenizer
  class Tokenizer {
      constructor() {
          this.preprocessor = new preprocessor();
  
          this.tokenQueue = [];
  
          this.allowCDATA = false;
  
          this.state = DATA_STATE;
          this.returnState = '';
  
          this.charRefCode = -1;
          this.tempBuff = [];
          this.lastStartTagName = '';
  
          this.consumedAfterSnapshot = -1;
          this.active = false;
  
          this.currentCharacterToken = null;
          this.currentToken = null;
          this.currentAttr = null;
      }
  
      //Errors
      _err() {
          // NOTE: err reporting is noop by default. Enabled by mixin.
      }
  
      _errOnNextCodePoint(err) {
          this._consume();
          this._err(err);
          this._unconsume();
      }
  
      //API
      getNextToken() {
          while (!this.tokenQueue.length && this.active) {
              this.consumedAfterSnapshot = 0;
  
              const cp = this._consume();
  
              if (!this._ensureHibernation()) {
                  this[this.state](cp);
              }
          }
  
          return this.tokenQueue.shift();
      }
  
      write(chunk, isLastChunk) {
          this.active = true;
          this.preprocessor.write(chunk, isLastChunk);
      }
  
      insertHtmlAtCurrentPos(chunk) {
          this.active = true;
          this.preprocessor.insertHtmlAtCurrentPos(chunk);
      }
  
      //Hibernation
      _ensureHibernation() {
          if (this.preprocessor.endOfChunkHit) {
              for (; this.consumedAfterSnapshot > 0; this.consumedAfterSnapshot--) {
                  this.preprocessor.retreat();
              }
  
              this.active = false;
              this.tokenQueue.push({ type: Tokenizer.HIBERNATION_TOKEN });
  
              return true;
          }
  
          return false;
      }
  
      //Consumption
      _consume() {
          this.consumedAfterSnapshot++;
          return this.preprocessor.advance();
      }
  
      _unconsume() {
          this.consumedAfterSnapshot--;
          this.preprocessor.retreat();
      }
  
      _reconsumeInState(state) {
          this.state = state;
          this._unconsume();
      }
  
      _consumeSequenceIfMatch(pattern, startCp, caseSensitive) {
          let consumedCount = 0;
          let isMatch = true;
          const patternLength = pattern.length;
          let patternPos = 0;
          let cp = startCp;
          let patternCp = void 0;
  
          for (; patternPos < patternLength; patternPos++) {
              if (patternPos > 0) {
                  cp = this._consume();
                  consumedCount++;
              }
  
              if (cp === $$1.EOF) {
                  isMatch = false;
                  break;
              }
  
              patternCp = pattern[patternPos];
  
              if (cp !== patternCp && (caseSensitive || cp !== toAsciiLowerCodePoint(patternCp))) {
                  isMatch = false;
                  break;
              }
          }
  
          if (!isMatch) {
              while (consumedCount--) {
                  this._unconsume();
              }
          }
  
          return isMatch;
      }
  
      //Temp buffer
      _isTempBufferEqualToScriptString() {
          if (this.tempBuff.length !== $$.SCRIPT_STRING.length) {
              return false;
          }
  
          for (let i = 0; i < this.tempBuff.length; i++) {
              if (this.tempBuff[i] !== $$.SCRIPT_STRING[i]) {
                  return false;
              }
          }
  
          return true;
      }
  
      //Token creation
      _createStartTagToken() {
          this.currentToken = {
              type: Tokenizer.START_TAG_TOKEN,
              tagName: '',
              selfClosing: false,
              ackSelfClosing: false,
              attrs: []
          };
      }
  
      _createEndTagToken() {
          this.currentToken = {
              type: Tokenizer.END_TAG_TOKEN,
              tagName: '',
              selfClosing: false,
              attrs: []
          };
      }
  
      _createCommentToken() {
          this.currentToken = {
              type: Tokenizer.COMMENT_TOKEN,
              data: ''
          };
      }
  
      _createDoctypeToken(initialName) {
          this.currentToken = {
              type: Tokenizer.DOCTYPE_TOKEN,
              name: initialName,
              forceQuirks: false,
              publicId: null,
              systemId: null
          };
      }
  
      _createCharacterToken(type, ch) {
          this.currentCharacterToken = {
              type: type,
              chars: ch
          };
      }
  
      _createEOFToken() {
          this.currentToken = { type: Tokenizer.EOF_TOKEN };
      }
  
      //Tag attributes
      _createAttr(attrNameFirstCh) {
          this.currentAttr = {
              name: attrNameFirstCh,
              value: ''
          };
      }
  
      _leaveAttrName(toState) {
          if (Tokenizer.getTokenAttr(this.currentToken, this.currentAttr.name) === null) {
              this.currentToken.attrs.push(this.currentAttr);
          } else {
              this._err(errorCodes.duplicateAttribute);
          }
  
          this.state = toState;
      }
  
      _leaveAttrValue(toState) {
          this.state = toState;
      }
  
      //Token emission
      _emitCurrentToken() {
          this._emitCurrentCharacterToken();
  
          const ct = this.currentToken;
  
          this.currentToken = null;
  
          //NOTE: store emited start tag's tagName to determine is the following end tag token is appropriate.
          if (ct.type === Tokenizer.START_TAG_TOKEN) {
              this.lastStartTagName = ct.tagName;
          } else if (ct.type === Tokenizer.END_TAG_TOKEN) {
              if (ct.attrs.length > 0) {
                  this._err(errorCodes.endTagWithAttributes);
              }
  
              if (ct.selfClosing) {
                  this._err(errorCodes.endTagWithTrailingSolidus);
              }
          }
  
          this.tokenQueue.push(ct);
      }
  
      _emitCurrentCharacterToken() {
          if (this.currentCharacterToken) {
              this.tokenQueue.push(this.currentCharacterToken);
              this.currentCharacterToken = null;
          }
      }
  
      _emitEOFToken() {
          this._createEOFToken();
          this._emitCurrentToken();
      }
  
      //Characters emission
  
      //OPTIMIZATION: specification uses only one type of character tokens (one token per character).
      //This causes a huge memory overhead and a lot of unnecessary parser loops. parse5 uses 3 groups of characters.
      //If we have a sequence of characters that belong to the same group, parser can process it
      //as a single solid character token.
      //So, there are 3 types of character tokens in parse5:
      //1)NULL_CHARACTER_TOKEN - \u0000-character sequences (e.g. '\u0000\u0000\u0000')
      //2)WHITESPACE_CHARACTER_TOKEN - any whitespace/new-line character sequences (e.g. '\n  \r\t   \f')
      //3)CHARACTER_TOKEN - any character sequence which don't belong to groups 1 and 2 (e.g. 'abcdef1234@@#$%^')
      _appendCharToCurrentCharacterToken(type, ch) {
          if (this.currentCharacterToken && this.currentCharacterToken.type !== type) {
              this._emitCurrentCharacterToken();
          }
  
          if (this.currentCharacterToken) {
              this.currentCharacterToken.chars += ch;
          } else {
              this._createCharacterToken(type, ch);
          }
      }
  
      _emitCodePoint(cp) {
          let type = Tokenizer.CHARACTER_TOKEN;
  
          if (isWhitespace(cp)) {
              type = Tokenizer.WHITESPACE_CHARACTER_TOKEN;
          } else if (cp === $$1.NULL) {
              type = Tokenizer.NULL_CHARACTER_TOKEN;
          }
  
          this._appendCharToCurrentCharacterToken(type, toChar(cp));
      }
  
      _emitSeveralCodePoints(codePoints) {
          for (let i = 0; i < codePoints.length; i++) {
              this._emitCodePoint(codePoints[i]);
          }
      }
  
      //NOTE: used then we emit character explicitly. This is always a non-whitespace and a non-null character.
      //So we can avoid additional checks here.
      _emitChars(ch) {
          this._appendCharToCurrentCharacterToken(Tokenizer.CHARACTER_TOKEN, ch);
      }
  
      // Character reference helpers
      _matchNamedCharacterReference(startCp) {
          let result = null;
          let excess = 1;
          let i = findNamedEntityTreeBranch(0, startCp);
  
          this.tempBuff.push(startCp);
  
          while (i > -1) {
              const current = namedEntityData[i];
              const inNode = current < MAX_BRANCH_MARKER_VALUE;
              const nodeWithData = inNode && current & HAS_DATA_FLAG;
  
              if (nodeWithData) {
                  //NOTE: we use greedy search, so we continue lookup at this point
                  result = current & DATA_DUPLET_FLAG ? [namedEntityData[++i], namedEntityData[++i]] : [namedEntityData[++i]];
                  excess = 0;
              }
  
              const cp = this._consume();
  
              this.tempBuff.push(cp);
              excess++;
  
              if (cp === $$1.EOF) {
                  break;
              }
  
              if (inNode) {
                  i = current & HAS_BRANCHES_FLAG ? findNamedEntityTreeBranch(i, cp) : -1;
              } else {
                  i = cp === current ? ++i : -1;
              }
          }
  
          while (excess--) {
              this.tempBuff.pop();
              this._unconsume();
          }
  
          return result;
      }
  
      _isCharacterReferenceInAttribute() {
          return (
              this.returnState === ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE ||
              this.returnState === ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE ||
              this.returnState === ATTRIBUTE_VALUE_UNQUOTED_STATE
          );
      }
  
      _isCharacterReferenceAttributeQuirk(withSemicolon) {
          if (!withSemicolon && this._isCharacterReferenceInAttribute()) {
              const nextCp = this._consume();
  
              this._unconsume();
  
              return nextCp === $$1.EQUALS_SIGN || isAsciiAlphaNumeric(nextCp);
          }
  
          return false;
      }
  
      _flushCodePointsConsumedAsCharacterReference() {
          if (this._isCharacterReferenceInAttribute()) {
              for (let i = 0; i < this.tempBuff.length; i++) {
                  this.currentAttr.value += toChar(this.tempBuff[i]);
              }
          } else {
              this._emitSeveralCodePoints(this.tempBuff);
          }
  
          this.tempBuff = [];
      }
  
      // State machine
  
      // Data state
      //------------------------------------------------------------------
      [DATA_STATE](cp) {
          this.preprocessor.dropParsedChunk();
  
          if (cp === $$1.LESS_THAN_SIGN) {
              this.state = TAG_OPEN_STATE;
          } else if (cp === $$1.AMPERSAND) {
              this.returnState = DATA_STATE;
              this.state = CHARACTER_REFERENCE_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitCodePoint(cp);
          } else if (cp === $$1.EOF) {
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      //  RCDATA state
      //------------------------------------------------------------------
      [RCDATA_STATE](cp) {
          this.preprocessor.dropParsedChunk();
  
          if (cp === $$1.AMPERSAND) {
              this.returnState = RCDATA_STATE;
              this.state = CHARACTER_REFERENCE_STATE;
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = RCDATA_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // RAWTEXT state
      //------------------------------------------------------------------
      [RAWTEXT_STATE](cp) {
          this.preprocessor.dropParsedChunk();
  
          if (cp === $$1.LESS_THAN_SIGN) {
              this.state = RAWTEXT_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // Script data state
      //------------------------------------------------------------------
      [SCRIPT_DATA_STATE](cp) {
          this.preprocessor.dropParsedChunk();
  
          if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // PLAINTEXT state
      //------------------------------------------------------------------
      [PLAINTEXT_STATE](cp) {
          this.preprocessor.dropParsedChunk();
  
          if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // Tag open state
      //------------------------------------------------------------------
      [TAG_OPEN_STATE](cp) {
          if (cp === $$1.EXCLAMATION_MARK) {
              this.state = MARKUP_DECLARATION_OPEN_STATE;
          } else if (cp === $$1.SOLIDUS) {
              this.state = END_TAG_OPEN_STATE;
          } else if (isAsciiLetter(cp)) {
              this._createStartTagToken();
              this._reconsumeInState(TAG_NAME_STATE);
          } else if (cp === $$1.QUESTION_MARK) {
              this._err(errorCodes.unexpectedQuestionMarkInsteadOfTagName);
              this._createCommentToken();
              this._reconsumeInState(BOGUS_COMMENT_STATE);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofBeforeTagName);
              this._emitChars('<');
              this._emitEOFToken();
          } else {
              this._err(errorCodes.invalidFirstCharacterOfTagName);
              this._emitChars('<');
              this._reconsumeInState(DATA_STATE);
          }
      }
  
      // End tag open state
      //------------------------------------------------------------------
      [END_TAG_OPEN_STATE](cp) {
          if (isAsciiLetter(cp)) {
              this._createEndTagToken();
              this._reconsumeInState(TAG_NAME_STATE);
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingEndTagName);
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofBeforeTagName);
              this._emitChars('</');
              this._emitEOFToken();
          } else {
              this._err(errorCodes.invalidFirstCharacterOfTagName);
              this._createCommentToken();
              this._reconsumeInState(BOGUS_COMMENT_STATE);
          }
      }
  
      // Tag name state
      //------------------------------------------------------------------
      [TAG_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = BEFORE_ATTRIBUTE_NAME_STATE;
          } else if (cp === $$1.SOLIDUS) {
              this.state = SELF_CLOSING_START_TAG_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (isAsciiUpper(cp)) {
              this.currentToken.tagName += toAsciiLowerChar(cp);
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.tagName += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this.currentToken.tagName += toChar(cp);
          }
      }
  
      // RCDATA less-than sign state
      //------------------------------------------------------------------
      [RCDATA_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.SOLIDUS) {
              this.tempBuff = [];
              this.state = RCDATA_END_TAG_OPEN_STATE;
          } else {
              this._emitChars('<');
              this._reconsumeInState(RCDATA_STATE);
          }
      }
  
      // RCDATA end tag open state
      //------------------------------------------------------------------
      [RCDATA_END_TAG_OPEN_STATE](cp) {
          if (isAsciiLetter(cp)) {
              this._createEndTagToken();
              this._reconsumeInState(RCDATA_END_TAG_NAME_STATE);
          } else {
              this._emitChars('</');
              this._reconsumeInState(RCDATA_STATE);
          }
      }
  
      // RCDATA end tag name state
      //------------------------------------------------------------------
      [RCDATA_END_TAG_NAME_STATE](cp) {
          if (isAsciiUpper(cp)) {
              this.currentToken.tagName += toAsciiLowerChar(cp);
              this.tempBuff.push(cp);
          } else if (isAsciiLower(cp)) {
              this.currentToken.tagName += toChar(cp);
              this.tempBuff.push(cp);
          } else {
              if (this.lastStartTagName === this.currentToken.tagName) {
                  if (isWhitespace(cp)) {
                      this.state = BEFORE_ATTRIBUTE_NAME_STATE;
                      return;
                  }
  
                  if (cp === $$1.SOLIDUS) {
                      this.state = SELF_CLOSING_START_TAG_STATE;
                      return;
                  }
  
                  if (cp === $$1.GREATER_THAN_SIGN) {
                      this.state = DATA_STATE;
                      this._emitCurrentToken();
                      return;
                  }
              }
  
              this._emitChars('</');
              this._emitSeveralCodePoints(this.tempBuff);
              this._reconsumeInState(RCDATA_STATE);
          }
      }
  
      // RAWTEXT less-than sign state
      //------------------------------------------------------------------
      [RAWTEXT_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.SOLIDUS) {
              this.tempBuff = [];
              this.state = RAWTEXT_END_TAG_OPEN_STATE;
          } else {
              this._emitChars('<');
              this._reconsumeInState(RAWTEXT_STATE);
          }
      }
  
      // RAWTEXT end tag open state
      //------------------------------------------------------------------
      [RAWTEXT_END_TAG_OPEN_STATE](cp) {
          if (isAsciiLetter(cp)) {
              this._createEndTagToken();
              this._reconsumeInState(RAWTEXT_END_TAG_NAME_STATE);
          } else {
              this._emitChars('</');
              this._reconsumeInState(RAWTEXT_STATE);
          }
      }
  
      // RAWTEXT end tag name state
      //------------------------------------------------------------------
      [RAWTEXT_END_TAG_NAME_STATE](cp) {
          if (isAsciiUpper(cp)) {
              this.currentToken.tagName += toAsciiLowerChar(cp);
              this.tempBuff.push(cp);
          } else if (isAsciiLower(cp)) {
              this.currentToken.tagName += toChar(cp);
              this.tempBuff.push(cp);
          } else {
              if (this.lastStartTagName === this.currentToken.tagName) {
                  if (isWhitespace(cp)) {
                      this.state = BEFORE_ATTRIBUTE_NAME_STATE;
                      return;
                  }
  
                  if (cp === $$1.SOLIDUS) {
                      this.state = SELF_CLOSING_START_TAG_STATE;
                      return;
                  }
  
                  if (cp === $$1.GREATER_THAN_SIGN) {
                      this._emitCurrentToken();
                      this.state = DATA_STATE;
                      return;
                  }
              }
  
              this._emitChars('</');
              this._emitSeveralCodePoints(this.tempBuff);
              this._reconsumeInState(RAWTEXT_STATE);
          }
      }
  
      // Script data less-than sign state
      //------------------------------------------------------------------
      [SCRIPT_DATA_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.SOLIDUS) {
              this.tempBuff = [];
              this.state = SCRIPT_DATA_END_TAG_OPEN_STATE;
          } else if (cp === $$1.EXCLAMATION_MARK) {
              this.state = SCRIPT_DATA_ESCAPE_START_STATE;
              this._emitChars('<!');
          } else {
              this._emitChars('<');
              this._reconsumeInState(SCRIPT_DATA_STATE);
          }
      }
  
      // Script data end tag open state
      //------------------------------------------------------------------
      [SCRIPT_DATA_END_TAG_OPEN_STATE](cp) {
          if (isAsciiLetter(cp)) {
              this._createEndTagToken();
              this._reconsumeInState(SCRIPT_DATA_END_TAG_NAME_STATE);
          } else {
              this._emitChars('</');
              this._reconsumeInState(SCRIPT_DATA_STATE);
          }
      }
  
      // Script data end tag name state
      //------------------------------------------------------------------
      [SCRIPT_DATA_END_TAG_NAME_STATE](cp) {
          if (isAsciiUpper(cp)) {
              this.currentToken.tagName += toAsciiLowerChar(cp);
              this.tempBuff.push(cp);
          } else if (isAsciiLower(cp)) {
              this.currentToken.tagName += toChar(cp);
              this.tempBuff.push(cp);
          } else {
              if (this.lastStartTagName === this.currentToken.tagName) {
                  if (isWhitespace(cp)) {
                      this.state = BEFORE_ATTRIBUTE_NAME_STATE;
                      return;
                  } else if (cp === $$1.SOLIDUS) {
                      this.state = SELF_CLOSING_START_TAG_STATE;
                      return;
                  } else if (cp === $$1.GREATER_THAN_SIGN) {
                      this._emitCurrentToken();
                      this.state = DATA_STATE;
                      return;
                  }
              }
  
              this._emitChars('</');
              this._emitSeveralCodePoints(this.tempBuff);
              this._reconsumeInState(SCRIPT_DATA_STATE);
          }
      }
  
      // Script data escape start state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPE_START_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_ESCAPE_START_DASH_STATE;
              this._emitChars('-');
          } else {
              this._reconsumeInState(SCRIPT_DATA_STATE);
          }
      }
  
      // Script data escape start dash state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPE_START_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_ESCAPED_DASH_DASH_STATE;
              this._emitChars('-');
          } else {
              this._reconsumeInState(SCRIPT_DATA_STATE);
          }
      }
  
      // Script data escaped state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_ESCAPED_DASH_STATE;
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // Script data escaped dash state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_ESCAPED_DASH_DASH_STATE;
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.state = SCRIPT_DATA_ESCAPED_STATE;
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this.state = SCRIPT_DATA_ESCAPED_STATE;
              this._emitCodePoint(cp);
          }
      }
  
      // Script data escaped dash dash state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_DASH_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = SCRIPT_DATA_STATE;
              this._emitChars('>');
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.state = SCRIPT_DATA_ESCAPED_STATE;
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this.state = SCRIPT_DATA_ESCAPED_STATE;
              this._emitCodePoint(cp);
          }
      }
  
      // Script data escaped less-than sign state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.SOLIDUS) {
              this.tempBuff = [];
              this.state = SCRIPT_DATA_ESCAPED_END_TAG_OPEN_STATE;
          } else if (isAsciiLetter(cp)) {
              this.tempBuff = [];
              this._emitChars('<');
              this._reconsumeInState(SCRIPT_DATA_DOUBLE_ESCAPE_START_STATE);
          } else {
              this._emitChars('<');
              this._reconsumeInState(SCRIPT_DATA_ESCAPED_STATE);
          }
      }
  
      // Script data escaped end tag open state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_END_TAG_OPEN_STATE](cp) {
          if (isAsciiLetter(cp)) {
              this._createEndTagToken();
              this._reconsumeInState(SCRIPT_DATA_ESCAPED_END_TAG_NAME_STATE);
          } else {
              this._emitChars('</');
              this._reconsumeInState(SCRIPT_DATA_ESCAPED_STATE);
          }
      }
  
      // Script data escaped end tag name state
      //------------------------------------------------------------------
      [SCRIPT_DATA_ESCAPED_END_TAG_NAME_STATE](cp) {
          if (isAsciiUpper(cp)) {
              this.currentToken.tagName += toAsciiLowerChar(cp);
              this.tempBuff.push(cp);
          } else if (isAsciiLower(cp)) {
              this.currentToken.tagName += toChar(cp);
              this.tempBuff.push(cp);
          } else {
              if (this.lastStartTagName === this.currentToken.tagName) {
                  if (isWhitespace(cp)) {
                      this.state = BEFORE_ATTRIBUTE_NAME_STATE;
                      return;
                  }
  
                  if (cp === $$1.SOLIDUS) {
                      this.state = SELF_CLOSING_START_TAG_STATE;
                      return;
                  }
  
                  if (cp === $$1.GREATER_THAN_SIGN) {
                      this._emitCurrentToken();
                      this.state = DATA_STATE;
                      return;
                  }
              }
  
              this._emitChars('</');
              this._emitSeveralCodePoints(this.tempBuff);
              this._reconsumeInState(SCRIPT_DATA_ESCAPED_STATE);
          }
      }
  
      // Script data double escape start state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPE_START_STATE](cp) {
          if (isWhitespace(cp) || cp === $$1.SOLIDUS || cp === $$1.GREATER_THAN_SIGN) {
              this.state = this._isTempBufferEqualToScriptString()
                  ? SCRIPT_DATA_DOUBLE_ESCAPED_STATE
                  : SCRIPT_DATA_ESCAPED_STATE;
              this._emitCodePoint(cp);
          } else if (isAsciiUpper(cp)) {
              this.tempBuff.push(toAsciiLowerCodePoint(cp));
              this._emitCodePoint(cp);
          } else if (isAsciiLower(cp)) {
              this.tempBuff.push(cp);
              this._emitCodePoint(cp);
          } else {
              this._reconsumeInState(SCRIPT_DATA_ESCAPED_STATE);
          }
      }
  
      // Script data double escaped state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPED_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_DASH_STATE;
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE;
              this._emitChars('<');
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // Script data double escaped dash state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPED_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH_STATE;
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE;
              this._emitChars('<');
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_STATE;
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_STATE;
              this._emitCodePoint(cp);
          }
      }
  
      // Script data double escaped dash dash state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this._emitChars('-');
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE;
              this._emitChars('<');
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = SCRIPT_DATA_STATE;
              this._emitChars('>');
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_STATE;
              this._emitChars(unicode.REPLACEMENT_CHARACTER);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInScriptHtmlCommentLikeText);
              this._emitEOFToken();
          } else {
              this.state = SCRIPT_DATA_DOUBLE_ESCAPED_STATE;
              this._emitCodePoint(cp);
          }
      }
  
      // Script data double escaped less-than sign state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.SOLIDUS) {
              this.tempBuff = [];
              this.state = SCRIPT_DATA_DOUBLE_ESCAPE_END_STATE;
              this._emitChars('/');
          } else {
              this._reconsumeInState(SCRIPT_DATA_DOUBLE_ESCAPED_STATE);
          }
      }
  
      // Script data double escape end state
      //------------------------------------------------------------------
      [SCRIPT_DATA_DOUBLE_ESCAPE_END_STATE](cp) {
          if (isWhitespace(cp) || cp === $$1.SOLIDUS || cp === $$1.GREATER_THAN_SIGN) {
              this.state = this._isTempBufferEqualToScriptString()
                  ? SCRIPT_DATA_ESCAPED_STATE
                  : SCRIPT_DATA_DOUBLE_ESCAPED_STATE;
  
              this._emitCodePoint(cp);
          } else if (isAsciiUpper(cp)) {
              this.tempBuff.push(toAsciiLowerCodePoint(cp));
              this._emitCodePoint(cp);
          } else if (isAsciiLower(cp)) {
              this.tempBuff.push(cp);
              this._emitCodePoint(cp);
          } else {
              this._reconsumeInState(SCRIPT_DATA_DOUBLE_ESCAPED_STATE);
          }
      }
  
      // Before attribute name state
      //------------------------------------------------------------------
      [BEFORE_ATTRIBUTE_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.SOLIDUS || cp === $$1.GREATER_THAN_SIGN || cp === $$1.EOF) {
              this._reconsumeInState(AFTER_ATTRIBUTE_NAME_STATE);
          } else if (cp === $$1.EQUALS_SIGN) {
              this._err(errorCodes.unexpectedEqualsSignBeforeAttributeName);
              this._createAttr('=');
              this.state = ATTRIBUTE_NAME_STATE;
          } else {
              this._createAttr('');
              this._reconsumeInState(ATTRIBUTE_NAME_STATE);
          }
      }
  
      // Attribute name state
      //------------------------------------------------------------------
      [ATTRIBUTE_NAME_STATE](cp) {
          if (isWhitespace(cp) || cp === $$1.SOLIDUS || cp === $$1.GREATER_THAN_SIGN || cp === $$1.EOF) {
              this._leaveAttrName(AFTER_ATTRIBUTE_NAME_STATE);
              this._unconsume();
          } else if (cp === $$1.EQUALS_SIGN) {
              this._leaveAttrName(BEFORE_ATTRIBUTE_VALUE_STATE);
          } else if (isAsciiUpper(cp)) {
              this.currentAttr.name += toAsciiLowerChar(cp);
          } else if (cp === $$1.QUOTATION_MARK || cp === $$1.APOSTROPHE || cp === $$1.LESS_THAN_SIGN) {
              this._err(errorCodes.unexpectedCharacterInAttributeName);
              this.currentAttr.name += toChar(cp);
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentAttr.name += unicode.REPLACEMENT_CHARACTER;
          } else {
              this.currentAttr.name += toChar(cp);
          }
      }
  
      // After attribute name state
      //------------------------------------------------------------------
      [AFTER_ATTRIBUTE_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.SOLIDUS) {
              this.state = SELF_CLOSING_START_TAG_STATE;
          } else if (cp === $$1.EQUALS_SIGN) {
              this.state = BEFORE_ATTRIBUTE_VALUE_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this._createAttr('');
              this._reconsumeInState(ATTRIBUTE_NAME_STATE);
          }
      }
  
      // Before attribute value state
      //------------------------------------------------------------------
      [BEFORE_ATTRIBUTE_VALUE_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.QUOTATION_MARK) {
              this.state = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this.state = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingAttributeValue);
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else {
              this._reconsumeInState(ATTRIBUTE_VALUE_UNQUOTED_STATE);
          }
      }
  
      // Attribute value (double-quoted) state
      //------------------------------------------------------------------
      [ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE](cp) {
          if (cp === $$1.QUOTATION_MARK) {
              this.state = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
          } else if (cp === $$1.AMPERSAND) {
              this.returnState = ATTRIBUTE_VALUE_DOUBLE_QUOTED_STATE;
              this.state = CHARACTER_REFERENCE_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentAttr.value += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this.currentAttr.value += toChar(cp);
          }
      }
  
      // Attribute value (single-quoted) state
      //------------------------------------------------------------------
      [ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE](cp) {
          if (cp === $$1.APOSTROPHE) {
              this.state = AFTER_ATTRIBUTE_VALUE_QUOTED_STATE;
          } else if (cp === $$1.AMPERSAND) {
              this.returnState = ATTRIBUTE_VALUE_SINGLE_QUOTED_STATE;
              this.state = CHARACTER_REFERENCE_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentAttr.value += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this.currentAttr.value += toChar(cp);
          }
      }
  
      // Attribute value (unquoted) state
      //------------------------------------------------------------------
      [ATTRIBUTE_VALUE_UNQUOTED_STATE](cp) {
          if (isWhitespace(cp)) {
              this._leaveAttrValue(BEFORE_ATTRIBUTE_NAME_STATE);
          } else if (cp === $$1.AMPERSAND) {
              this.returnState = ATTRIBUTE_VALUE_UNQUOTED_STATE;
              this.state = CHARACTER_REFERENCE_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._leaveAttrValue(DATA_STATE);
              this._emitCurrentToken();
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentAttr.value += unicode.REPLACEMENT_CHARACTER;
          } else if (
              cp === $$1.QUOTATION_MARK ||
              cp === $$1.APOSTROPHE ||
              cp === $$1.LESS_THAN_SIGN ||
              cp === $$1.EQUALS_SIGN ||
              cp === $$1.GRAVE_ACCENT
          ) {
              this._err(errorCodes.unexpectedCharacterInUnquotedAttributeValue);
              this.currentAttr.value += toChar(cp);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this.currentAttr.value += toChar(cp);
          }
      }
  
      // After attribute value (quoted) state
      //------------------------------------------------------------------
      [AFTER_ATTRIBUTE_VALUE_QUOTED_STATE](cp) {
          if (isWhitespace(cp)) {
              this._leaveAttrValue(BEFORE_ATTRIBUTE_NAME_STATE);
          } else if (cp === $$1.SOLIDUS) {
              this._leaveAttrValue(SELF_CLOSING_START_TAG_STATE);
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._leaveAttrValue(DATA_STATE);
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingWhitespaceBetweenAttributes);
              this._reconsumeInState(BEFORE_ATTRIBUTE_NAME_STATE);
          }
      }
  
      // Self-closing start tag state
      //------------------------------------------------------------------
      [SELF_CLOSING_START_TAG_STATE](cp) {
          if (cp === $$1.GREATER_THAN_SIGN) {
              this.currentToken.selfClosing = true;
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInTag);
              this._emitEOFToken();
          } else {
              this._err(errorCodes.unexpectedSolidusInTag);
              this._reconsumeInState(BEFORE_ATTRIBUTE_NAME_STATE);
          }
      }
  
      // Bogus comment state
      //------------------------------------------------------------------
      [BOGUS_COMMENT_STATE](cp) {
          if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._emitCurrentToken();
              this._emitEOFToken();
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.data += unicode.REPLACEMENT_CHARACTER;
          } else {
              this.currentToken.data += toChar(cp);
          }
      }
  
      // Markup declaration open state
      //------------------------------------------------------------------
      [MARKUP_DECLARATION_OPEN_STATE](cp) {
          if (this._consumeSequenceIfMatch($$.DASH_DASH_STRING, cp, true)) {
              this._createCommentToken();
              this.state = COMMENT_START_STATE;
          } else if (this._consumeSequenceIfMatch($$.DOCTYPE_STRING, cp, false)) {
              this.state = DOCTYPE_STATE;
          } else if (this._consumeSequenceIfMatch($$.CDATA_START_STRING, cp, true)) {
              if (this.allowCDATA) {
                  this.state = CDATA_SECTION_STATE;
              } else {
                  this._err(errorCodes.cdataInHtmlContent);
                  this._createCommentToken();
                  this.currentToken.data = '[CDATA[';
                  this.state = BOGUS_COMMENT_STATE;
              }
          }
  
          //NOTE: sequence lookup can be abrupted by hibernation. In that case lookup
          //results are no longer valid and we will need to start over.
          else if (!this._ensureHibernation()) {
              this._err(errorCodes.incorrectlyOpenedComment);
              this._createCommentToken();
              this._reconsumeInState(BOGUS_COMMENT_STATE);
          }
      }
  
      // Comment start state
      //------------------------------------------------------------------
      [COMMENT_START_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_START_DASH_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptClosingOfEmptyComment);
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else {
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment start dash state
      //------------------------------------------------------------------
      [COMMENT_START_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_END_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptClosingOfEmptyComment);
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInComment);
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.data += '-';
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment state
      //------------------------------------------------------------------
      [COMMENT_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_END_DASH_STATE;
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.currentToken.data += '<';
              this.state = COMMENT_LESS_THAN_SIGN_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.data += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInComment);
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.data += toChar(cp);
          }
      }
  
      // Comment less-than sign state
      //------------------------------------------------------------------
      [COMMENT_LESS_THAN_SIGN_STATE](cp) {
          if (cp === $$1.EXCLAMATION_MARK) {
              this.currentToken.data += '!';
              this.state = COMMENT_LESS_THAN_SIGN_BANG_STATE;
          } else if (cp === $$1.LESS_THAN_SIGN) {
              this.currentToken.data += '!';
          } else {
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment less-than sign bang state
      //------------------------------------------------------------------
      [COMMENT_LESS_THAN_SIGN_BANG_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_LESS_THAN_SIGN_BANG_DASH_STATE;
          } else {
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment less-than sign bang dash state
      //------------------------------------------------------------------
      [COMMENT_LESS_THAN_SIGN_BANG_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH_STATE;
          } else {
              this._reconsumeInState(COMMENT_END_DASH_STATE);
          }
      }
  
      // Comment less-than sign bang dash dash state
      //------------------------------------------------------------------
      [COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH_STATE](cp) {
          if (cp !== $$1.GREATER_THAN_SIGN && cp !== $$1.EOF) {
              this._err(errorCodes.nestedComment);
          }
  
          this._reconsumeInState(COMMENT_END_STATE);
      }
  
      // Comment end dash state
      //------------------------------------------------------------------
      [COMMENT_END_DASH_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.state = COMMENT_END_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInComment);
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.data += '-';
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment end state
      //------------------------------------------------------------------
      [COMMENT_END_STATE](cp) {
          if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EXCLAMATION_MARK) {
              this.state = COMMENT_END_BANG_STATE;
          } else if (cp === $$1.HYPHEN_MINUS) {
              this.currentToken.data += '-';
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInComment);
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.data += '--';
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // Comment end bang state
      //------------------------------------------------------------------
      [COMMENT_END_BANG_STATE](cp) {
          if (cp === $$1.HYPHEN_MINUS) {
              this.currentToken.data += '--!';
              this.state = COMMENT_END_DASH_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.incorrectlyClosedComment);
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInComment);
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.data += '--!';
              this._reconsumeInState(COMMENT_STATE);
          }
      }
  
      // DOCTYPE state
      //------------------------------------------------------------------
      [DOCTYPE_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = BEFORE_DOCTYPE_NAME_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._reconsumeInState(BEFORE_DOCTYPE_NAME_STATE);
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this._createDoctypeToken(null);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingWhitespaceBeforeDoctypeName);
              this._reconsumeInState(BEFORE_DOCTYPE_NAME_STATE);
          }
      }
  
      // Before DOCTYPE name state
      //------------------------------------------------------------------
      [BEFORE_DOCTYPE_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (isAsciiUpper(cp)) {
              this._createDoctypeToken(toAsciiLowerChar(cp));
              this.state = DOCTYPE_NAME_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this._createDoctypeToken(unicode.REPLACEMENT_CHARACTER);
              this.state = DOCTYPE_NAME_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingDoctypeName);
              this._createDoctypeToken(null);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this._createDoctypeToken(null);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._createDoctypeToken(toChar(cp));
              this.state = DOCTYPE_NAME_STATE;
          }
      }
  
      // DOCTYPE name state
      //------------------------------------------------------------------
      [DOCTYPE_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = AFTER_DOCTYPE_NAME_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (isAsciiUpper(cp)) {
              this.currentToken.name += toAsciiLowerChar(cp);
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.name += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.name += toChar(cp);
          }
      }
  
      // After DOCTYPE name state
      //------------------------------------------------------------------
      [AFTER_DOCTYPE_NAME_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else if (this._consumeSequenceIfMatch($$.PUBLIC_STRING, cp, false)) {
              this.state = AFTER_DOCTYPE_PUBLIC_KEYWORD_STATE;
          } else if (this._consumeSequenceIfMatch($$.SYSTEM_STRING, cp, false)) {
              this.state = AFTER_DOCTYPE_SYSTEM_KEYWORD_STATE;
          }
          //NOTE: sequence lookup can be abrupted by hibernation. In that case lookup
          //results are no longer valid and we will need to start over.
          else if (!this._ensureHibernation()) {
              this._err(errorCodes.invalidCharacterSequenceAfterDoctypeName);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // After DOCTYPE public keyword state
      //------------------------------------------------------------------
      [AFTER_DOCTYPE_PUBLIC_KEYWORD_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE;
          } else if (cp === $$1.QUOTATION_MARK) {
              this._err(errorCodes.missingWhitespaceAfterDoctypePublicKeyword);
              this.currentToken.publicId = '';
              this.state = DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this._err(errorCodes.missingWhitespaceAfterDoctypePublicKeyword);
              this.currentToken.publicId = '';
              this.state = DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // Before DOCTYPE public identifier state
      //------------------------------------------------------------------
      [BEFORE_DOCTYPE_PUBLIC_IDENTIFIER_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.QUOTATION_MARK) {
              this.currentToken.publicId = '';
              this.state = DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this.currentToken.publicId = '';
              this.state = DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // DOCTYPE public identifier (double-quoted) state
      //------------------------------------------------------------------
      [DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED_STATE](cp) {
          if (cp === $$1.QUOTATION_MARK) {
              this.state = AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.publicId += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.publicId += toChar(cp);
          }
      }
  
      // DOCTYPE public identifier (single-quoted) state
      //------------------------------------------------------------------
      [DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED_STATE](cp) {
          if (cp === $$1.APOSTROPHE) {
              this.state = AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.publicId += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptDoctypePublicIdentifier);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.publicId += toChar(cp);
          }
      }
  
      // After DOCTYPE public identifier state
      //------------------------------------------------------------------
      [AFTER_DOCTYPE_PUBLIC_IDENTIFIER_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.QUOTATION_MARK) {
              this._err(errorCodes.missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers);
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this._err(errorCodes.missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers);
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // Between DOCTYPE public and system identifiers state
      //------------------------------------------------------------------
      [BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.GREATER_THAN_SIGN) {
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.QUOTATION_MARK) {
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // After DOCTYPE system keyword state
      //------------------------------------------------------------------
      [AFTER_DOCTYPE_SYSTEM_KEYWORD_STATE](cp) {
          if (isWhitespace(cp)) {
              this.state = BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE;
          } else if (cp === $$1.QUOTATION_MARK) {
              this._err(errorCodes.missingWhitespaceAfterDoctypeSystemKeyword);
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this._err(errorCodes.missingWhitespaceAfterDoctypeSystemKeyword);
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // Before DOCTYPE system identifier state
      //------------------------------------------------------------------
      [BEFORE_DOCTYPE_SYSTEM_IDENTIFIER_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.QUOTATION_MARK) {
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE;
          } else if (cp === $$1.APOSTROPHE) {
              this.currentToken.systemId = '';
              this.state = DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.missingDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this.state = DATA_STATE;
              this._emitCurrentToken();
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.missingQuoteBeforeDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // DOCTYPE system identifier (double-quoted) state
      //------------------------------------------------------------------
      [DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED_STATE](cp) {
          if (cp === $$1.QUOTATION_MARK) {
              this.state = AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.systemId += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.systemId += toChar(cp);
          }
      }
  
      // DOCTYPE system identifier (single-quoted) state
      //------------------------------------------------------------------
      [DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED_STATE](cp) {
          if (cp === $$1.APOSTROPHE) {
              this.state = AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
              this.currentToken.systemId += unicode.REPLACEMENT_CHARACTER;
          } else if (cp === $$1.GREATER_THAN_SIGN) {
              this._err(errorCodes.abruptDoctypeSystemIdentifier);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this.currentToken.systemId += toChar(cp);
          }
      }
  
      // After DOCTYPE system identifier state
      //------------------------------------------------------------------
      [AFTER_DOCTYPE_SYSTEM_IDENTIFIER_STATE](cp) {
          if (isWhitespace(cp)) {
              return;
          }
  
          if (cp === $$1.GREATER_THAN_SIGN) {
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInDoctype);
              this.currentToken.forceQuirks = true;
              this._emitCurrentToken();
              this._emitEOFToken();
          } else {
              this._err(errorCodes.unexpectedCharacterAfterDoctypeSystemIdentifier);
              this._reconsumeInState(BOGUS_DOCTYPE_STATE);
          }
      }
  
      // Bogus DOCTYPE state
      //------------------------------------------------------------------
      [BOGUS_DOCTYPE_STATE](cp) {
          if (cp === $$1.GREATER_THAN_SIGN) {
              this._emitCurrentToken();
              this.state = DATA_STATE;
          } else if (cp === $$1.NULL) {
              this._err(errorCodes.unexpectedNullCharacter);
          } else if (cp === $$1.EOF) {
              this._emitCurrentToken();
              this._emitEOFToken();
          }
      }
  
      // CDATA section state
      //------------------------------------------------------------------
      [CDATA_SECTION_STATE](cp) {
          if (cp === $$1.RIGHT_SQUARE_BRACKET) {
              this.state = CDATA_SECTION_BRACKET_STATE;
          } else if (cp === $$1.EOF) {
              this._err(errorCodes.eofInCdata);
              this._emitEOFToken();
          } else {
              this._emitCodePoint(cp);
          }
      }
  
      // CDATA section bracket state
      //------------------------------------------------------------------
      [CDATA_SECTION_BRACKET_STATE](cp) {
          if (cp === $$1.RIGHT_SQUARE_BRACKET) {
              this.state = CDATA_SECTION_END_STATE;
          } else {
              this._emitChars(']');
              this._reconsumeInState(CDATA_SECTION_STATE);
          }
      }
  
      // CDATA section end state
      //------------------------------------------------------------------
      [CDATA_SECTION_END_STATE](cp) {
          if (cp === $$1.GREATER_THAN_SIGN) {
              this.state = DATA_STATE;
          } else if (cp === $$1.RIGHT_SQUARE_BRACKET) {
              this._emitChars(']');
          } else {
              this._emitChars(']]');
              this._reconsumeInState(CDATA_SECTION_STATE);
          }
      }
  
      // Character reference state
      //------------------------------------------------------------------
      [CHARACTER_REFERENCE_STATE](cp) {
          this.tempBuff = [$$1.AMPERSAND];
  
          if (cp === $$1.NUMBER_SIGN) {
              this.tempBuff.push(cp);
              this.state = NUMERIC_CHARACTER_REFERENCE_STATE;
          } else if (isAsciiAlphaNumeric(cp)) {
              this._reconsumeInState(NAMED_CHARACTER_REFERENCE_STATE);
          } else {
              this._flushCodePointsConsumedAsCharacterReference();
              this._reconsumeInState(this.returnState);
          }
      }
  
      // Named character reference state
      //------------------------------------------------------------------
      [NAMED_CHARACTER_REFERENCE_STATE](cp) {
          const matchResult = this._matchNamedCharacterReference(cp);
  
          //NOTE: matching can be abrupted by hibernation. In that case match
          //results are no longer valid and we will need to start over.
          if (this._ensureHibernation()) {
              this.tempBuff = [$$1.AMPERSAND];
          } else if (matchResult) {
              const withSemicolon = this.tempBuff[this.tempBuff.length - 1] === $$1.SEMICOLON;
  
              if (!this._isCharacterReferenceAttributeQuirk(withSemicolon)) {
                  if (!withSemicolon) {
                      this._errOnNextCodePoint(errorCodes.missingSemicolonAfterCharacterReference);
                  }
  
                  this.tempBuff = matchResult;
              }
  
              this._flushCodePointsConsumedAsCharacterReference();
              this.state = this.returnState;
          } else {
              this._flushCodePointsConsumedAsCharacterReference();
              this.state = AMBIGUOUS_AMPERSAND_STATE;
          }
      }
  
      // Ambiguos ampersand state
      //------------------------------------------------------------------
      [AMBIGUOUS_AMPERSAND_STATE](cp) {
          if (isAsciiAlphaNumeric(cp)) {
              if (this._isCharacterReferenceInAttribute()) {
                  this.currentAttr.value += toChar(cp);
              } else {
                  this._emitCodePoint(cp);
              }
          } else {
              if (cp === $$1.SEMICOLON) {
                  this._err(errorCodes.unknownNamedCharacterReference);
              }
  
              this._reconsumeInState(this.returnState);
          }
      }
  
      // Numeric character reference state
      //------------------------------------------------------------------
      [NUMERIC_CHARACTER_REFERENCE_STATE](cp) {
          this.charRefCode = 0;
  
          if (cp === $$1.LATIN_SMALL_X || cp === $$1.LATIN_CAPITAL_X) {
              this.tempBuff.push(cp);
              this.state = HEXADEMICAL_CHARACTER_REFERENCE_START_STATE;
          } else {
              this._reconsumeInState(DECIMAL_CHARACTER_REFERENCE_START_STATE);
          }
      }
  
      // Hexademical character reference start state
      //------------------------------------------------------------------
      [HEXADEMICAL_CHARACTER_REFERENCE_START_STATE](cp) {
          if (isAsciiHexDigit(cp)) {
              this._reconsumeInState(HEXADEMICAL_CHARACTER_REFERENCE_STATE);
          } else {
              this._err(errorCodes.absenceOfDigitsInNumericCharacterReference);
              this._flushCodePointsConsumedAsCharacterReference();
              this._reconsumeInState(this.returnState);
          }
      }
  
      // Decimal character reference start state
      //------------------------------------------------------------------
      [DECIMAL_CHARACTER_REFERENCE_START_STATE](cp) {
          if (isAsciiDigit(cp)) {
              this._reconsumeInState(DECIMAL_CHARACTER_REFERENCE_STATE);
          } else {
              this._err(errorCodes.absenceOfDigitsInNumericCharacterReference);
              this._flushCodePointsConsumedAsCharacterReference();
              this._reconsumeInState(this.returnState);
          }
      }
  
      // Hexademical character reference state
      //------------------------------------------------------------------
      [HEXADEMICAL_CHARACTER_REFERENCE_STATE](cp) {
          if (isAsciiUpperHexDigit(cp)) {
              this.charRefCode = this.charRefCode * 16 + cp - 0x37;
          } else if (isAsciiLowerHexDigit(cp)) {
              this.charRefCode = this.charRefCode * 16 + cp - 0x57;
          } else if (isAsciiDigit(cp)) {
              this.charRefCode = this.charRefCode * 16 + cp - 0x30;
          } else if (cp === $$1.SEMICOLON) {
              this.state = NUMERIC_CHARACTER_REFERENCE_END_STATE;
          } else {
              this._err(errorCodes.missingSemicolonAfterCharacterReference);
              this._reconsumeInState(NUMERIC_CHARACTER_REFERENCE_END_STATE);
          }
      }
  
      // Decimal character reference state
      //------------------------------------------------------------------
      [DECIMAL_CHARACTER_REFERENCE_STATE](cp) {
          if (isAsciiDigit(cp)) {
              this.charRefCode = this.charRefCode * 10 + cp - 0x30;
          } else if (cp === $$1.SEMICOLON) {
              this.state = NUMERIC_CHARACTER_REFERENCE_END_STATE;
          } else {
              this._err(errorCodes.missingSemicolonAfterCharacterReference);
              this._reconsumeInState(NUMERIC_CHARACTER_REFERENCE_END_STATE);
          }
      }
  
      // Numeric character reference end state
      //------------------------------------------------------------------
      [NUMERIC_CHARACTER_REFERENCE_END_STATE]() {
          if (this.charRefCode === $$1.NULL) {
              this._err(errorCodes.nullCharacterReference);
              this.charRefCode = $$1.REPLACEMENT_CHARACTER;
          } else if (this.charRefCode > 0x10ffff) {
              this._err(errorCodes.characterReferenceOutsideUnicodeRange);
              this.charRefCode = $$1.REPLACEMENT_CHARACTER;
          } else if (unicode.isSurrogate(this.charRefCode)) {
              this._err(errorCodes.surrogateCharacterReference);
              this.charRefCode = $$1.REPLACEMENT_CHARACTER;
          } else if (unicode.isUndefinedCodePoint(this.charRefCode)) {
              this._err(errorCodes.noncharacterCharacterReference);
          } else if (unicode.isControlCodePoint(this.charRefCode) || this.charRefCode === $$1.CARRIAGE_RETURN) {
              this._err(errorCodes.controlCharacterReference);
  
              const replacement = C1_CONTROLS_REFERENCE_REPLACEMENTS[this.charRefCode];
  
              if (replacement) {
                  this.charRefCode = replacement;
              }
          }
  
          this.tempBuff = [this.charRefCode];
  
          this._flushCodePointsConsumedAsCharacterReference();
          this._reconsumeInState(this.returnState);
      }
  }
  
  //Token types
  Tokenizer.CHARACTER_TOKEN = 'CHARACTER_TOKEN';
  Tokenizer.NULL_CHARACTER_TOKEN = 'NULL_CHARACTER_TOKEN';
  Tokenizer.WHITESPACE_CHARACTER_TOKEN = 'WHITESPACE_CHARACTER_TOKEN';
  Tokenizer.START_TAG_TOKEN = 'START_TAG_TOKEN';
  Tokenizer.END_TAG_TOKEN = 'END_TAG_TOKEN';
  Tokenizer.COMMENT_TOKEN = 'COMMENT_TOKEN';
  Tokenizer.DOCTYPE_TOKEN = 'DOCTYPE_TOKEN';
  Tokenizer.EOF_TOKEN = 'EOF_TOKEN';
  Tokenizer.HIBERNATION_TOKEN = 'HIBERNATION_TOKEN';
  
  //Tokenizer initial states for different modes
  Tokenizer.MODE = {
      DATA: DATA_STATE,
      RCDATA: RCDATA_STATE,
      RAWTEXT: RAWTEXT_STATE,
      SCRIPT_DATA: SCRIPT_DATA_STATE,
      PLAINTEXT: PLAINTEXT_STATE
  };
  
  //Static
  Tokenizer.getTokenAttr = function(token, attrName) {
      for (let i = token.attrs.length - 1; i >= 0; i--) {
          if (token.attrs[i].name === attrName) {
              return token.attrs[i].value;
          }
      }
  
      return null;
  };
  
  var tokenizer = Tokenizer;
  
  var html = createCommonjsModule(function (module, exports) {
  
  const NS = (exports.NAMESPACES = {
      HTML: 'http://www.w3.org/1999/xhtml',
      MATHML: 'http://www.w3.org/1998/Math/MathML',
      SVG: 'http://www.w3.org/2000/svg',
      XLINK: 'http://www.w3.org/1999/xlink',
      XML: 'http://www.w3.org/XML/1998/namespace',
      XMLNS: 'http://www.w3.org/2000/xmlns/'
  });
  
  exports.ATTRS = {
      TYPE: 'type',
      ACTION: 'action',
      ENCODING: 'encoding',
      PROMPT: 'prompt',
      NAME: 'name',
      COLOR: 'color',
      FACE: 'face',
      SIZE: 'size'
  };
  
  exports.DOCUMENT_MODE = {
      NO_QUIRKS: 'no-quirks',
      QUIRKS: 'quirks',
      LIMITED_QUIRKS: 'limited-quirks'
  };
  
  const $ = (exports.TAG_NAMES = {
      A: 'a',
      ADDRESS: 'address',
      ANNOTATION_XML: 'annotation-xml',
      APPLET: 'applet',
      AREA: 'area',
      ARTICLE: 'article',
      ASIDE: 'aside',
  
      B: 'b',
      BASE: 'base',
      BASEFONT: 'basefont',
      BGSOUND: 'bgsound',
      BIG: 'big',
      BLOCKQUOTE: 'blockquote',
      BODY: 'body',
      BR: 'br',
      BUTTON: 'button',
  
      CAPTION: 'caption',
      CENTER: 'center',
      CODE: 'code',
      COL: 'col',
      COLGROUP: 'colgroup',
  
      DD: 'dd',
      DESC: 'desc',
      DETAILS: 'details',
      DIALOG: 'dialog',
      DIR: 'dir',
      DIV: 'div',
      DL: 'dl',
      DT: 'dt',
  
      EM: 'em',
      EMBED: 'embed',
  
      FIELDSET: 'fieldset',
      FIGCAPTION: 'figcaption',
      FIGURE: 'figure',
      FONT: 'font',
      FOOTER: 'footer',
      FOREIGN_OBJECT: 'foreignObject',
      FORM: 'form',
      FRAME: 'frame',
      FRAMESET: 'frameset',
  
      H1: 'h1',
      H2: 'h2',
      H3: 'h3',
      H4: 'h4',
      H5: 'h5',
      H6: 'h6',
      HEAD: 'head',
      HEADER: 'header',
      HGROUP: 'hgroup',
      HR: 'hr',
      HTML: 'html',
  
      I: 'i',
      IMG: 'img',
      IMAGE: 'image',
      INPUT: 'input',
      IFRAME: 'iframe',
  
      KEYGEN: 'keygen',
  
      LABEL: 'label',
      LI: 'li',
      LINK: 'link',
      LISTING: 'listing',
  
      MAIN: 'main',
      MALIGNMARK: 'malignmark',
      MARQUEE: 'marquee',
      MATH: 'math',
      MENU: 'menu',
      META: 'meta',
      MGLYPH: 'mglyph',
      MI: 'mi',
      MO: 'mo',
      MN: 'mn',
      MS: 'ms',
      MTEXT: 'mtext',
  
      NAV: 'nav',
      NOBR: 'nobr',
      NOFRAMES: 'noframes',
      NOEMBED: 'noembed',
      NOSCRIPT: 'noscript',
  
      OBJECT: 'object',
      OL: 'ol',
      OPTGROUP: 'optgroup',
      OPTION: 'option',
  
      P: 'p',
      PARAM: 'param',
      PLAINTEXT: 'plaintext',
      PRE: 'pre',
  
      RB: 'rb',
      RP: 'rp',
      RT: 'rt',
      RTC: 'rtc',
      RUBY: 'ruby',
  
      S: 's',
      SCRIPT: 'script',
      SECTION: 'section',
      SELECT: 'select',
      SOURCE: 'source',
      SMALL: 'small',
      SPAN: 'span',
      STRIKE: 'strike',
      STRONG: 'strong',
      STYLE: 'style',
      SUB: 'sub',
      SUMMARY: 'summary',
      SUP: 'sup',
  
      TABLE: 'table',
      TBODY: 'tbody',
      TEMPLATE: 'template',
      TEXTAREA: 'textarea',
      TFOOT: 'tfoot',
      TD: 'td',
      TH: 'th',
      THEAD: 'thead',
      TITLE: 'title',
      TR: 'tr',
      TRACK: 'track',
      TT: 'tt',
  
      U: 'u',
      UL: 'ul',
  
      SVG: 'svg',
  
      VAR: 'var',
  
      WBR: 'wbr',
  
      XMP: 'xmp'
  });
  
  exports.SPECIAL_ELEMENTS = {
      [NS.HTML]: {
          [$.ADDRESS]: true,
          [$.APPLET]: true,
          [$.AREA]: true,
          [$.ARTICLE]: true,
          [$.ASIDE]: true,
          [$.BASE]: true,
          [$.BASEFONT]: true,
          [$.BGSOUND]: true,
          [$.BLOCKQUOTE]: true,
          [$.BODY]: true,
          [$.BR]: true,
          [$.BUTTON]: true,
          [$.CAPTION]: true,
          [$.CENTER]: true,
          [$.COL]: true,
          [$.COLGROUP]: true,
          [$.DD]: true,
          [$.DETAILS]: true,
          [$.DIR]: true,
          [$.DIV]: true,
          [$.DL]: true,
          [$.DT]: true,
          [$.EMBED]: true,
          [$.FIELDSET]: true,
          [$.FIGCAPTION]: true,
          [$.FIGURE]: true,
          [$.FOOTER]: true,
          [$.FORM]: true,
          [$.FRAME]: true,
          [$.FRAMESET]: true,
          [$.H1]: true,
          [$.H2]: true,
          [$.H3]: true,
          [$.H4]: true,
          [$.H5]: true,
          [$.H6]: true,
          [$.HEAD]: true,
          [$.HEADER]: true,
          [$.HGROUP]: true,
          [$.HR]: true,
          [$.HTML]: true,
          [$.IFRAME]: true,
          [$.IMG]: true,
          [$.INPUT]: true,
          [$.LI]: true,
          [$.LINK]: true,
          [$.LISTING]: true,
          [$.MAIN]: true,
          [$.MARQUEE]: true,
          [$.MENU]: true,
          [$.META]: true,
          [$.NAV]: true,
          [$.NOEMBED]: true,
          [$.NOFRAMES]: true,
          [$.NOSCRIPT]: true,
          [$.OBJECT]: true,
          [$.OL]: true,
          [$.P]: true,
          [$.PARAM]: true,
          [$.PLAINTEXT]: true,
          [$.PRE]: true,
          [$.SCRIPT]: true,
          [$.SECTION]: true,
          [$.SELECT]: true,
          [$.SOURCE]: true,
          [$.STYLE]: true,
          [$.SUMMARY]: true,
          [$.TABLE]: true,
          [$.TBODY]: true,
          [$.TD]: true,
          [$.TEMPLATE]: true,
          [$.TEXTAREA]: true,
          [$.TFOOT]: true,
          [$.TH]: true,
          [$.THEAD]: true,
          [$.TITLE]: true,
          [$.TR]: true,
          [$.TRACK]: true,
          [$.UL]: true,
          [$.WBR]: true,
          [$.XMP]: true
      },
      [NS.MATHML]: {
          [$.MI]: true,
          [$.MO]: true,
          [$.MN]: true,
          [$.MS]: true,
          [$.MTEXT]: true,
          [$.ANNOTATION_XML]: true
      },
      [NS.SVG]: {
          [$.TITLE]: true,
          [$.FOREIGN_OBJECT]: true,
          [$.DESC]: true
      }
  };
  });
  var html_1 = html.NAMESPACES;
  var html_2 = html.ATTRS;
  var html_3 = html.DOCUMENT_MODE;
  var html_4 = html.TAG_NAMES;
  var html_5 = html.SPECIAL_ELEMENTS;
  
  //Aliases
  const $$2 = html.TAG_NAMES;
  const NS = html.NAMESPACES;
  
  //Element utils
  
  //OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
  //It's faster than using dictionary.
  function isImpliedEndTagRequired(tn) {
      switch (tn.length) {
          case 1:
              return tn === $$2.P;
  
          case 2:
              return tn === $$2.RB || tn === $$2.RP || tn === $$2.RT || tn === $$2.DD || tn === $$2.DT || tn === $$2.LI;
  
          case 3:
              return tn === $$2.RTC;
  
          case 6:
              return tn === $$2.OPTION;
  
          case 8:
              return tn === $$2.OPTGROUP;
      }
  
      return false;
  }
  
  function isImpliedEndTagRequiredThoroughly(tn) {
      switch (tn.length) {
          case 1:
              return tn === $$2.P;
  
          case 2:
              return (
                  tn === $$2.RB ||
                  tn === $$2.RP ||
                  tn === $$2.RT ||
                  tn === $$2.DD ||
                  tn === $$2.DT ||
                  tn === $$2.LI ||
                  tn === $$2.TD ||
                  tn === $$2.TH ||
                  tn === $$2.TR
              );
  
          case 3:
              return tn === $$2.RTC;
  
          case 5:
              return tn === $$2.TBODY || tn === $$2.TFOOT || tn === $$2.THEAD;
  
          case 6:
              return tn === $$2.OPTION;
  
          case 7:
              return tn === $$2.CAPTION;
  
          case 8:
              return tn === $$2.OPTGROUP || tn === $$2.COLGROUP;
      }
  
      return false;
  }
  
  function isScopingElement(tn, ns) {
      switch (tn.length) {
          case 2:
              if (tn === $$2.TD || tn === $$2.TH) {
                  return ns === NS.HTML;
              } else if (tn === $$2.MI || tn === $$2.MO || tn === $$2.MN || tn === $$2.MS) {
                  return ns === NS.MATHML;
              }
  
              break;
  
          case 4:
              if (tn === $$2.HTML) {
                  return ns === NS.HTML;
              } else if (tn === $$2.DESC) {
                  return ns === NS.SVG;
              }
  
              break;
  
          case 5:
              if (tn === $$2.TABLE) {
                  return ns === NS.HTML;
              } else if (tn === $$2.MTEXT) {
                  return ns === NS.MATHML;
              } else if (tn === $$2.TITLE) {
                  return ns === NS.SVG;
              }
  
              break;
  
          case 6:
              return (tn === $$2.APPLET || tn === $$2.OBJECT) && ns === NS.HTML;
  
          case 7:
              return (tn === $$2.CAPTION || tn === $$2.MARQUEE) && ns === NS.HTML;
  
          case 8:
              return tn === $$2.TEMPLATE && ns === NS.HTML;
  
          case 13:
              return tn === $$2.FOREIGN_OBJECT && ns === NS.SVG;
  
          case 14:
              return tn === $$2.ANNOTATION_XML && ns === NS.MATHML;
      }
  
      return false;
  }
  
  //Stack of open elements
  class OpenElementStack {
      constructor(document, treeAdapter) {
          this.stackTop = -1;
          this.items = [];
          this.current = document;
          this.currentTagName = null;
          this.currentTmplContent = null;
          this.tmplCount = 0;
          this.treeAdapter = treeAdapter;
      }
  
      //Index of element
      _indexOf(element) {
          let idx = -1;
  
          for (let i = this.stackTop; i >= 0; i--) {
              if (this.items[i] === element) {
                  idx = i;
                  break;
              }
          }
          return idx;
      }
  
      //Update current element
      _isInTemplate() {
          return this.currentTagName === $$2.TEMPLATE && this.treeAdapter.getNamespaceURI(this.current) === NS.HTML;
      }
  
      _updateCurrentElement() {
          this.current = this.items[this.stackTop];
          this.currentTagName = this.current && this.treeAdapter.getTagName(this.current);
  
          this.currentTmplContent = this._isInTemplate() ? this.treeAdapter.getTemplateContent(this.current) : null;
      }
  
      //Mutations
      push(element) {
          this.items[++this.stackTop] = element;
          this._updateCurrentElement();
  
          if (this._isInTemplate()) {
              this.tmplCount++;
          }
      }
  
      pop() {
          this.stackTop--;
  
          if (this.tmplCount > 0 && this._isInTemplate()) {
              this.tmplCount--;
          }
  
          this._updateCurrentElement();
      }
  
      replace(oldElement, newElement) {
          const idx = this._indexOf(oldElement);
  
          this.items[idx] = newElement;
  
          if (idx === this.stackTop) {
              this._updateCurrentElement();
          }
      }
  
      insertAfter(referenceElement, newElement) {
          const insertionIdx = this._indexOf(referenceElement) + 1;
  
          this.items.splice(insertionIdx, 0, newElement);
  
          if (insertionIdx === ++this.stackTop) {
              this._updateCurrentElement();
          }
      }
  
      popUntilTagNamePopped(tagName) {
          while (this.stackTop > -1) {
              const tn = this.currentTagName;
              const ns = this.treeAdapter.getNamespaceURI(this.current);
  
              this.pop();
  
              if (tn === tagName && ns === NS.HTML) {
                  break;
              }
          }
      }
  
      popUntilElementPopped(element) {
          while (this.stackTop > -1) {
              const poppedElement = this.current;
  
              this.pop();
  
              if (poppedElement === element) {
                  break;
              }
          }
      }
  
      popUntilNumberedHeaderPopped() {
          while (this.stackTop > -1) {
              const tn = this.currentTagName;
              const ns = this.treeAdapter.getNamespaceURI(this.current);
  
              this.pop();
  
              if (
                  tn === $$2.H1 ||
                  tn === $$2.H2 ||
                  tn === $$2.H3 ||
                  tn === $$2.H4 ||
                  tn === $$2.H5 ||
                  (tn === $$2.H6 && ns === NS.HTML)
              ) {
                  break;
              }
          }
      }
  
      popUntilTableCellPopped() {
          while (this.stackTop > -1) {
              const tn = this.currentTagName;
              const ns = this.treeAdapter.getNamespaceURI(this.current);
  
              this.pop();
  
              if (tn === $$2.TD || (tn === $$2.TH && ns === NS.HTML)) {
                  break;
              }
          }
      }
  
      popAllUpToHtmlElement() {
          //NOTE: here we assume that root <html> element is always first in the open element stack, so
          //we perform this fast stack clean up.
          this.stackTop = 0;
          this._updateCurrentElement();
      }
  
      clearBackToTableContext() {
          while (
              (this.currentTagName !== $$2.TABLE && this.currentTagName !== $$2.TEMPLATE && this.currentTagName !== $$2.HTML) ||
              this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML
          ) {
              this.pop();
          }
      }
  
      clearBackToTableBodyContext() {
          while (
              (this.currentTagName !== $$2.TBODY &&
                  this.currentTagName !== $$2.TFOOT &&
                  this.currentTagName !== $$2.THEAD &&
                  this.currentTagName !== $$2.TEMPLATE &&
                  this.currentTagName !== $$2.HTML) ||
              this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML
          ) {
              this.pop();
          }
      }
  
      clearBackToTableRowContext() {
          while (
              (this.currentTagName !== $$2.TR && this.currentTagName !== $$2.TEMPLATE && this.currentTagName !== $$2.HTML) ||
              this.treeAdapter.getNamespaceURI(this.current) !== NS.HTML
          ) {
              this.pop();
          }
      }
  
      remove(element) {
          for (let i = this.stackTop; i >= 0; i--) {
              if (this.items[i] === element) {
                  this.items.splice(i, 1);
                  this.stackTop--;
                  this._updateCurrentElement();
                  break;
              }
          }
      }
  
      //Search
      tryPeekProperlyNestedBodyElement() {
          //Properly nested <body> element (should be second element in stack).
          const element = this.items[1];
  
          return element && this.treeAdapter.getTagName(element) === $$2.BODY ? element : null;
      }
  
      contains(element) {
          return this._indexOf(element) > -1;
      }
  
      getCommonAncestor(element) {
          let elementIdx = this._indexOf(element);
  
          return --elementIdx >= 0 ? this.items[elementIdx] : null;
      }
  
      isRootHtmlElementCurrent() {
          return this.stackTop === 0 && this.currentTagName === $$2.HTML;
      }
  
      //Element in scope
      hasInScope(tagName) {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (tn === tagName && ns === NS.HTML) {
                  return true;
              }
  
              if (isScopingElement(tn, ns)) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasNumberedHeaderInScope() {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (
                  (tn === $$2.H1 || tn === $$2.H2 || tn === $$2.H3 || tn === $$2.H4 || tn === $$2.H5 || tn === $$2.H6) &&
                  ns === NS.HTML
              ) {
                  return true;
              }
  
              if (isScopingElement(tn, ns)) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasInListItemScope(tagName) {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (tn === tagName && ns === NS.HTML) {
                  return true;
              }
  
              if (((tn === $$2.UL || tn === $$2.OL) && ns === NS.HTML) || isScopingElement(tn, ns)) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasInButtonScope(tagName) {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (tn === tagName && ns === NS.HTML) {
                  return true;
              }
  
              if ((tn === $$2.BUTTON && ns === NS.HTML) || isScopingElement(tn, ns)) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasInTableScope(tagName) {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (ns !== NS.HTML) {
                  continue;
              }
  
              if (tn === tagName) {
                  return true;
              }
  
              if (tn === $$2.TABLE || tn === $$2.TEMPLATE || tn === $$2.HTML) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasTableBodyContextInTableScope() {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (ns !== NS.HTML) {
                  continue;
              }
  
              if (tn === $$2.TBODY || tn === $$2.THEAD || tn === $$2.TFOOT) {
                  return true;
              }
  
              if (tn === $$2.TABLE || tn === $$2.HTML) {
                  return false;
              }
          }
  
          return true;
      }
  
      hasInSelectScope(tagName) {
          for (let i = this.stackTop; i >= 0; i--) {
              const tn = this.treeAdapter.getTagName(this.items[i]);
              const ns = this.treeAdapter.getNamespaceURI(this.items[i]);
  
              if (ns !== NS.HTML) {
                  continue;
              }
  
              if (tn === tagName) {
                  return true;
              }
  
              if (tn !== $$2.OPTION && tn !== $$2.OPTGROUP) {
                  return false;
              }
          }
  
          return true;
      }
  
      //Implied end tags
      generateImpliedEndTags() {
          while (isImpliedEndTagRequired(this.currentTagName)) {
              this.pop();
          }
      }
  
      generateImpliedEndTagsThoroughly() {
          while (isImpliedEndTagRequiredThoroughly(this.currentTagName)) {
              this.pop();
          }
      }
  
      generateImpliedEndTagsWithExclusion(exclusionTagName) {
          while (isImpliedEndTagRequired(this.currentTagName) && this.currentTagName !== exclusionTagName) {
              this.pop();
          }
      }
  }
  
  var openElementStack = OpenElementStack;
  
  //Const
  const NOAH_ARK_CAPACITY = 3;
  
  //List of formatting elements
  class FormattingElementList {
      constructor(treeAdapter) {
          this.length = 0;
          this.entries = [];
          this.treeAdapter = treeAdapter;
          this.bookmark = null;
      }
  
      //Noah Ark's condition
      //OPTIMIZATION: at first we try to find possible candidates for exclusion using
      //lightweight heuristics without thorough attributes check.
      _getNoahArkConditionCandidates(newElement) {
          const candidates = [];
  
          if (this.length >= NOAH_ARK_CAPACITY) {
              const neAttrsLength = this.treeAdapter.getAttrList(newElement).length;
              const neTagName = this.treeAdapter.getTagName(newElement);
              const neNamespaceURI = this.treeAdapter.getNamespaceURI(newElement);
  
              for (let i = this.length - 1; i >= 0; i--) {
                  const entry = this.entries[i];
  
                  if (entry.type === FormattingElementList.MARKER_ENTRY) {
                      break;
                  }
  
                  const element = entry.element;
                  const elementAttrs = this.treeAdapter.getAttrList(element);
  
                  const isCandidate =
                      this.treeAdapter.getTagName(element) === neTagName &&
                      this.treeAdapter.getNamespaceURI(element) === neNamespaceURI &&
                      elementAttrs.length === neAttrsLength;
  
                  if (isCandidate) {
                      candidates.push({ idx: i, attrs: elementAttrs });
                  }
              }
          }
  
          return candidates.length < NOAH_ARK_CAPACITY ? [] : candidates;
      }
  
      _ensureNoahArkCondition(newElement) {
          const candidates = this._getNoahArkConditionCandidates(newElement);
          let cLength = candidates.length;
  
          if (cLength) {
              const neAttrs = this.treeAdapter.getAttrList(newElement);
              const neAttrsLength = neAttrs.length;
              const neAttrsMap = Object.create(null);
  
              //NOTE: build attrs map for the new element so we can perform fast lookups
              for (let i = 0; i < neAttrsLength; i++) {
                  const neAttr = neAttrs[i];
  
                  neAttrsMap[neAttr.name] = neAttr.value;
              }
  
              for (let i = 0; i < neAttrsLength; i++) {
                  for (let j = 0; j < cLength; j++) {
                      const cAttr = candidates[j].attrs[i];
  
                      if (neAttrsMap[cAttr.name] !== cAttr.value) {
                          candidates.splice(j, 1);
                          cLength--;
                      }
  
                      if (candidates.length < NOAH_ARK_CAPACITY) {
                          return;
                      }
                  }
              }
  
              //NOTE: remove bottommost candidates until Noah's Ark condition will not be met
              for (let i = cLength - 1; i >= NOAH_ARK_CAPACITY - 1; i--) {
                  this.entries.splice(candidates[i].idx, 1);
                  this.length--;
              }
          }
      }
  
      //Mutations
      insertMarker() {
          this.entries.push({ type: FormattingElementList.MARKER_ENTRY });
          this.length++;
      }
  
      pushElement(element, token) {
          this._ensureNoahArkCondition(element);
  
          this.entries.push({
              type: FormattingElementList.ELEMENT_ENTRY,
              element: element,
              token: token
          });
  
          this.length++;
      }
  
      insertElementAfterBookmark(element, token) {
          let bookmarkIdx = this.length - 1;
  
          for (; bookmarkIdx >= 0; bookmarkIdx--) {
              if (this.entries[bookmarkIdx] === this.bookmark) {
                  break;
              }
          }
  
          this.entries.splice(bookmarkIdx + 1, 0, {
              type: FormattingElementList.ELEMENT_ENTRY,
              element: element,
              token: token
          });
  
          this.length++;
      }
  
      removeEntry(entry) {
          for (let i = this.length - 1; i >= 0; i--) {
              if (this.entries[i] === entry) {
                  this.entries.splice(i, 1);
                  this.length--;
                  break;
              }
          }
      }
  
      clearToLastMarker() {
          while (this.length) {
              const entry = this.entries.pop();
  
              this.length--;
  
              if (entry.type === FormattingElementList.MARKER_ENTRY) {
                  break;
              }
          }
      }
  
      //Search
      getElementEntryInScopeWithTagName(tagName) {
          for (let i = this.length - 1; i >= 0; i--) {
              const entry = this.entries[i];
  
              if (entry.type === FormattingElementList.MARKER_ENTRY) {
                  return null;
              }
  
              if (this.treeAdapter.getTagName(entry.element) === tagName) {
                  return entry;
              }
          }
  
          return null;
      }
  
      getElementEntry(element) {
          for (let i = this.length - 1; i >= 0; i--) {
              const entry = this.entries[i];
  
              if (entry.type === FormattingElementList.ELEMENT_ENTRY && entry.element === element) {
                  return entry;
              }
          }
  
          return null;
      }
  }
  
  //Entry types
  FormattingElementList.MARKER_ENTRY = 'MARKER_ENTRY';
  FormattingElementList.ELEMENT_ENTRY = 'ELEMENT_ENTRY';
  
  var formattingElementList = FormattingElementList;
  
  class Mixin {
      constructor(host) {
          const originalMethods = {};
          const overriddenMethods = this._getOverriddenMethods(this, originalMethods);
  
          for (const key of Object.keys(overriddenMethods)) {
              if (typeof overriddenMethods[key] === 'function') {
                  originalMethods[key] = host[key];
                  host[key] = overriddenMethods[key];
              }
          }
      }
  
      _getOverriddenMethods() {
          throw new Error('Not implemented');
      }
  }
  
  Mixin.install = function(host, Ctor, opts) {
      if (!host.__mixins) {
          host.__mixins = [];
      }
  
      for (let i = 0; i < host.__mixins.length; i++) {
          if (host.__mixins[i].constructor === Ctor) {
              return host.__mixins[i];
          }
      }
  
      const mixin = new Ctor(host, opts);
  
      host.__mixins.push(mixin);
  
      return mixin;
  };
  
  var mixin = Mixin;
  
  class PositionTrackingPreprocessorMixin extends mixin {
      constructor(preprocessor) {
          super(preprocessor);
  
          this.preprocessor = preprocessor;
          this.isEol = false;
          this.lineStartPos = 0;
          this.droppedBufferSize = 0;
  
          this.offset = 0;
          this.col = 0;
          this.line = 1;
      }
  
      _getOverriddenMethods(mxn, orig) {
          return {
              advance() {
                  const pos = this.pos + 1;
                  const ch = this.html[pos];
  
                  //NOTE: LF should be in the last column of the line
                  if (mxn.isEol) {
                      mxn.isEol = false;
                      mxn.line++;
                      mxn.lineStartPos = pos;
                  }
  
                  if (ch === '\n' || (ch === '\r' && this.html[pos + 1] !== '\n')) {
                      mxn.isEol = true;
                  }
  
                  mxn.col = pos - mxn.lineStartPos + 1;
                  mxn.offset = mxn.droppedBufferSize + pos;
  
                  return orig.advance.call(this);
              },
  
              retreat() {
                  orig.retreat.call(this);
  
                  mxn.isEol = false;
                  mxn.col = this.pos - mxn.lineStartPos + 1;
              },
  
              dropParsedChunk() {
                  const prevPos = this.pos;
  
                  orig.dropParsedChunk.call(this);
  
                  const reduction = prevPos - this.pos;
  
                  mxn.lineStartPos -= reduction;
                  mxn.droppedBufferSize += reduction;
                  mxn.offset = mxn.droppedBufferSize + this.pos;
              }
          };
      }
  }
  
  var preprocessorMixin = PositionTrackingPreprocessorMixin;
  
  class LocationInfoTokenizerMixin extends mixin {
      constructor(tokenizer) {
          super(tokenizer);
  
          this.tokenizer = tokenizer;
          this.posTracker = mixin.install(tokenizer.preprocessor, preprocessorMixin);
          this.currentAttrLocation = null;
          this.ctLoc = null;
      }
  
      _getCurrentLocation() {
          return {
              startLine: this.posTracker.line,
              startCol: this.posTracker.col,
              startOffset: this.posTracker.offset,
              endLine: -1,
              endCol: -1,
              endOffset: -1
          };
      }
  
      _attachCurrentAttrLocationInfo() {
          this.currentAttrLocation.endLine = this.posTracker.line;
          this.currentAttrLocation.endCol = this.posTracker.col;
          this.currentAttrLocation.endOffset = this.posTracker.offset;
  
          const currentToken = this.tokenizer.currentToken;
          const currentAttr = this.tokenizer.currentAttr;
  
          if (!currentToken.location.attrs) {
              currentToken.location.attrs = Object.create(null);
          }
  
          currentToken.location.attrs[currentAttr.name] = this.currentAttrLocation;
      }
  
      _getOverriddenMethods(mxn, orig) {
          const methods = {
              _createStartTagToken() {
                  orig._createStartTagToken.call(this);
                  this.currentToken.location = mxn.ctLoc;
              },
  
              _createEndTagToken() {
                  orig._createEndTagToken.call(this);
                  this.currentToken.location = mxn.ctLoc;
              },
  
              _createCommentToken() {
                  orig._createCommentToken.call(this);
                  this.currentToken.location = mxn.ctLoc;
              },
  
              _createDoctypeToken(initialName) {
                  orig._createDoctypeToken.call(this, initialName);
                  this.currentToken.location = mxn.ctLoc;
              },
  
              _createCharacterToken(type, ch) {
                  orig._createCharacterToken.call(this, type, ch);
                  this.currentCharacterToken.location = mxn.ctLoc;
              },
  
              _createEOFToken() {
                  orig._createEOFToken.call(this);
                  this.currentToken.location = mxn._getCurrentLocation();
              },
  
              _createAttr(attrNameFirstCh) {
                  orig._createAttr.call(this, attrNameFirstCh);
                  mxn.currentAttrLocation = mxn._getCurrentLocation();
              },
  
              _leaveAttrName(toState) {
                  orig._leaveAttrName.call(this, toState);
                  mxn._attachCurrentAttrLocationInfo();
              },
  
              _leaveAttrValue(toState) {
                  orig._leaveAttrValue.call(this, toState);
                  mxn._attachCurrentAttrLocationInfo();
              },
  
              _emitCurrentToken() {
                  const ctLoc = this.currentToken.location;
  
                  //NOTE: if we have pending character token make it's end location equal to the
                  //current token's start location.
                  if (this.currentCharacterToken) {
                      this.currentCharacterToken.location.endLine = ctLoc.startLine;
                      this.currentCharacterToken.location.endCol = ctLoc.startCol;
                      this.currentCharacterToken.location.endOffset = ctLoc.startOffset;
                  }
  
                  if (this.currentToken.type === tokenizer.EOF_TOKEN) {
                      ctLoc.endLine = ctLoc.startLine;
                      ctLoc.endCol = ctLoc.startCol;
                      ctLoc.endOffset = ctLoc.startOffset;
                  } else {
                      ctLoc.endLine = mxn.posTracker.line;
                      ctLoc.endCol = mxn.posTracker.col + 1;
                      ctLoc.endOffset = mxn.posTracker.offset + 1;
                  }
  
                  orig._emitCurrentToken.call(this);
              },
  
              _emitCurrentCharacterToken() {
                  const ctLoc = this.currentCharacterToken && this.currentCharacterToken.location;
  
                  //NOTE: if we have character token and it's location wasn't set in the _emitCurrentToken(),
                  //then set it's location at the current preprocessor position.
                  //We don't need to increment preprocessor position, since character token
                  //emission is always forced by the start of the next character token here.
                  //So, we already have advanced position.
                  if (ctLoc && ctLoc.endOffset === -1) {
                      ctLoc.endLine = mxn.posTracker.line;
                      ctLoc.endCol = mxn.posTracker.col;
                      ctLoc.endOffset = mxn.posTracker.offset;
                  }
  
                  orig._emitCurrentCharacterToken.call(this);
              }
          };
  
          //NOTE: patch initial states for each mode to obtain token start position
          Object.keys(tokenizer.MODE).forEach(modeName => {
              const state = tokenizer.MODE[modeName];
  
              methods[state] = function(cp) {
                  mxn.ctLoc = mxn._getCurrentLocation();
                  orig[state].call(this, cp);
              };
          });
  
          return methods;
      }
  }
  
  var tokenizerMixin = LocationInfoTokenizerMixin;
  
  class LocationInfoOpenElementStackMixin extends mixin {
      constructor(stack, opts) {
          super(stack);
  
          this.onItemPop = opts.onItemPop;
      }
  
      _getOverriddenMethods(mxn, orig) {
          return {
              pop() {
                  mxn.onItemPop(this.current);
                  orig.pop.call(this);
              },
  
              popAllUpToHtmlElement() {
                  for (let i = this.stackTop; i > 0; i--) {
                      mxn.onItemPop(this.items[i]);
                  }
  
                  orig.popAllUpToHtmlElement.call(this);
              },
  
              remove(element) {
                  mxn.onItemPop(this.current);
                  orig.remove.call(this, element);
              }
          };
      }
  }
  
  var openElementStackMixin = LocationInfoOpenElementStackMixin;
  
  //Aliases
  const $$3 = html.TAG_NAMES;
  
  class LocationInfoParserMixin extends mixin {
      constructor(parser) {
          super(parser);
  
          this.parser = parser;
          this.treeAdapter = this.parser.treeAdapter;
          this.posTracker = null;
          this.lastStartTagToken = null;
          this.lastFosterParentingLocation = null;
          this.currentToken = null;
      }
  
      _setStartLocation(element) {
          let loc = null;
  
          if (this.lastStartTagToken) {
              loc = Object.assign({}, this.lastStartTagToken.location);
              loc.startTag = this.lastStartTagToken.location;
          }
  
          this.treeAdapter.setNodeSourceCodeLocation(element, loc);
      }
  
      _setEndLocation(element, closingToken) {
          const loc = this.treeAdapter.getNodeSourceCodeLocation(element);
  
          if (loc) {
              if (closingToken.location) {
                  const ctLoc = closingToken.location;
                  const tn = this.treeAdapter.getTagName(element);
  
                  // NOTE: For cases like <p> <p> </p> - First 'p' closes without a closing
                  // tag and for cases like <td> <p> </td> - 'p' closes without a closing tag.
                  const isClosingEndTag = closingToken.type === tokenizer.END_TAG_TOKEN && tn === closingToken.tagName;
  
                  if (isClosingEndTag) {
                      loc.endTag = Object.assign({}, ctLoc);
                      loc.endLine = ctLoc.endLine;
                      loc.endCol = ctLoc.endCol;
                      loc.endOffset = ctLoc.endOffset;
                  } else {
                      loc.endLine = ctLoc.startLine;
                      loc.endCol = ctLoc.startCol;
                      loc.endOffset = ctLoc.startOffset;
                  }
              }
          }
      }
  
      _getOverriddenMethods(mxn, orig) {
          return {
              _bootstrap(document, fragmentContext) {
                  orig._bootstrap.call(this, document, fragmentContext);
  
                  mxn.lastStartTagToken = null;
                  mxn.lastFosterParentingLocation = null;
                  mxn.currentToken = null;
  
                  const tokenizerMixin$1 = mixin.install(this.tokenizer, tokenizerMixin);
  
                  mxn.posTracker = tokenizerMixin$1.posTracker;
  
                  mixin.install(this.openElements, openElementStackMixin, {
                      onItemPop: function(element) {
                          mxn._setEndLocation(element, mxn.currentToken);
                      }
                  });
              },
  
              _runParsingLoop(scriptHandler) {
                  orig._runParsingLoop.call(this, scriptHandler);
  
                  // NOTE: generate location info for elements
                  // that remains on open element stack
                  for (let i = this.openElements.stackTop; i >= 0; i--) {
                      mxn._setEndLocation(this.openElements.items[i], mxn.currentToken);
                  }
              },
  
              //Token processing
              _processTokenInForeignContent(token) {
                  mxn.currentToken = token;
                  orig._processTokenInForeignContent.call(this, token);
              },
  
              _processToken(token) {
                  mxn.currentToken = token;
                  orig._processToken.call(this, token);
  
                  //NOTE: <body> and <html> are never popped from the stack, so we need to updated
                  //their end location explicitly.
                  const requireExplicitUpdate =
                      token.type === tokenizer.END_TAG_TOKEN &&
                      (token.tagName === $$3.HTML || (token.tagName === $$3.BODY && this.openElements.hasInScope($$3.BODY)));
  
                  if (requireExplicitUpdate) {
                      for (let i = this.openElements.stackTop; i >= 0; i--) {
                          const element = this.openElements.items[i];
  
                          if (this.treeAdapter.getTagName(element) === token.tagName) {
                              mxn._setEndLocation(element, token);
                              break;
                          }
                      }
                  }
              },
  
              //Doctype
              _setDocumentType(token) {
                  orig._setDocumentType.call(this, token);
  
                  const documentChildren = this.treeAdapter.getChildNodes(this.document);
                  const cnLength = documentChildren.length;
  
                  for (let i = 0; i < cnLength; i++) {
                      const node = documentChildren[i];
  
                      if (this.treeAdapter.isDocumentTypeNode(node)) {
                          this.treeAdapter.setNodeSourceCodeLocation(node, token.location);
                          break;
                      }
                  }
              },
  
              //Elements
              _attachElementToTree(element) {
                  //NOTE: _attachElementToTree is called from _appendElement, _insertElement and _insertTemplate methods.
                  //So we will use token location stored in this methods for the element.
                  mxn._setStartLocation(element);
                  mxn.lastStartTagToken = null;
                  orig._attachElementToTree.call(this, element);
              },
  
              _appendElement(token, namespaceURI) {
                  mxn.lastStartTagToken = token;
                  orig._appendElement.call(this, token, namespaceURI);
              },
  
              _insertElement(token, namespaceURI) {
                  mxn.lastStartTagToken = token;
                  orig._insertElement.call(this, token, namespaceURI);
              },
  
              _insertTemplate(token) {
                  mxn.lastStartTagToken = token;
                  orig._insertTemplate.call(this, token);
  
                  const tmplContent = this.treeAdapter.getTemplateContent(this.openElements.current);
  
                  this.treeAdapter.setNodeSourceCodeLocation(tmplContent, null);
              },
  
              _insertFakeRootElement() {
                  orig._insertFakeRootElement.call(this);
                  this.treeAdapter.setNodeSourceCodeLocation(this.openElements.current, null);
              },
  
              //Comments
              _appendCommentNode(token, parent) {
                  orig._appendCommentNode.call(this, token, parent);
  
                  const children = this.treeAdapter.getChildNodes(parent);
                  const commentNode = children[children.length - 1];
  
                  this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location);
              },
  
              //Text
              _findFosterParentingLocation() {
                  //NOTE: store last foster parenting location, so we will be able to find inserted text
                  //in case of foster parenting
                  mxn.lastFosterParentingLocation = orig._findFosterParentingLocation.call(this);
  
                  return mxn.lastFosterParentingLocation;
              },
  
              _insertCharacters(token) {
                  orig._insertCharacters.call(this, token);
  
                  const hasFosterParent = this._shouldFosterParentOnInsertion();
  
                  const parent =
                      (hasFosterParent && mxn.lastFosterParentingLocation.parent) ||
                      this.openElements.currentTmplContent ||
                      this.openElements.current;
  
                  const siblings = this.treeAdapter.getChildNodes(parent);
  
                  const textNodeIdx =
                      hasFosterParent && mxn.lastFosterParentingLocation.beforeElement
                          ? siblings.indexOf(mxn.lastFosterParentingLocation.beforeElement) - 1
                          : siblings.length - 1;
  
                  const textNode = siblings[textNodeIdx];
  
                  //NOTE: if we have location assigned by another token, then just update end position
                  const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode);
  
                  if (tnLoc) {
                      tnLoc.endLine = token.location.endLine;
                      tnLoc.endCol = token.location.endCol;
                      tnLoc.endOffset = token.location.endOffset;
                  } else {
                      this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location);
                  }
              }
          };
      }
  }
  
  var parserMixin = LocationInfoParserMixin;
  
  class ErrorReportingMixinBase extends mixin {
      constructor(host, opts) {
          super(host);
  
          this.posTracker = null;
          this.onParseError = opts.onParseError;
      }
  
      _setErrorLocation(err) {
          err.startLine = err.endLine = this.posTracker.line;
          err.startCol = err.endCol = this.posTracker.col;
          err.startOffset = err.endOffset = this.posTracker.offset;
      }
  
      _reportError(code) {
          const err = {
              code: code,
              startLine: -1,
              startCol: -1,
              startOffset: -1,
              endLine: -1,
              endCol: -1,
              endOffset: -1
          };
  
          this._setErrorLocation(err);
          this.onParseError(err);
      }
  
      _getOverriddenMethods(mxn) {
          return {
              _err(code) {
                  mxn._reportError(code);
              }
          };
      }
  }
  
  var mixinBase = ErrorReportingMixinBase;
  
  class ErrorReportingPreprocessorMixin extends mixinBase {
      constructor(preprocessor, opts) {
          super(preprocessor, opts);
  
          this.posTracker = mixin.install(preprocessor, preprocessorMixin);
          this.lastErrOffset = -1;
      }
  
      _reportError(code) {
          //NOTE: avoid reporting error twice on advance/retreat
          if (this.lastErrOffset !== this.posTracker.offset) {
              this.lastErrOffset = this.posTracker.offset;
              super._reportError(code);
          }
      }
  }
  
  var preprocessorMixin$1 = ErrorReportingPreprocessorMixin;
  
  class ErrorReportingTokenizerMixin extends mixinBase {
      constructor(tokenizer, opts) {
          super(tokenizer, opts);
  
          const preprocessorMixin = mixin.install(tokenizer.preprocessor, preprocessorMixin$1, opts);
  
          this.posTracker = preprocessorMixin.posTracker;
      }
  }
  
  var tokenizerMixin$1 = ErrorReportingTokenizerMixin;
  
  class ErrorReportingParserMixin extends mixinBase {
      constructor(parser, opts) {
          super(parser, opts);
  
          this.opts = opts;
          this.ctLoc = null;
          this.locBeforeToken = false;
      }
  
      _setErrorLocation(err) {
          if (this.ctLoc) {
              err.startLine = this.ctLoc.startLine;
              err.startCol = this.ctLoc.startCol;
              err.startOffset = this.ctLoc.startOffset;
  
              err.endLine = this.locBeforeToken ? this.ctLoc.startLine : this.ctLoc.endLine;
              err.endCol = this.locBeforeToken ? this.ctLoc.startCol : this.ctLoc.endCol;
              err.endOffset = this.locBeforeToken ? this.ctLoc.startOffset : this.ctLoc.endOffset;
          }
      }
  
      _getOverriddenMethods(mxn, orig) {
          return {
              _bootstrap(document, fragmentContext) {
                  orig._bootstrap.call(this, document, fragmentContext);
  
                  mixin.install(this.tokenizer, tokenizerMixin$1, mxn.opts);
                  mixin.install(this.tokenizer, tokenizerMixin);
              },
  
              _processInputToken(token) {
                  mxn.ctLoc = token.location;
  
                  orig._processInputToken.call(this, token);
              },
  
              _err(code, options) {
                  mxn.locBeforeToken = options && options.beforeToken;
                  mxn._reportError(code);
              }
          };
      }
  }
  
  var parserMixin$1 = ErrorReportingParserMixin;
  
  var _default = createCommonjsModule(function (module, exports) {
  
  const { DOCUMENT_MODE } = html;
  
  //Node construction
  exports.createDocument = function() {
      return {
          nodeName: '#document',
          mode: DOCUMENT_MODE.NO_QUIRKS,
          childNodes: []
      };
  };
  
  exports.createDocumentFragment = function() {
      return {
          nodeName: '#document-fragment',
          childNodes: []
      };
  };
  
  exports.createElement = function(tagName, namespaceURI, attrs) {
      return {
          nodeName: tagName,
          tagName: tagName,
          attrs: attrs,
          namespaceURI: namespaceURI,
          childNodes: [],
          parentNode: null
      };
  };
  
  exports.createCommentNode = function(data) {
      return {
          nodeName: '#comment',
          data: data,
          parentNode: null
      };
  };
  
  const createTextNode = function(value) {
      return {
          nodeName: '#text',
          value: value,
          parentNode: null
      };
  };
  
  //Tree mutation
  const appendChild = (exports.appendChild = function(parentNode, newNode) {
      parentNode.childNodes.push(newNode);
      newNode.parentNode = parentNode;
  });
  
  const insertBefore = (exports.insertBefore = function(parentNode, newNode, referenceNode) {
      const insertionIdx = parentNode.childNodes.indexOf(referenceNode);
  
      parentNode.childNodes.splice(insertionIdx, 0, newNode);
      newNode.parentNode = parentNode;
  });
  
  exports.setTemplateContent = function(templateElement, contentElement) {
      templateElement.content = contentElement;
  };
  
  exports.getTemplateContent = function(templateElement) {
      return templateElement.content;
  };
  
  exports.setDocumentType = function(document, name, publicId, systemId) {
      let doctypeNode = null;
  
      for (let i = 0; i < document.childNodes.length; i++) {
          if (document.childNodes[i].nodeName === '#documentType') {
              doctypeNode = document.childNodes[i];
              break;
          }
      }
  
      if (doctypeNode) {
          doctypeNode.name = name;
          doctypeNode.publicId = publicId;
          doctypeNode.systemId = systemId;
      } else {
          appendChild(document, {
              nodeName: '#documentType',
              name: name,
              publicId: publicId,
              systemId: systemId
          });
      }
  };
  
  exports.setDocumentMode = function(document, mode) {
      document.mode = mode;
  };
  
  exports.getDocumentMode = function(document) {
      return document.mode;
  };
  
  exports.detachNode = function(node) {
      if (node.parentNode) {
          const idx = node.parentNode.childNodes.indexOf(node);
  
          node.parentNode.childNodes.splice(idx, 1);
          node.parentNode = null;
      }
  };
  
  exports.insertText = function(parentNode, text) {
      if (parentNode.childNodes.length) {
          const prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
  
          if (prevNode.nodeName === '#text') {
              prevNode.value += text;
              return;
          }
      }
  
      appendChild(parentNode, createTextNode(text));
  };
  
  exports.insertTextBefore = function(parentNode, text, referenceNode) {
      const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
  
      if (prevNode && prevNode.nodeName === '#text') {
          prevNode.value += text;
      } else {
          insertBefore(parentNode, createTextNode(text), referenceNode);
      }
  };
  
  exports.adoptAttributes = function(recipient, attrs) {
      const recipientAttrsMap = [];
  
      for (let i = 0; i < recipient.attrs.length; i++) {
          recipientAttrsMap.push(recipient.attrs[i].name);
      }
  
      for (let j = 0; j < attrs.length; j++) {
          if (recipientAttrsMap.indexOf(attrs[j].name) === -1) {
              recipient.attrs.push(attrs[j]);
          }
      }
  };
  
  //Tree traversing
  exports.getFirstChild = function(node) {
      return node.childNodes[0];
  };
  
  exports.getChildNodes = function(node) {
      return node.childNodes;
  };
  
  exports.getParentNode = function(node) {
      return node.parentNode;
  };
  
  exports.getAttrList = function(element) {
      return element.attrs;
  };
  
  //Node data
  exports.getTagName = function(element) {
      return element.tagName;
  };
  
  exports.getNamespaceURI = function(element) {
      return element.namespaceURI;
  };
  
  exports.getTextNodeContent = function(textNode) {
      return textNode.value;
  };
  
  exports.getCommentNodeContent = function(commentNode) {
      return commentNode.data;
  };
  
  exports.getDocumentTypeNodeName = function(doctypeNode) {
      return doctypeNode.name;
  };
  
  exports.getDocumentTypeNodePublicId = function(doctypeNode) {
      return doctypeNode.publicId;
  };
  
  exports.getDocumentTypeNodeSystemId = function(doctypeNode) {
      return doctypeNode.systemId;
  };
  
  //Node types
  exports.isTextNode = function(node) {
      return node.nodeName === '#text';
  };
  
  exports.isCommentNode = function(node) {
      return node.nodeName === '#comment';
  };
  
  exports.isDocumentTypeNode = function(node) {
      return node.nodeName === '#documentType';
  };
  
  exports.isElementNode = function(node) {
      return !!node.tagName;
  };
  
  // Source code location
  exports.setNodeSourceCodeLocation = function(node, location) {
      node.sourceCodeLocation = location;
  };
  
  exports.getNodeSourceCodeLocation = function(node) {
      return node.sourceCodeLocation;
  };
  });
  var _default_1 = _default.createDocument;
  var _default_2 = _default.createDocumentFragment;
  var _default_3 = _default.createElement;
  var _default_4 = _default.createCommentNode;
  var _default_5 = _default.appendChild;
  var _default_6 = _default.insertBefore;
  var _default_7 = _default.setTemplateContent;
  var _default_8 = _default.getTemplateContent;
  var _default_9 = _default.setDocumentType;
  var _default_10 = _default.setDocumentMode;
  var _default_11 = _default.getDocumentMode;
  var _default_12 = _default.detachNode;
  var _default_13 = _default.insertText;
  var _default_14 = _default.insertTextBefore;
  var _default_15 = _default.adoptAttributes;
  var _default_16 = _default.getFirstChild;
  var _default_17 = _default.getChildNodes;
  var _default_18 = _default.getParentNode;
  var _default_19 = _default.getAttrList;
  var _default_20 = _default.getTagName;
  var _default_21 = _default.getNamespaceURI;
  var _default_22 = _default.getTextNodeContent;
  var _default_23 = _default.getCommentNodeContent;
  var _default_24 = _default.getDocumentTypeNodeName;
  var _default_25 = _default.getDocumentTypeNodePublicId;
  var _default_26 = _default.getDocumentTypeNodeSystemId;
  var _default_27 = _default.isTextNode;
  var _default_28 = _default.isCommentNode;
  var _default_29 = _default.isDocumentTypeNode;
  var _default_30 = _default.isElementNode;
  var _default_31 = _default.setNodeSourceCodeLocation;
  var _default_32 = _default.getNodeSourceCodeLocation;
  
  var mergeOptions = function mergeOptions(defaults, options) {
      options = options || Object.create(null);
  
      return [defaults, options].reduce((merged, optObj) => {
          Object.keys(optObj).forEach(key => {
              merged[key] = optObj[key];
          });
  
          return merged;
      }, Object.create(null));
  };
  
  const { DOCUMENT_MODE } = html;
  
  //Const
  const VALID_DOCTYPE_NAME = 'html';
  const VALID_SYSTEM_ID = 'about:legacy-compat';
  const QUIRKS_MODE_SYSTEM_ID = 'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd';
  
  const QUIRKS_MODE_PUBLIC_ID_PREFIXES = [
      '+//silmaril//dtd html pro v0r11 19970101//en',
      '-//advasoft ltd//dtd html 3.0 aswedit + extensions//en',
      '-//as//dtd html 3.0 aswedit + extensions//en',
      '-//ietf//dtd html 2.0 level 1//en',
      '-//ietf//dtd html 2.0 level 2//en',
      '-//ietf//dtd html 2.0 strict level 1//en',
      '-//ietf//dtd html 2.0 strict level 2//en',
      '-//ietf//dtd html 2.0 strict//en',
      '-//ietf//dtd html 2.0//en',
      '-//ietf//dtd html 2.1e//en',
      '-//ietf//dtd html 3.0//en',
      '-//ietf//dtd html 3.0//en//',
      '-//ietf//dtd html 3.2 final//en',
      '-//ietf//dtd html 3.2//en',
      '-//ietf//dtd html 3//en',
      '-//ietf//dtd html level 0//en',
      '-//ietf//dtd html level 0//en//2.0',
      '-//ietf//dtd html level 1//en',
      '-//ietf//dtd html level 1//en//2.0',
      '-//ietf//dtd html level 2//en',
      '-//ietf//dtd html level 2//en//2.0',
      '-//ietf//dtd html level 3//en',
      '-//ietf//dtd html level 3//en//3.0',
      '-//ietf//dtd html strict level 0//en',
      '-//ietf//dtd html strict level 0//en//2.0',
      '-//ietf//dtd html strict level 1//en',
      '-//ietf//dtd html strict level 1//en//2.0',
      '-//ietf//dtd html strict level 2//en',
      '-//ietf//dtd html strict level 2//en//2.0',
      '-//ietf//dtd html strict level 3//en',
      '-//ietf//dtd html strict level 3//en//3.0',
      '-//ietf//dtd html strict//en',
      '-//ietf//dtd html strict//en//2.0',
      '-//ietf//dtd html strict//en//3.0',
      '-//ietf//dtd html//en',
      '-//ietf//dtd html//en//2.0',
      '-//ietf//dtd html//en//3.0',
      '-//metrius//dtd metrius presentational//en',
      '-//microsoft//dtd internet explorer 2.0 html strict//en',
      '-//microsoft//dtd internet explorer 2.0 html//en',
      '-//microsoft//dtd internet explorer 2.0 tables//en',
      '-//microsoft//dtd internet explorer 3.0 html strict//en',
      '-//microsoft//dtd internet explorer 3.0 html//en',
      '-//microsoft//dtd internet explorer 3.0 tables//en',
      '-//netscape comm. corp.//dtd html//en',
      '-//netscape comm. corp.//dtd strict html//en',
      "-//o'reilly and associates//dtd html 2.0//en",
      "-//o'reilly and associates//dtd html extended 1.0//en",
      '-//spyglass//dtd html 2.0 extended//en',
      '-//sq//dtd html 2.0 hotmetal + extensions//en',
      '-//sun microsystems corp.//dtd hotjava html//en',
      '-//sun microsystems corp.//dtd hotjava strict html//en',
      '-//w3c//dtd html 3 1995-03-24//en',
      '-//w3c//dtd html 3.2 draft//en',
      '-//w3c//dtd html 3.2 final//en',
      '-//w3c//dtd html 3.2//en',
      '-//w3c//dtd html 3.2s draft//en',
      '-//w3c//dtd html 4.0 frameset//en',
      '-//w3c//dtd html 4.0 transitional//en',
      '-//w3c//dtd html experimental 19960712//en',
      '-//w3c//dtd html experimental 970421//en',
      '-//w3c//dtd w3 html//en',
      '-//w3o//dtd w3 html 3.0//en',
      '-//w3o//dtd w3 html 3.0//en//',
      '-//webtechs//dtd mozilla html 2.0//en',
      '-//webtechs//dtd mozilla html//en'
  ];
  
  const QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES = QUIRKS_MODE_PUBLIC_ID_PREFIXES.concat([
      '-//w3c//dtd html 4.01 frameset//',
      '-//w3c//dtd html 4.01 transitional//'
  ]);
  
  const QUIRKS_MODE_PUBLIC_IDS = ['-//w3o//dtd w3 html strict 3.0//en//', '-/w3c/dtd html 4.0 transitional/en', 'html'];
  const LIMITED_QUIRKS_PUBLIC_ID_PREFIXES = ['-//W3C//DTD XHTML 1.0 Frameset//', '-//W3C//DTD XHTML 1.0 Transitional//'];
  
  const LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES = LIMITED_QUIRKS_PUBLIC_ID_PREFIXES.concat([
      '-//W3C//DTD HTML 4.01 Frameset//',
      '-//W3C//DTD HTML 4.01 Transitional//'
  ]);
  
  //Utils
  function enquoteDoctypeId(id) {
      const quote = id.indexOf('"') !== -1 ? "'" : '"';
  
      return quote + id + quote;
  }
  
  function hasPrefix(publicId, prefixes) {
      for (let i = 0; i < prefixes.length; i++) {
          if (publicId.indexOf(prefixes[i]) === 0) {
              return true;
          }
      }
  
      return false;
  }
  
  //API
  var isConforming = function(token) {
      return (
          token.name === VALID_DOCTYPE_NAME &&
          token.publicId === null &&
          (token.systemId === null || token.systemId === VALID_SYSTEM_ID)
      );
  };
  
  var getDocumentMode = function(token) {
      if (token.name !== VALID_DOCTYPE_NAME) {
          return DOCUMENT_MODE.QUIRKS;
      }
  
      const systemId = token.systemId;
  
      if (systemId && systemId.toLowerCase() === QUIRKS_MODE_SYSTEM_ID) {
          return DOCUMENT_MODE.QUIRKS;
      }
  
      let publicId = token.publicId;
  
      if (publicId !== null) {
          publicId = publicId.toLowerCase();
  
          if (QUIRKS_MODE_PUBLIC_IDS.indexOf(publicId) > -1) {
              return DOCUMENT_MODE.QUIRKS;
          }
  
          let prefixes = systemId === null ? QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES : QUIRKS_MODE_PUBLIC_ID_PREFIXES;
  
          if (hasPrefix(publicId, prefixes)) {
              return DOCUMENT_MODE.QUIRKS;
          }
  
          prefixes =
              systemId === null ? LIMITED_QUIRKS_PUBLIC_ID_PREFIXES : LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES;
  
          if (hasPrefix(publicId, prefixes)) {
              return DOCUMENT_MODE.LIMITED_QUIRKS;
          }
      }
  
      return DOCUMENT_MODE.NO_QUIRKS;
  };
  
  var serializeContent = function(name, publicId, systemId) {
      let str = '!DOCTYPE ';
  
      if (name) {
          str += name;
      }
  
      if (publicId) {
          str += ' PUBLIC ' + enquoteDoctypeId(publicId);
      } else if (systemId) {
          str += ' SYSTEM';
      }
  
      if (systemId !== null) {
          str += ' ' + enquoteDoctypeId(systemId);
      }
  
      return str;
  };
  
  var doctype = {
  	isConforming: isConforming,
  	getDocumentMode: getDocumentMode,
  	serializeContent: serializeContent
  };
  
  var foreignContent = createCommonjsModule(function (module, exports) {
  
  
  
  
  //Aliases
  const $ = html.TAG_NAMES;
  const NS = html.NAMESPACES;
  const ATTRS = html.ATTRS;
  
  //MIME types
  const MIME_TYPES = {
      TEXT_HTML: 'text/html',
      APPLICATION_XML: 'application/xhtml+xml'
  };
  
  //Attributes
  const DEFINITION_URL_ATTR = 'definitionurl';
  const ADJUSTED_DEFINITION_URL_ATTR = 'definitionURL';
  const SVG_ATTRS_ADJUSTMENT_MAP = {
      attributename: 'attributeName',
      attributetype: 'attributeType',
      basefrequency: 'baseFrequency',
      baseprofile: 'baseProfile',
      calcmode: 'calcMode',
      clippathunits: 'clipPathUnits',
      diffuseconstant: 'diffuseConstant',
      edgemode: 'edgeMode',
      filterunits: 'filterUnits',
      glyphref: 'glyphRef',
      gradienttransform: 'gradientTransform',
      gradientunits: 'gradientUnits',
      kernelmatrix: 'kernelMatrix',
      kernelunitlength: 'kernelUnitLength',
      keypoints: 'keyPoints',
      keysplines: 'keySplines',
      keytimes: 'keyTimes',
      lengthadjust: 'lengthAdjust',
      limitingconeangle: 'limitingConeAngle',
      markerheight: 'markerHeight',
      markerunits: 'markerUnits',
      markerwidth: 'markerWidth',
      maskcontentunits: 'maskContentUnits',
      maskunits: 'maskUnits',
      numoctaves: 'numOctaves',
      pathlength: 'pathLength',
      patterncontentunits: 'patternContentUnits',
      patterntransform: 'patternTransform',
      patternunits: 'patternUnits',
      pointsatx: 'pointsAtX',
      pointsaty: 'pointsAtY',
      pointsatz: 'pointsAtZ',
      preservealpha: 'preserveAlpha',
      preserveaspectratio: 'preserveAspectRatio',
      primitiveunits: 'primitiveUnits',
      refx: 'refX',
      refy: 'refY',
      repeatcount: 'repeatCount',
      repeatdur: 'repeatDur',
      requiredextensions: 'requiredExtensions',
      requiredfeatures: 'requiredFeatures',
      specularconstant: 'specularConstant',
      specularexponent: 'specularExponent',
      spreadmethod: 'spreadMethod',
      startoffset: 'startOffset',
      stddeviation: 'stdDeviation',
      stitchtiles: 'stitchTiles',
      surfacescale: 'surfaceScale',
      systemlanguage: 'systemLanguage',
      tablevalues: 'tableValues',
      targetx: 'targetX',
      targety: 'targetY',
      textlength: 'textLength',
      viewbox: 'viewBox',
      viewtarget: 'viewTarget',
      xchannelselector: 'xChannelSelector',
      ychannelselector: 'yChannelSelector',
      zoomandpan: 'zoomAndPan'
  };
  
  const XML_ATTRS_ADJUSTMENT_MAP = {
      'xlink:actuate': { prefix: 'xlink', name: 'actuate', namespace: NS.XLINK },
      'xlink:arcrole': { prefix: 'xlink', name: 'arcrole', namespace: NS.XLINK },
      'xlink:href': { prefix: 'xlink', name: 'href', namespace: NS.XLINK },
      'xlink:role': { prefix: 'xlink', name: 'role', namespace: NS.XLINK },
      'xlink:show': { prefix: 'xlink', name: 'show', namespace: NS.XLINK },
      'xlink:title': { prefix: 'xlink', name: 'title', namespace: NS.XLINK },
      'xlink:type': { prefix: 'xlink', name: 'type', namespace: NS.XLINK },
      'xml:base': { prefix: 'xml', name: 'base', namespace: NS.XML },
      'xml:lang': { prefix: 'xml', name: 'lang', namespace: NS.XML },
      'xml:space': { prefix: 'xml', name: 'space', namespace: NS.XML },
      xmlns: { prefix: '', name: 'xmlns', namespace: NS.XMLNS },
      'xmlns:xlink': { prefix: 'xmlns', name: 'xlink', namespace: NS.XMLNS }
  };
  
  //SVG tag names adjustment map
  const SVG_TAG_NAMES_ADJUSTMENT_MAP = (exports.SVG_TAG_NAMES_ADJUSTMENT_MAP = {
      altglyph: 'altGlyph',
      altglyphdef: 'altGlyphDef',
      altglyphitem: 'altGlyphItem',
      animatecolor: 'animateColor',
      animatemotion: 'animateMotion',
      animatetransform: 'animateTransform',
      clippath: 'clipPath',
      feblend: 'feBlend',
      fecolormatrix: 'feColorMatrix',
      fecomponenttransfer: 'feComponentTransfer',
      fecomposite: 'feComposite',
      feconvolvematrix: 'feConvolveMatrix',
      fediffuselighting: 'feDiffuseLighting',
      fedisplacementmap: 'feDisplacementMap',
      fedistantlight: 'feDistantLight',
      feflood: 'feFlood',
      fefunca: 'feFuncA',
      fefuncb: 'feFuncB',
      fefuncg: 'feFuncG',
      fefuncr: 'feFuncR',
      fegaussianblur: 'feGaussianBlur',
      feimage: 'feImage',
      femerge: 'feMerge',
      femergenode: 'feMergeNode',
      femorphology: 'feMorphology',
      feoffset: 'feOffset',
      fepointlight: 'fePointLight',
      fespecularlighting: 'feSpecularLighting',
      fespotlight: 'feSpotLight',
      fetile: 'feTile',
      feturbulence: 'feTurbulence',
      foreignobject: 'foreignObject',
      glyphref: 'glyphRef',
      lineargradient: 'linearGradient',
      radialgradient: 'radialGradient',
      textpath: 'textPath'
  });
  
  //Tags that causes exit from foreign content
  const EXITS_FOREIGN_CONTENT = {
      [$.B]: true,
      [$.BIG]: true,
      [$.BLOCKQUOTE]: true,
      [$.BODY]: true,
      [$.BR]: true,
      [$.CENTER]: true,
      [$.CODE]: true,
      [$.DD]: true,
      [$.DIV]: true,
      [$.DL]: true,
      [$.DT]: true,
      [$.EM]: true,
      [$.EMBED]: true,
      [$.H1]: true,
      [$.H2]: true,
      [$.H3]: true,
      [$.H4]: true,
      [$.H5]: true,
      [$.H6]: true,
      [$.HEAD]: true,
      [$.HR]: true,
      [$.I]: true,
      [$.IMG]: true,
      [$.LI]: true,
      [$.LISTING]: true,
      [$.MENU]: true,
      [$.META]: true,
      [$.NOBR]: true,
      [$.OL]: true,
      [$.P]: true,
      [$.PRE]: true,
      [$.RUBY]: true,
      [$.S]: true,
      [$.SMALL]: true,
      [$.SPAN]: true,
      [$.STRONG]: true,
      [$.STRIKE]: true,
      [$.SUB]: true,
      [$.SUP]: true,
      [$.TABLE]: true,
      [$.TT]: true,
      [$.U]: true,
      [$.UL]: true,
      [$.VAR]: true
  };
  
  //Check exit from foreign content
  exports.causesExit = function(startTagToken) {
      const tn = startTagToken.tagName;
      const isFontWithAttrs =
          tn === $.FONT &&
          (tokenizer.getTokenAttr(startTagToken, ATTRS.COLOR) !== null ||
              tokenizer.getTokenAttr(startTagToken, ATTRS.SIZE) !== null ||
              tokenizer.getTokenAttr(startTagToken, ATTRS.FACE) !== null);
  
      return isFontWithAttrs ? true : EXITS_FOREIGN_CONTENT[tn];
  };
  
  //Token adjustments
  exports.adjustTokenMathMLAttrs = function(token) {
      for (let i = 0; i < token.attrs.length; i++) {
          if (token.attrs[i].name === DEFINITION_URL_ATTR) {
              token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR;
              break;
          }
      }
  };
  
  exports.adjustTokenSVGAttrs = function(token) {
      for (let i = 0; i < token.attrs.length; i++) {
          const adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
  
          if (adjustedAttrName) {
              token.attrs[i].name = adjustedAttrName;
          }
      }
  };
  
  exports.adjustTokenXMLAttrs = function(token) {
      for (let i = 0; i < token.attrs.length; i++) {
          const adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
  
          if (adjustedAttrEntry) {
              token.attrs[i].prefix = adjustedAttrEntry.prefix;
              token.attrs[i].name = adjustedAttrEntry.name;
              token.attrs[i].namespace = adjustedAttrEntry.namespace;
          }
      }
  };
  
  exports.adjustTokenSVGTagName = function(token) {
      const adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP[token.tagName];
  
      if (adjustedTagName) {
          token.tagName = adjustedTagName;
      }
  };
  
  //Integration points
  function isMathMLTextIntegrationPoint(tn, ns) {
      return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT);
  }
  
  function isHtmlIntegrationPoint(tn, ns, attrs) {
      if (ns === NS.MATHML && tn === $.ANNOTATION_XML) {
          for (let i = 0; i < attrs.length; i++) {
              if (attrs[i].name === ATTRS.ENCODING) {
                  const value = attrs[i].value.toLowerCase();
  
                  return value === MIME_TYPES.TEXT_HTML || value === MIME_TYPES.APPLICATION_XML;
              }
          }
      }
  
      return ns === NS.SVG && (tn === $.FOREIGN_OBJECT || tn === $.DESC || tn === $.TITLE);
  }
  
  exports.isIntegrationPoint = function(tn, ns, attrs, foreignNS) {
      if ((!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs)) {
          return true;
      }
  
      if ((!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns)) {
          return true;
      }
  
      return false;
  };
  });
  var foreignContent_1 = foreignContent.SVG_TAG_NAMES_ADJUSTMENT_MAP;
  var foreignContent_2 = foreignContent.causesExit;
  var foreignContent_3 = foreignContent.adjustTokenMathMLAttrs;
  var foreignContent_4 = foreignContent.adjustTokenSVGAttrs;
  var foreignContent_5 = foreignContent.adjustTokenXMLAttrs;
  var foreignContent_6 = foreignContent.adjustTokenSVGTagName;
  var foreignContent_7 = foreignContent.isIntegrationPoint;
  
  //Aliases
  const $$4 = html.TAG_NAMES;
  const NS$1 = html.NAMESPACES;
  const ATTRS = html.ATTRS;
  
  const DEFAULT_OPTIONS = {
      scriptingEnabled: true,
      sourceCodeLocationInfo: false,
      onParseError: null,
      treeAdapter: _default
  };
  
  //Misc constants
  const HIDDEN_INPUT_TYPE = 'hidden';
  
  //Adoption agency loops iteration count
  const AA_OUTER_LOOP_ITER = 8;
  const AA_INNER_LOOP_ITER = 3;
  
  //Insertion modes
  const INITIAL_MODE = 'INITIAL_MODE';
  const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE';
  const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE';
  const IN_HEAD_MODE = 'IN_HEAD_MODE';
  const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE';
  const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE';
  const IN_BODY_MODE = 'IN_BODY_MODE';
  const TEXT_MODE = 'TEXT_MODE';
  const IN_TABLE_MODE = 'IN_TABLE_MODE';
  const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE';
  const IN_CAPTION_MODE = 'IN_CAPTION_MODE';
  const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE';
  const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE';
  const IN_ROW_MODE = 'IN_ROW_MODE';
  const IN_CELL_MODE = 'IN_CELL_MODE';
  const IN_SELECT_MODE = 'IN_SELECT_MODE';
  const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE';
  const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE';
  const AFTER_BODY_MODE = 'AFTER_BODY_MODE';
  const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE';
  const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE';
  const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE';
  const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE';
  
  //Insertion mode reset map
  const INSERTION_MODE_RESET_MAP = {
      [$$4.TR]: IN_ROW_MODE,
      [$$4.TBODY]: IN_TABLE_BODY_MODE,
      [$$4.THEAD]: IN_TABLE_BODY_MODE,
      [$$4.TFOOT]: IN_TABLE_BODY_MODE,
      [$$4.CAPTION]: IN_CAPTION_MODE,
      [$$4.COLGROUP]: IN_COLUMN_GROUP_MODE,
      [$$4.TABLE]: IN_TABLE_MODE,
      [$$4.BODY]: IN_BODY_MODE,
      [$$4.FRAMESET]: IN_FRAMESET_MODE
  };
  
  //Template insertion mode switch map
  const TEMPLATE_INSERTION_MODE_SWITCH_MAP = {
      [$$4.CAPTION]: IN_TABLE_MODE,
      [$$4.COLGROUP]: IN_TABLE_MODE,
      [$$4.TBODY]: IN_TABLE_MODE,
      [$$4.TFOOT]: IN_TABLE_MODE,
      [$$4.THEAD]: IN_TABLE_MODE,
      [$$4.COL]: IN_COLUMN_GROUP_MODE,
      [$$4.TR]: IN_TABLE_BODY_MODE,
      [$$4.TD]: IN_ROW_MODE,
      [$$4.TH]: IN_ROW_MODE
  };
  
  //Token handlers map for insertion modes
  const TOKEN_HANDLERS = {
      [INITIAL_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenInInitialMode,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode,
          [tokenizer.START_TAG_TOKEN]: tokenInInitialMode,
          [tokenizer.END_TAG_TOKEN]: tokenInInitialMode,
          [tokenizer.EOF_TOKEN]: tokenInInitialMode
      },
      [BEFORE_HTML_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagBeforeHtml,
          [tokenizer.END_TAG_TOKEN]: endTagBeforeHtml,
          [tokenizer.EOF_TOKEN]: tokenBeforeHtml
      },
      [BEFORE_HEAD_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenBeforeHead,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
          [tokenizer.START_TAG_TOKEN]: startTagBeforeHead,
          [tokenizer.END_TAG_TOKEN]: endTagBeforeHead,
          [tokenizer.EOF_TOKEN]: tokenBeforeHead
      },
      [IN_HEAD_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenInHead,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
          [tokenizer.START_TAG_TOKEN]: startTagInHead,
          [tokenizer.END_TAG_TOKEN]: endTagInHead,
          [tokenizer.EOF_TOKEN]: tokenInHead
      },
      [IN_HEAD_NO_SCRIPT_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
          [tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript,
          [tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript,
          [tokenizer.EOF_TOKEN]: tokenInHeadNoScript
      },
      [AFTER_HEAD_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenAfterHead,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
          [tokenizer.START_TAG_TOKEN]: startTagAfterHead,
          [tokenizer.END_TAG_TOKEN]: endTagAfterHead,
          [tokenizer.EOF_TOKEN]: tokenAfterHead
      },
      [IN_BODY_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInBody,
          [tokenizer.END_TAG_TOKEN]: endTagInBody,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [TEXT_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: ignoreToken,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: ignoreToken,
          [tokenizer.END_TAG_TOKEN]: endTagInText,
          [tokenizer.EOF_TOKEN]: eofInText
      },
      [IN_TABLE_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInTable,
          [tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInTable,
          [tokenizer.END_TAG_TOKEN]: endTagInTable,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_TABLE_TEXT_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInTableText,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText,
          [tokenizer.COMMENT_TOKEN]: tokenInTableText,
          [tokenizer.DOCTYPE_TOKEN]: tokenInTableText,
          [tokenizer.START_TAG_TOKEN]: tokenInTableText,
          [tokenizer.END_TAG_TOKEN]: tokenInTableText,
          [tokenizer.EOF_TOKEN]: tokenInTableText
      },
      [IN_CAPTION_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInCaption,
          [tokenizer.END_TAG_TOKEN]: endTagInCaption,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_COLUMN_GROUP_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInColumnGroup,
          [tokenizer.END_TAG_TOKEN]: endTagInColumnGroup,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_TABLE_BODY_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInTable,
          [tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInTableBody,
          [tokenizer.END_TAG_TOKEN]: endTagInTableBody,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_ROW_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInTable,
          [tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInRow,
          [tokenizer.END_TAG_TOKEN]: endTagInRow,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_CELL_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInCell,
          [tokenizer.END_TAG_TOKEN]: endTagInCell,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_SELECT_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInSelect,
          [tokenizer.END_TAG_TOKEN]: endTagInSelect,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_SELECT_IN_TABLE_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInSelectInTable,
          [tokenizer.END_TAG_TOKEN]: endTagInSelectInTable,
          [tokenizer.EOF_TOKEN]: eofInBody
      },
      [IN_TEMPLATE_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: characterInBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInTemplate,
          [tokenizer.END_TAG_TOKEN]: endTagInTemplate,
          [tokenizer.EOF_TOKEN]: eofInTemplate
      },
      [AFTER_BODY_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenAfterBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagAfterBody,
          [tokenizer.END_TAG_TOKEN]: endTagAfterBody,
          [tokenizer.EOF_TOKEN]: stopParsing
      },
      [IN_FRAMESET_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagInFrameset,
          [tokenizer.END_TAG_TOKEN]: endTagInFrameset,
          [tokenizer.EOF_TOKEN]: stopParsing
      },
      [AFTER_FRAMESET_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
          [tokenizer.COMMENT_TOKEN]: appendComment,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagAfterFrameset,
          [tokenizer.END_TAG_TOKEN]: endTagAfterFrameset,
          [tokenizer.EOF_TOKEN]: stopParsing
      },
      [AFTER_AFTER_BODY_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody,
          [tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendCommentToDocument,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody,
          [tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody,
          [tokenizer.EOF_TOKEN]: stopParsing
      },
      [AFTER_AFTER_FRAMESET_MODE]: {
          [tokenizer.CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
          [tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
          [tokenizer.COMMENT_TOKEN]: appendCommentToDocument,
          [tokenizer.DOCTYPE_TOKEN]: ignoreToken,
          [tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset,
          [tokenizer.END_TAG_TOKEN]: ignoreToken,
          [tokenizer.EOF_TOKEN]: stopParsing
      }
  };
  
  //Parser
  class Parser {
      constructor(options) {
          this.options = mergeOptions(DEFAULT_OPTIONS, options);
  
          this.treeAdapter = this.options.treeAdapter;
          this.pendingScript = null;
  
          if (this.options.sourceCodeLocationInfo) {
              mixin.install(this, parserMixin);
          }
  
          if (this.options.onParseError) {
              mixin.install(this, parserMixin$1, { onParseError: this.options.onParseError });
          }
      }
  
      // API
      parse(html) {
          const document = this.treeAdapter.createDocument();
  
          this._bootstrap(document, null);
          this.tokenizer.write(html, true);
          this._runParsingLoop(null);
  
          return document;
      }
  
      parseFragment(html, fragmentContext) {
          //NOTE: use <template> element as a fragment context if context element was not provided,
          //so we will parse in "forgiving" manner
          if (!fragmentContext) {
              fragmentContext = this.treeAdapter.createElement($$4.TEMPLATE, NS$1.HTML, []);
          }
  
          //NOTE: create fake element which will be used as 'document' for fragment parsing.
          //This is important for jsdom there 'document' can't be recreated, therefore
          //fragment parsing causes messing of the main `document`.
          const documentMock = this.treeAdapter.createElement('documentmock', NS$1.HTML, []);
  
          this._bootstrap(documentMock, fragmentContext);
  
          if (this.treeAdapter.getTagName(fragmentContext) === $$4.TEMPLATE) {
              this._pushTmplInsertionMode(IN_TEMPLATE_MODE);
          }
  
          this._initTokenizerForFragmentParsing();
          this._insertFakeRootElement();
          this._resetInsertionMode();
          this._findFormInFragmentContext();
          this.tokenizer.write(html, true);
          this._runParsingLoop(null);
  
          const rootElement = this.treeAdapter.getFirstChild(documentMock);
          const fragment = this.treeAdapter.createDocumentFragment();
  
          this._adoptNodes(rootElement, fragment);
  
          return fragment;
      }
  
      //Bootstrap parser
      _bootstrap(document, fragmentContext) {
          this.tokenizer = new tokenizer(this.options);
  
          this.stopped = false;
  
          this.insertionMode = INITIAL_MODE;
          this.originalInsertionMode = '';
  
          this.document = document;
          this.fragmentContext = fragmentContext;
  
          this.headElement = null;
          this.formElement = null;
  
          this.openElements = new openElementStack(this.document, this.treeAdapter);
          this.activeFormattingElements = new formattingElementList(this.treeAdapter);
  
          this.tmplInsertionModeStack = [];
          this.tmplInsertionModeStackTop = -1;
          this.currentTmplInsertionMode = null;
  
          this.pendingCharacterTokens = [];
          this.hasNonWhitespacePendingCharacterToken = false;
  
          this.framesetOk = true;
          this.skipNextNewLine = false;
          this.fosterParentingEnabled = false;
      }
  
      //Errors
      _err() {
          // NOTE: err reporting is noop by default. Enabled by mixin.
      }
  
      //Parsing loop
      _runParsingLoop(scriptHandler) {
          while (!this.stopped) {
              this._setupTokenizerCDATAMode();
  
              const token = this.tokenizer.getNextToken();
  
              if (token.type === tokenizer.HIBERNATION_TOKEN) {
                  break;
              }
  
              if (this.skipNextNewLine) {
                  this.skipNextNewLine = false;
  
                  if (token.type === tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {
                      if (token.chars.length === 1) {
                          continue;
                      }
  
                      token.chars = token.chars.substr(1);
                  }
              }
  
              this._processInputToken(token);
  
              if (scriptHandler && this.pendingScript) {
                  break;
              }
          }
      }
  
      runParsingLoopForCurrentChunk(writeCallback, scriptHandler) {
          this._runParsingLoop(scriptHandler);
  
          if (scriptHandler && this.pendingScript) {
              const script = this.pendingScript;
  
              this.pendingScript = null;
  
              scriptHandler(script);
  
              return;
          }
  
          if (writeCallback) {
              writeCallback();
          }
      }
  
      //Text parsing
      _setupTokenizerCDATAMode() {
          const current = this._getAdjustedCurrentElement();
  
          this.tokenizer.allowCDATA =
              current &&
              current !== this.document &&
              this.treeAdapter.getNamespaceURI(current) !== NS$1.HTML &&
              !this._isIntegrationPoint(current);
      }
  
      _switchToTextParsing(currentToken, nextTokenizerState) {
          this._insertElement(currentToken, NS$1.HTML);
          this.tokenizer.state = nextTokenizerState;
          this.originalInsertionMode = this.insertionMode;
          this.insertionMode = TEXT_MODE;
      }
  
      switchToPlaintextParsing() {
          this.insertionMode = TEXT_MODE;
          this.originalInsertionMode = IN_BODY_MODE;
          this.tokenizer.state = tokenizer.MODE.PLAINTEXT;
      }
  
      //Fragment parsing
      _getAdjustedCurrentElement() {
          return this.openElements.stackTop === 0 && this.fragmentContext
              ? this.fragmentContext
              : this.openElements.current;
      }
  
      _findFormInFragmentContext() {
          let node = this.fragmentContext;
  
          do {
              if (this.treeAdapter.getTagName(node) === $$4.FORM) {
                  this.formElement = node;
                  break;
              }
  
              node = this.treeAdapter.getParentNode(node);
          } while (node);
      }
  
      _initTokenizerForFragmentParsing() {
          if (this.treeAdapter.getNamespaceURI(this.fragmentContext) === NS$1.HTML) {
              const tn = this.treeAdapter.getTagName(this.fragmentContext);
  
              if (tn === $$4.TITLE || tn === $$4.TEXTAREA) {
                  this.tokenizer.state = tokenizer.MODE.RCDATA;
              } else if (
                  tn === $$4.STYLE ||
                  tn === $$4.XMP ||
                  tn === $$4.IFRAME ||
                  tn === $$4.NOEMBED ||
                  tn === $$4.NOFRAMES ||
                  tn === $$4.NOSCRIPT
              ) {
                  this.tokenizer.state = tokenizer.MODE.RAWTEXT;
              } else if (tn === $$4.SCRIPT) {
                  this.tokenizer.state = tokenizer.MODE.SCRIPT_DATA;
              } else if (tn === $$4.PLAINTEXT) {
                  this.tokenizer.state = tokenizer.MODE.PLAINTEXT;
              }
          }
      }
  
      //Tree mutation
      _setDocumentType(token) {
          const name = token.name || '';
          const publicId = token.publicId || '';
          const systemId = token.systemId || '';
  
          this.treeAdapter.setDocumentType(this.document, name, publicId, systemId);
      }
  
      _attachElementToTree(element) {
          if (this._shouldFosterParentOnInsertion()) {
              this._fosterParentElement(element);
          } else {
              const parent = this.openElements.currentTmplContent || this.openElements.current;
  
              this.treeAdapter.appendChild(parent, element);
          }
      }
  
      _appendElement(token, namespaceURI) {
          const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
  
          this._attachElementToTree(element);
      }
  
      _insertElement(token, namespaceURI) {
          const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
  
          this._attachElementToTree(element);
          this.openElements.push(element);
      }
  
      _insertFakeElement(tagName) {
          const element = this.treeAdapter.createElement(tagName, NS$1.HTML, []);
  
          this._attachElementToTree(element);
          this.openElements.push(element);
      }
  
      _insertTemplate(token) {
          const tmpl = this.treeAdapter.createElement(token.tagName, NS$1.HTML, token.attrs);
          const content = this.treeAdapter.createDocumentFragment();
  
          this.treeAdapter.setTemplateContent(tmpl, content);
          this._attachElementToTree(tmpl);
          this.openElements.push(tmpl);
      }
  
      _insertFakeRootElement() {
          const element = this.treeAdapter.createElement($$4.HTML, NS$1.HTML, []);
  
          this.treeAdapter.appendChild(this.openElements.current, element);
          this.openElements.push(element);
      }
  
      _appendCommentNode(token, parent) {
          const commentNode = this.treeAdapter.createCommentNode(token.data);
  
          this.treeAdapter.appendChild(parent, commentNode);
      }
  
      _insertCharacters(token) {
          if (this._shouldFosterParentOnInsertion()) {
              this._fosterParentText(token.chars);
          } else {
              const parent = this.openElements.currentTmplContent || this.openElements.current;
  
              this.treeAdapter.insertText(parent, token.chars);
          }
      }
  
      _adoptNodes(donor, recipient) {
          for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) {
              this.treeAdapter.detachNode(child);
              this.treeAdapter.appendChild(recipient, child);
          }
      }
  
      //Token processing
      _shouldProcessTokenInForeignContent(token) {
          const current = this._getAdjustedCurrentElement();
  
          if (!current || current === this.document) {
              return false;
          }
  
          const ns = this.treeAdapter.getNamespaceURI(current);
  
          if (ns === NS$1.HTML) {
              return false;
          }
  
          if (
              this.treeAdapter.getTagName(current) === $$4.ANNOTATION_XML &&
              ns === NS$1.MATHML &&
              token.type === tokenizer.START_TAG_TOKEN &&
              token.tagName === $$4.SVG
          ) {
              return false;
          }
  
          const isCharacterToken =
              token.type === tokenizer.CHARACTER_TOKEN ||
              token.type === tokenizer.NULL_CHARACTER_TOKEN ||
              token.type === tokenizer.WHITESPACE_CHARACTER_TOKEN;
  
          const isMathMLTextStartTag =
              token.type === tokenizer.START_TAG_TOKEN && token.tagName !== $$4.MGLYPH && token.tagName !== $$4.MALIGNMARK;
  
          if ((isMathMLTextStartTag || isCharacterToken) && this._isIntegrationPoint(current, NS$1.MATHML)) {
              return false;
          }
  
          if (
              (token.type === tokenizer.START_TAG_TOKEN || isCharacterToken) &&
              this._isIntegrationPoint(current, NS$1.HTML)
          ) {
              return false;
          }
  
          return token.type !== tokenizer.EOF_TOKEN;
      }
  
      _processToken(token) {
          TOKEN_HANDLERS[this.insertionMode][token.type](this, token);
      }
  
      _processTokenInBodyMode(token) {
          TOKEN_HANDLERS[IN_BODY_MODE][token.type](this, token);
      }
  
      _processTokenInForeignContent(token) {
          if (token.type === tokenizer.CHARACTER_TOKEN) {
              characterInForeignContent(this, token);
          } else if (token.type === tokenizer.NULL_CHARACTER_TOKEN) {
              nullCharacterInForeignContent(this, token);
          } else if (token.type === tokenizer.WHITESPACE_CHARACTER_TOKEN) {
              insertCharacters(this, token);
          } else if (token.type === tokenizer.COMMENT_TOKEN) {
              appendComment(this, token);
          } else if (token.type === tokenizer.START_TAG_TOKEN) {
              startTagInForeignContent(this, token);
          } else if (token.type === tokenizer.END_TAG_TOKEN) {
              endTagInForeignContent(this, token);
          }
      }
  
      _processInputToken(token) {
          if (this._shouldProcessTokenInForeignContent(token)) {
              this._processTokenInForeignContent(token);
          } else {
              this._processToken(token);
          }
  
          if (token.type === tokenizer.START_TAG_TOKEN && token.selfClosing && !token.ackSelfClosing) {
              this._err(errorCodes.nonVoidHtmlElementStartTagWithTrailingSolidus);
          }
      }
  
      //Integration points
      _isIntegrationPoint(element, foreignNS) {
          const tn = this.treeAdapter.getTagName(element);
          const ns = this.treeAdapter.getNamespaceURI(element);
          const attrs = this.treeAdapter.getAttrList(element);
  
          return foreignContent.isIntegrationPoint(tn, ns, attrs, foreignNS);
      }
  
      //Active formatting elements reconstruction
      _reconstructActiveFormattingElements() {
          const listLength = this.activeFormattingElements.length;
  
          if (listLength) {
              let unopenIdx = listLength;
              let entry = null;
  
              do {
                  unopenIdx--;
                  entry = this.activeFormattingElements.entries[unopenIdx];
  
                  if (entry.type === formattingElementList.MARKER_ENTRY || this.openElements.contains(entry.element)) {
                      unopenIdx++;
                      break;
                  }
              } while (unopenIdx > 0);
  
              for (let i = unopenIdx; i < listLength; i++) {
                  entry = this.activeFormattingElements.entries[i];
                  this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element));
                  entry.element = this.openElements.current;
              }
          }
      }
  
      //Close elements
      _closeTableCell() {
          this.openElements.generateImpliedEndTags();
          this.openElements.popUntilTableCellPopped();
          this.activeFormattingElements.clearToLastMarker();
          this.insertionMode = IN_ROW_MODE;
      }
  
      _closePElement() {
          this.openElements.generateImpliedEndTagsWithExclusion($$4.P);
          this.openElements.popUntilTagNamePopped($$4.P);
      }
  
      //Insertion modes
      _resetInsertionMode() {
          for (let i = this.openElements.stackTop, last = false; i >= 0; i--) {
              let element = this.openElements.items[i];
  
              if (i === 0) {
                  last = true;
  
                  if (this.fragmentContext) {
                      element = this.fragmentContext;
                  }
              }
  
              const tn = this.treeAdapter.getTagName(element);
              const newInsertionMode = INSERTION_MODE_RESET_MAP[tn];
  
              if (newInsertionMode) {
                  this.insertionMode = newInsertionMode;
                  break;
              } else if (!last && (tn === $$4.TD || tn === $$4.TH)) {
                  this.insertionMode = IN_CELL_MODE;
                  break;
              } else if (!last && tn === $$4.HEAD) {
                  this.insertionMode = IN_HEAD_MODE;
                  break;
              } else if (tn === $$4.SELECT) {
                  this._resetInsertionModeForSelect(i);
                  break;
              } else if (tn === $$4.TEMPLATE) {
                  this.insertionMode = this.currentTmplInsertionMode;
                  break;
              } else if (tn === $$4.HTML) {
                  this.insertionMode = this.headElement ? AFTER_HEAD_MODE : BEFORE_HEAD_MODE;
                  break;
              } else if (last) {
                  this.insertionMode = IN_BODY_MODE;
                  break;
              }
          }
      }
  
      _resetInsertionModeForSelect(selectIdx) {
          if (selectIdx > 0) {
              for (let i = selectIdx - 1; i > 0; i--) {
                  const ancestor = this.openElements.items[i];
                  const tn = this.treeAdapter.getTagName(ancestor);
  
                  if (tn === $$4.TEMPLATE) {
                      break;
                  } else if (tn === $$4.TABLE) {
                      this.insertionMode = IN_SELECT_IN_TABLE_MODE;
                      return;
                  }
              }
          }
  
          this.insertionMode = IN_SELECT_MODE;
      }
  
      _pushTmplInsertionMode(mode) {
          this.tmplInsertionModeStack.push(mode);
          this.tmplInsertionModeStackTop++;
          this.currentTmplInsertionMode = mode;
      }
  
      _popTmplInsertionMode() {
          this.tmplInsertionModeStack.pop();
          this.tmplInsertionModeStackTop--;
          this.currentTmplInsertionMode = this.tmplInsertionModeStack[this.tmplInsertionModeStackTop];
      }
  
      //Foster parenting
      _isElementCausesFosterParenting(element) {
          const tn = this.treeAdapter.getTagName(element);
  
          return tn === $$4.TABLE || tn === $$4.TBODY || tn === $$4.TFOOT || tn === $$4.THEAD || tn === $$4.TR;
      }
  
      _shouldFosterParentOnInsertion() {
          return this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current);
      }
  
      _findFosterParentingLocation() {
          const location = {
              parent: null,
              beforeElement: null
          };
  
          for (let i = this.openElements.stackTop; i >= 0; i--) {
              const openElement = this.openElements.items[i];
              const tn = this.treeAdapter.getTagName(openElement);
              const ns = this.treeAdapter.getNamespaceURI(openElement);
  
              if (tn === $$4.TEMPLATE && ns === NS$1.HTML) {
                  location.parent = this.treeAdapter.getTemplateContent(openElement);
                  break;
              } else if (tn === $$4.TABLE) {
                  location.parent = this.treeAdapter.getParentNode(openElement);
  
                  if (location.parent) {
                      location.beforeElement = openElement;
                  } else {
                      location.parent = this.openElements.items[i - 1];
                  }
  
                  break;
              }
          }
  
          if (!location.parent) {
              location.parent = this.openElements.items[0];
          }
  
          return location;
      }
  
      _fosterParentElement(element) {
          const location = this._findFosterParentingLocation();
  
          if (location.beforeElement) {
              this.treeAdapter.insertBefore(location.parent, element, location.beforeElement);
          } else {
              this.treeAdapter.appendChild(location.parent, element);
          }
      }
  
      _fosterParentText(chars) {
          const location = this._findFosterParentingLocation();
  
          if (location.beforeElement) {
              this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement);
          } else {
              this.treeAdapter.insertText(location.parent, chars);
          }
      }
  
      //Special elements
      _isSpecialElement(element) {
          const tn = this.treeAdapter.getTagName(element);
          const ns = this.treeAdapter.getNamespaceURI(element);
  
          return html.SPECIAL_ELEMENTS[ns][tn];
      }
  }
  
  var parser = Parser;
  
  //Adoption agency algorithm
  //(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency)
  //------------------------------------------------------------------
  
  //Steps 5-8 of the algorithm
  function aaObtainFormattingElementEntry(p, token) {
      let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName);
  
      if (formattingElementEntry) {
          if (!p.openElements.contains(formattingElementEntry.element)) {
              p.activeFormattingElements.removeEntry(formattingElementEntry);
              formattingElementEntry = null;
          } else if (!p.openElements.hasInScope(token.tagName)) {
              formattingElementEntry = null;
          }
      } else {
          genericEndTagInBody(p, token);
      }
  
      return formattingElementEntry;
  }
  
  //Steps 9 and 10 of the algorithm
  function aaObtainFurthestBlock(p, formattingElementEntry) {
      let furthestBlock = null;
  
      for (let i = p.openElements.stackTop; i >= 0; i--) {
          const element = p.openElements.items[i];
  
          if (element === formattingElementEntry.element) {
              break;
          }
  
          if (p._isSpecialElement(element)) {
              furthestBlock = element;
          }
      }
  
      if (!furthestBlock) {
          p.openElements.popUntilElementPopped(formattingElementEntry.element);
          p.activeFormattingElements.removeEntry(formattingElementEntry);
      }
  
      return furthestBlock;
  }
  
  //Step 13 of the algorithm
  function aaInnerLoop(p, furthestBlock, formattingElement) {
      let lastElement = furthestBlock;
      let nextElement = p.openElements.getCommonAncestor(furthestBlock);
  
      for (let i = 0, element = nextElement; element !== formattingElement; i++, element = nextElement) {
          //NOTE: store next element for the next loop iteration (it may be deleted from the stack by step 9.5)
          nextElement = p.openElements.getCommonAncestor(element);
  
          const elementEntry = p.activeFormattingElements.getElementEntry(element);
          const counterOverflow = elementEntry && i >= AA_INNER_LOOP_ITER;
          const shouldRemoveFromOpenElements = !elementEntry || counterOverflow;
  
          if (shouldRemoveFromOpenElements) {
              if (counterOverflow) {
                  p.activeFormattingElements.removeEntry(elementEntry);
              }
  
              p.openElements.remove(element);
          } else {
              element = aaRecreateElementFromEntry(p, elementEntry);
  
              if (lastElement === furthestBlock) {
                  p.activeFormattingElements.bookmark = elementEntry;
              }
  
              p.treeAdapter.detachNode(lastElement);
              p.treeAdapter.appendChild(element, lastElement);
              lastElement = element;
          }
      }
  
      return lastElement;
  }
  
  //Step 13.7 of the algorithm
  function aaRecreateElementFromEntry(p, elementEntry) {
      const ns = p.treeAdapter.getNamespaceURI(elementEntry.element);
      const newElement = p.treeAdapter.createElement(elementEntry.token.tagName, ns, elementEntry.token.attrs);
  
      p.openElements.replace(elementEntry.element, newElement);
      elementEntry.element = newElement;
  
      return newElement;
  }
  
  //Step 14 of the algorithm
  function aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement) {
      if (p._isElementCausesFosterParenting(commonAncestor)) {
          p._fosterParentElement(lastElement);
      } else {
          const tn = p.treeAdapter.getTagName(commonAncestor);
          const ns = p.treeAdapter.getNamespaceURI(commonAncestor);
  
          if (tn === $$4.TEMPLATE && ns === NS$1.HTML) {
              commonAncestor = p.treeAdapter.getTemplateContent(commonAncestor);
          }
  
          p.treeAdapter.appendChild(commonAncestor, lastElement);
      }
  }
  
  //Steps 15-19 of the algorithm
  function aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) {
      const ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element);
      const token = formattingElementEntry.token;
      const newElement = p.treeAdapter.createElement(token.tagName, ns, token.attrs);
  
      p._adoptNodes(furthestBlock, newElement);
      p.treeAdapter.appendChild(furthestBlock, newElement);
  
      p.activeFormattingElements.insertElementAfterBookmark(newElement, formattingElementEntry.token);
      p.activeFormattingElements.removeEntry(formattingElementEntry);
  
      p.openElements.remove(formattingElementEntry.element);
      p.openElements.insertAfter(furthestBlock, newElement);
  }
  
  //Algorithm entry point
  function callAdoptionAgency(p, token) {
      let formattingElementEntry;
  
      for (let i = 0; i < AA_OUTER_LOOP_ITER; i++) {
          formattingElementEntry = aaObtainFormattingElementEntry(p, token);
  
          if (!formattingElementEntry) {
              break;
          }
  
          const furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry);
  
          if (!furthestBlock) {
              break;
          }
  
          p.activeFormattingElements.bookmark = formattingElementEntry;
  
          const lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element);
          const commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element);
  
          p.treeAdapter.detachNode(lastElement);
          aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement);
          aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry);
      }
  }
  
  //Generic token handlers
  //------------------------------------------------------------------
  function ignoreToken() {
      //NOTE: do nothing =)
  }
  
  function misplacedDoctype(p) {
      p._err(errorCodes.misplacedDoctype);
  }
  
  function appendComment(p, token) {
      p._appendCommentNode(token, p.openElements.currentTmplContent || p.openElements.current);
  }
  
  function appendCommentToRootHtmlElement(p, token) {
      p._appendCommentNode(token, p.openElements.items[0]);
  }
  
  function appendCommentToDocument(p, token) {
      p._appendCommentNode(token, p.document);
  }
  
  function insertCharacters(p, token) {
      p._insertCharacters(token);
  }
  
  function stopParsing(p) {
      p.stopped = true;
  }
  
  // The "initial" insertion mode
  //------------------------------------------------------------------
  function doctypeInInitialMode(p, token) {
      p._setDocumentType(token);
  
      const mode = token.forceQuirks ? html.DOCUMENT_MODE.QUIRKS : doctype.getDocumentMode(token);
  
      if (!doctype.isConforming(token)) {
          p._err(errorCodes.nonConformingDoctype);
      }
  
      p.treeAdapter.setDocumentMode(p.document, mode);
  
      p.insertionMode = BEFORE_HTML_MODE;
  }
  
  function tokenInInitialMode(p, token) {
      p._err(errorCodes.missingDoctype, { beforeToken: true });
      p.treeAdapter.setDocumentMode(p.document, html.DOCUMENT_MODE.QUIRKS);
      p.insertionMode = BEFORE_HTML_MODE;
      p._processToken(token);
  }
  
  // The "before html" insertion mode
  //------------------------------------------------------------------
  function startTagBeforeHtml(p, token) {
      if (token.tagName === $$4.HTML) {
          p._insertElement(token, NS$1.HTML);
          p.insertionMode = BEFORE_HEAD_MODE;
      } else {
          tokenBeforeHtml(p, token);
      }
  }
  
  function endTagBeforeHtml(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML || tn === $$4.HEAD || tn === $$4.BODY || tn === $$4.BR) {
          tokenBeforeHtml(p, token);
      }
  }
  
  function tokenBeforeHtml(p, token) {
      p._insertFakeRootElement();
      p.insertionMode = BEFORE_HEAD_MODE;
      p._processToken(token);
  }
  
  // The "before head" insertion mode
  //------------------------------------------------------------------
  function startTagBeforeHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.HEAD) {
          p._insertElement(token, NS$1.HTML);
          p.headElement = p.openElements.current;
          p.insertionMode = IN_HEAD_MODE;
      } else {
          tokenBeforeHead(p, token);
      }
  }
  
  function endTagBeforeHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HEAD || tn === $$4.BODY || tn === $$4.HTML || tn === $$4.BR) {
          tokenBeforeHead(p, token);
      } else {
          p._err(errorCodes.endTagWithoutMatchingOpenElement);
      }
  }
  
  function tokenBeforeHead(p, token) {
      p._insertFakeElement($$4.HEAD);
      p.headElement = p.openElements.current;
      p.insertionMode = IN_HEAD_MODE;
      p._processToken(token);
  }
  
  // The "in head" insertion mode
  //------------------------------------------------------------------
  function startTagInHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.BASE || tn === $$4.BASEFONT || tn === $$4.BGSOUND || tn === $$4.LINK || tn === $$4.META) {
          p._appendElement(token, NS$1.HTML);
          token.ackSelfClosing = true;
      } else if (tn === $$4.TITLE) {
          p._switchToTextParsing(token, tokenizer.MODE.RCDATA);
      } else if (tn === $$4.NOSCRIPT) {
          if (p.options.scriptingEnabled) {
              p._switchToTextParsing(token, tokenizer.MODE.RAWTEXT);
          } else {
              p._insertElement(token, NS$1.HTML);
              p.insertionMode = IN_HEAD_NO_SCRIPT_MODE;
          }
      } else if (tn === $$4.NOFRAMES || tn === $$4.STYLE) {
          p._switchToTextParsing(token, tokenizer.MODE.RAWTEXT);
      } else if (tn === $$4.SCRIPT) {
          p._switchToTextParsing(token, tokenizer.MODE.SCRIPT_DATA);
      } else if (tn === $$4.TEMPLATE) {
          p._insertTemplate(token, NS$1.HTML);
          p.activeFormattingElements.insertMarker();
          p.framesetOk = false;
          p.insertionMode = IN_TEMPLATE_MODE;
          p._pushTmplInsertionMode(IN_TEMPLATE_MODE);
      } else if (tn === $$4.HEAD) {
          p._err(errorCodes.misplacedStartTagForHeadElement);
      } else {
          tokenInHead(p, token);
      }
  }
  
  function endTagInHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HEAD) {
          p.openElements.pop();
          p.insertionMode = AFTER_HEAD_MODE;
      } else if (tn === $$4.BODY || tn === $$4.BR || tn === $$4.HTML) {
          tokenInHead(p, token);
      } else if (tn === $$4.TEMPLATE) {
          if (p.openElements.tmplCount > 0) {
              p.openElements.generateImpliedEndTagsThoroughly();
  
              if (p.openElements.currentTagName !== $$4.TEMPLATE) {
                  p._err(errorCodes.closingOfElementWithOpenChildElements);
              }
  
              p.openElements.popUntilTagNamePopped($$4.TEMPLATE);
              p.activeFormattingElements.clearToLastMarker();
              p._popTmplInsertionMode();
              p._resetInsertionMode();
          } else {
              p._err(errorCodes.endTagWithoutMatchingOpenElement);
          }
      } else {
          p._err(errorCodes.endTagWithoutMatchingOpenElement);
      }
  }
  
  function tokenInHead(p, token) {
      p.openElements.pop();
      p.insertionMode = AFTER_HEAD_MODE;
      p._processToken(token);
  }
  
  // The "in head no script" insertion mode
  //------------------------------------------------------------------
  function startTagInHeadNoScript(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (
          tn === $$4.BASEFONT ||
          tn === $$4.BGSOUND ||
          tn === $$4.HEAD ||
          tn === $$4.LINK ||
          tn === $$4.META ||
          tn === $$4.NOFRAMES ||
          tn === $$4.STYLE
      ) {
          startTagInHead(p, token);
      } else if (tn === $$4.NOSCRIPT) {
          p._err(errorCodes.nestedNoscriptInHead);
      } else {
          tokenInHeadNoScript(p, token);
      }
  }
  
  function endTagInHeadNoScript(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.NOSCRIPT) {
          p.openElements.pop();
          p.insertionMode = IN_HEAD_MODE;
      } else if (tn === $$4.BR) {
          tokenInHeadNoScript(p, token);
      } else {
          p._err(errorCodes.endTagWithoutMatchingOpenElement);
      }
  }
  
  function tokenInHeadNoScript(p, token) {
      const errCode =
          token.type === tokenizer.EOF_TOKEN ? errorCodes.openElementsLeftAfterEof : errorCodes.disallowedContentInNoscriptInHead;
  
      p._err(errCode);
      p.openElements.pop();
      p.insertionMode = IN_HEAD_MODE;
      p._processToken(token);
  }
  
  // The "after head" insertion mode
  //------------------------------------------------------------------
  function startTagAfterHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.BODY) {
          p._insertElement(token, NS$1.HTML);
          p.framesetOk = false;
          p.insertionMode = IN_BODY_MODE;
      } else if (tn === $$4.FRAMESET) {
          p._insertElement(token, NS$1.HTML);
          p.insertionMode = IN_FRAMESET_MODE;
      } else if (
          tn === $$4.BASE ||
          tn === $$4.BASEFONT ||
          tn === $$4.BGSOUND ||
          tn === $$4.LINK ||
          tn === $$4.META ||
          tn === $$4.NOFRAMES ||
          tn === $$4.SCRIPT ||
          tn === $$4.STYLE ||
          tn === $$4.TEMPLATE ||
          tn === $$4.TITLE
      ) {
          p._err(errorCodes.abandonedHeadElementChild);
          p.openElements.push(p.headElement);
          startTagInHead(p, token);
          p.openElements.remove(p.headElement);
      } else if (tn === $$4.HEAD) {
          p._err(errorCodes.misplacedStartTagForHeadElement);
      } else {
          tokenAfterHead(p, token);
      }
  }
  
  function endTagAfterHead(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.BODY || tn === $$4.HTML || tn === $$4.BR) {
          tokenAfterHead(p, token);
      } else if (tn === $$4.TEMPLATE) {
          endTagInHead(p, token);
      } else {
          p._err(errorCodes.endTagWithoutMatchingOpenElement);
      }
  }
  
  function tokenAfterHead(p, token) {
      p._insertFakeElement($$4.BODY);
      p.insertionMode = IN_BODY_MODE;
      p._processToken(token);
  }
  
  // The "in body" insertion mode
  //------------------------------------------------------------------
  function whitespaceCharacterInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertCharacters(token);
  }
  
  function characterInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertCharacters(token);
      p.framesetOk = false;
  }
  
  function htmlStartTagInBody(p, token) {
      if (p.openElements.tmplCount === 0) {
          p.treeAdapter.adoptAttributes(p.openElements.items[0], token.attrs);
      }
  }
  
  function bodyStartTagInBody(p, token) {
      const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();
  
      if (bodyElement && p.openElements.tmplCount === 0) {
          p.framesetOk = false;
          p.treeAdapter.adoptAttributes(bodyElement, token.attrs);
      }
  }
  
  function framesetStartTagInBody(p, token) {
      const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();
  
      if (p.framesetOk && bodyElement) {
          p.treeAdapter.detachNode(bodyElement);
          p.openElements.popAllUpToHtmlElement();
          p._insertElement(token, NS$1.HTML);
          p.insertionMode = IN_FRAMESET_MODE;
      }
  }
  
  function addressStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function numberedHeaderStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      const tn = p.openElements.currentTagName;
  
      if (tn === $$4.H1 || tn === $$4.H2 || tn === $$4.H3 || tn === $$4.H4 || tn === $$4.H5 || tn === $$4.H6) {
          p.openElements.pop();
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function preStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
      //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move
      //on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.)
      p.skipNextNewLine = true;
      p.framesetOk = false;
  }
  
  function formStartTagInBody(p, token) {
      const inTemplate = p.openElements.tmplCount > 0;
  
      if (!p.formElement || inTemplate) {
          if (p.openElements.hasInButtonScope($$4.P)) {
              p._closePElement();
          }
  
          p._insertElement(token, NS$1.HTML);
  
          if (!inTemplate) {
              p.formElement = p.openElements.current;
          }
      }
  }
  
  function listItemStartTagInBody(p, token) {
      p.framesetOk = false;
  
      const tn = token.tagName;
  
      for (let i = p.openElements.stackTop; i >= 0; i--) {
          const element = p.openElements.items[i];
          const elementTn = p.treeAdapter.getTagName(element);
          let closeTn = null;
  
          if (tn === $$4.LI && elementTn === $$4.LI) {
              closeTn = $$4.LI;
          } else if ((tn === $$4.DD || tn === $$4.DT) && (elementTn === $$4.DD || elementTn === $$4.DT)) {
              closeTn = elementTn;
          }
  
          if (closeTn) {
              p.openElements.generateImpliedEndTagsWithExclusion(closeTn);
              p.openElements.popUntilTagNamePopped(closeTn);
              break;
          }
  
          if (elementTn !== $$4.ADDRESS && elementTn !== $$4.DIV && elementTn !== $$4.P && p._isSpecialElement(element)) {
              break;
          }
      }
  
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function plaintextStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
      p.tokenizer.state = tokenizer.MODE.PLAINTEXT;
  }
  
  function buttonStartTagInBody(p, token) {
      if (p.openElements.hasInScope($$4.BUTTON)) {
          p.openElements.generateImpliedEndTags();
          p.openElements.popUntilTagNamePopped($$4.BUTTON);
      }
  
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
      p.framesetOk = false;
  }
  
  function aStartTagInBody(p, token) {
      const activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName($$4.A);
  
      if (activeElementEntry) {
          callAdoptionAgency(p, token);
          p.openElements.remove(activeElementEntry.element);
          p.activeFormattingElements.removeEntry(activeElementEntry);
      }
  
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
      p.activeFormattingElements.pushElement(p.openElements.current, token);
  }
  
  function bStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
      p.activeFormattingElements.pushElement(p.openElements.current, token);
  }
  
  function nobrStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
  
      if (p.openElements.hasInScope($$4.NOBR)) {
          callAdoptionAgency(p, token);
          p._reconstructActiveFormattingElements();
      }
  
      p._insertElement(token, NS$1.HTML);
      p.activeFormattingElements.pushElement(p.openElements.current, token);
  }
  
  function appletStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
      p.activeFormattingElements.insertMarker();
      p.framesetOk = false;
  }
  
  function tableStartTagInBody(p, token) {
      if (
          p.treeAdapter.getDocumentMode(p.document) !== html.DOCUMENT_MODE.QUIRKS &&
          p.openElements.hasInButtonScope($$4.P)
      ) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
      p.framesetOk = false;
      p.insertionMode = IN_TABLE_MODE;
  }
  
  function areaStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._appendElement(token, NS$1.HTML);
      p.framesetOk = false;
      token.ackSelfClosing = true;
  }
  
  function inputStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._appendElement(token, NS$1.HTML);
  
      const inputType = tokenizer.getTokenAttr(token, ATTRS.TYPE);
  
      if (!inputType || inputType.toLowerCase() !== HIDDEN_INPUT_TYPE) {
          p.framesetOk = false;
      }
  
      token.ackSelfClosing = true;
  }
  
  function paramStartTagInBody(p, token) {
      p._appendElement(token, NS$1.HTML);
      token.ackSelfClosing = true;
  }
  
  function hrStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._appendElement(token, NS$1.HTML);
      p.framesetOk = false;
      p.ackSelfClosing = true;
  }
  
  function imageStartTagInBody(p, token) {
      token.tagName = $$4.IMG;
      areaStartTagInBody(p, token);
  }
  
  function textareaStartTagInBody(p, token) {
      p._insertElement(token, NS$1.HTML);
      //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move
      //on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.)
      p.skipNextNewLine = true;
      p.tokenizer.state = tokenizer.MODE.RCDATA;
      p.originalInsertionMode = p.insertionMode;
      p.framesetOk = false;
      p.insertionMode = TEXT_MODE;
  }
  
  function xmpStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._reconstructActiveFormattingElements();
      p.framesetOk = false;
      p._switchToTextParsing(token, tokenizer.MODE.RAWTEXT);
  }
  
  function iframeStartTagInBody(p, token) {
      p.framesetOk = false;
      p._switchToTextParsing(token, tokenizer.MODE.RAWTEXT);
  }
  
  //NOTE: here we assume that we always act as an user agent with enabled plugins, so we parse
  //<noembed> as a rawtext.
  function noembedStartTagInBody(p, token) {
      p._switchToTextParsing(token, tokenizer.MODE.RAWTEXT);
  }
  
  function selectStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
      p.framesetOk = false;
  
      if (
          p.insertionMode === IN_TABLE_MODE ||
          p.insertionMode === IN_CAPTION_MODE ||
          p.insertionMode === IN_TABLE_BODY_MODE ||
          p.insertionMode === IN_ROW_MODE ||
          p.insertionMode === IN_CELL_MODE
      ) {
          p.insertionMode = IN_SELECT_IN_TABLE_MODE;
      } else {
          p.insertionMode = IN_SELECT_MODE;
      }
  }
  
  function optgroupStartTagInBody(p, token) {
      if (p.openElements.currentTagName === $$4.OPTION) {
          p.openElements.pop();
      }
  
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
  }
  
  function rbStartTagInBody(p, token) {
      if (p.openElements.hasInScope($$4.RUBY)) {
          p.openElements.generateImpliedEndTags();
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function rtStartTagInBody(p, token) {
      if (p.openElements.hasInScope($$4.RUBY)) {
          p.openElements.generateImpliedEndTagsWithExclusion($$4.RTC);
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function menuStartTagInBody(p, token) {
      if (p.openElements.hasInButtonScope($$4.P)) {
          p._closePElement();
      }
  
      p._insertElement(token, NS$1.HTML);
  }
  
  function mathStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
  
      foreignContent.adjustTokenMathMLAttrs(token);
      foreignContent.adjustTokenXMLAttrs(token);
  
      if (token.selfClosing) {
          p._appendElement(token, NS$1.MATHML);
      } else {
          p._insertElement(token, NS$1.MATHML);
      }
  
      token.ackSelfClosing = true;
  }
  
  function svgStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
  
      foreignContent.adjustTokenSVGAttrs(token);
      foreignContent.adjustTokenXMLAttrs(token);
  
      if (token.selfClosing) {
          p._appendElement(token, NS$1.SVG);
      } else {
          p._insertElement(token, NS$1.SVG);
      }
  
      token.ackSelfClosing = true;
  }
  
  function genericStartTagInBody(p, token) {
      p._reconstructActiveFormattingElements();
      p._insertElement(token, NS$1.HTML);
  }
  
  //OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
  //It's faster than using dictionary.
  function startTagInBody(p, token) {
      const tn = token.tagName;
  
      switch (tn.length) {
          case 1:
              if (tn === $$4.I || tn === $$4.S || tn === $$4.B || tn === $$4.U) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.P) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.A) {
                  aStartTagInBody(p, token);
              } else {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 2:
              if (tn === $$4.DL || tn === $$4.OL || tn === $$4.UL) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.H1 || tn === $$4.H2 || tn === $$4.H3 || tn === $$4.H4 || tn === $$4.H5 || tn === $$4.H6) {
                  numberedHeaderStartTagInBody(p, token);
              } else if (tn === $$4.LI || tn === $$4.DD || tn === $$4.DT) {
                  listItemStartTagInBody(p, token);
              } else if (tn === $$4.EM || tn === $$4.TT) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.BR) {
                  areaStartTagInBody(p, token);
              } else if (tn === $$4.HR) {
                  hrStartTagInBody(p, token);
              } else if (tn === $$4.RB) {
                  rbStartTagInBody(p, token);
              } else if (tn === $$4.RT || tn === $$4.RP) {
                  rtStartTagInBody(p, token);
              } else if (tn !== $$4.TH && tn !== $$4.TD && tn !== $$4.TR) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 3:
              if (tn === $$4.DIV || tn === $$4.DIR || tn === $$4.NAV) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.PRE) {
                  preStartTagInBody(p, token);
              } else if (tn === $$4.BIG) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.IMG || tn === $$4.WBR) {
                  areaStartTagInBody(p, token);
              } else if (tn === $$4.XMP) {
                  xmpStartTagInBody(p, token);
              } else if (tn === $$4.SVG) {
                  svgStartTagInBody(p, token);
              } else if (tn === $$4.RTC) {
                  rbStartTagInBody(p, token);
              } else if (tn !== $$4.COL) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 4:
              if (tn === $$4.HTML) {
                  htmlStartTagInBody(p, token);
              } else if (tn === $$4.BASE || tn === $$4.LINK || tn === $$4.META) {
                  startTagInHead(p, token);
              } else if (tn === $$4.BODY) {
                  bodyStartTagInBody(p, token);
              } else if (tn === $$4.MAIN || tn === $$4.MENU) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.FORM) {
                  formStartTagInBody(p, token);
              } else if (tn === $$4.CODE || tn === $$4.FONT) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.NOBR) {
                  nobrStartTagInBody(p, token);
              } else if (tn === $$4.AREA) {
                  areaStartTagInBody(p, token);
              } else if (tn === $$4.MATH) {
                  mathStartTagInBody(p, token);
              } else if (tn === $$4.MENU) {
                  menuStartTagInBody(p, token);
              } else if (tn !== $$4.HEAD) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 5:
              if (tn === $$4.STYLE || tn === $$4.TITLE) {
                  startTagInHead(p, token);
              } else if (tn === $$4.ASIDE) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.SMALL) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.TABLE) {
                  tableStartTagInBody(p, token);
              } else if (tn === $$4.EMBED) {
                  areaStartTagInBody(p, token);
              } else if (tn === $$4.INPUT) {
                  inputStartTagInBody(p, token);
              } else if (tn === $$4.PARAM || tn === $$4.TRACK) {
                  paramStartTagInBody(p, token);
              } else if (tn === $$4.IMAGE) {
                  imageStartTagInBody(p, token);
              } else if (tn !== $$4.FRAME && tn !== $$4.TBODY && tn !== $$4.TFOOT && tn !== $$4.THEAD) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 6:
              if (tn === $$4.SCRIPT) {
                  startTagInHead(p, token);
              } else if (
                  tn === $$4.CENTER ||
                  tn === $$4.FIGURE ||
                  tn === $$4.FOOTER ||
                  tn === $$4.HEADER ||
                  tn === $$4.HGROUP ||
                  tn === $$4.DIALOG
              ) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.BUTTON) {
                  buttonStartTagInBody(p, token);
              } else if (tn === $$4.STRIKE || tn === $$4.STRONG) {
                  bStartTagInBody(p, token);
              } else if (tn === $$4.APPLET || tn === $$4.OBJECT) {
                  appletStartTagInBody(p, token);
              } else if (tn === $$4.KEYGEN) {
                  areaStartTagInBody(p, token);
              } else if (tn === $$4.SOURCE) {
                  paramStartTagInBody(p, token);
              } else if (tn === $$4.IFRAME) {
                  iframeStartTagInBody(p, token);
              } else if (tn === $$4.SELECT) {
                  selectStartTagInBody(p, token);
              } else if (tn === $$4.OPTION) {
                  optgroupStartTagInBody(p, token);
              } else {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 7:
              if (tn === $$4.BGSOUND) {
                  startTagInHead(p, token);
              } else if (
                  tn === $$4.DETAILS ||
                  tn === $$4.ADDRESS ||
                  tn === $$4.ARTICLE ||
                  tn === $$4.SECTION ||
                  tn === $$4.SUMMARY
              ) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.LISTING) {
                  preStartTagInBody(p, token);
              } else if (tn === $$4.MARQUEE) {
                  appletStartTagInBody(p, token);
              } else if (tn === $$4.NOEMBED) {
                  noembedStartTagInBody(p, token);
              } else if (tn !== $$4.CAPTION) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 8:
              if (tn === $$4.BASEFONT) {
                  startTagInHead(p, token);
              } else if (tn === $$4.FRAMESET) {
                  framesetStartTagInBody(p, token);
              } else if (tn === $$4.FIELDSET) {
                  addressStartTagInBody(p, token);
              } else if (tn === $$4.TEXTAREA) {
                  textareaStartTagInBody(p, token);
              } else if (tn === $$4.TEMPLATE) {
                  startTagInHead(p, token);
              } else if (tn === $$4.NOSCRIPT) {
                  if (p.options.scriptingEnabled) {
                      noembedStartTagInBody(p, token);
                  } else {
                      genericStartTagInBody(p, token);
                  }
              } else if (tn === $$4.OPTGROUP) {
                  optgroupStartTagInBody(p, token);
              } else if (tn !== $$4.COLGROUP) {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 9:
              if (tn === $$4.PLAINTEXT) {
                  plaintextStartTagInBody(p, token);
              } else {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          case 10:
              if (tn === $$4.BLOCKQUOTE || tn === $$4.FIGCAPTION) {
                  addressStartTagInBody(p, token);
              } else {
                  genericStartTagInBody(p, token);
              }
  
              break;
  
          default:
              genericStartTagInBody(p, token);
      }
  }
  
  function bodyEndTagInBody(p) {
      if (p.openElements.hasInScope($$4.BODY)) {
          p.insertionMode = AFTER_BODY_MODE;
      }
  }
  
  function htmlEndTagInBody(p, token) {
      if (p.openElements.hasInScope($$4.BODY)) {
          p.insertionMode = AFTER_BODY_MODE;
          p._processToken(token);
      }
  }
  
  function addressEndTagInBody(p, token) {
      const tn = token.tagName;
  
      if (p.openElements.hasInScope(tn)) {
          p.openElements.generateImpliedEndTags();
          p.openElements.popUntilTagNamePopped(tn);
      }
  }
  
  function formEndTagInBody(p) {
      const inTemplate = p.openElements.tmplCount > 0;
      const formElement = p.formElement;
  
      if (!inTemplate) {
          p.formElement = null;
      }
  
      if ((formElement || inTemplate) && p.openElements.hasInScope($$4.FORM)) {
          p.openElements.generateImpliedEndTags();
  
          if (inTemplate) {
              p.openElements.popUntilTagNamePopped($$4.FORM);
          } else {
              p.openElements.remove(formElement);
          }
      }
  }
  
  function pEndTagInBody(p) {
      if (!p.openElements.hasInButtonScope($$4.P)) {
          p._insertFakeElement($$4.P);
      }
  
      p._closePElement();
  }
  
  function liEndTagInBody(p) {
      if (p.openElements.hasInListItemScope($$4.LI)) {
          p.openElements.generateImpliedEndTagsWithExclusion($$4.LI);
          p.openElements.popUntilTagNamePopped($$4.LI);
      }
  }
  
  function ddEndTagInBody(p, token) {
      const tn = token.tagName;
  
      if (p.openElements.hasInScope(tn)) {
          p.openElements.generateImpliedEndTagsWithExclusion(tn);
          p.openElements.popUntilTagNamePopped(tn);
      }
  }
  
  function numberedHeaderEndTagInBody(p) {
      if (p.openElements.hasNumberedHeaderInScope()) {
          p.openElements.generateImpliedEndTags();
          p.openElements.popUntilNumberedHeaderPopped();
      }
  }
  
  function appletEndTagInBody(p, token) {
      const tn = token.tagName;
  
      if (p.openElements.hasInScope(tn)) {
          p.openElements.generateImpliedEndTags();
          p.openElements.popUntilTagNamePopped(tn);
          p.activeFormattingElements.clearToLastMarker();
      }
  }
  
  function brEndTagInBody(p) {
      p._reconstructActiveFormattingElements();
      p._insertFakeElement($$4.BR);
      p.openElements.pop();
      p.framesetOk = false;
  }
  
  function genericEndTagInBody(p, token) {
      const tn = token.tagName;
  
      for (let i = p.openElements.stackTop; i > 0; i--) {
          const element = p.openElements.items[i];
  
          if (p.treeAdapter.getTagName(element) === tn) {
              p.openElements.generateImpliedEndTagsWithExclusion(tn);
              p.openElements.popUntilElementPopped(element);
              break;
          }
  
          if (p._isSpecialElement(element)) {
              break;
          }
      }
  }
  
  //OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
  //It's faster than using dictionary.
  function endTagInBody(p, token) {
      const tn = token.tagName;
  
      switch (tn.length) {
          case 1:
              if (tn === $$4.A || tn === $$4.B || tn === $$4.I || tn === $$4.S || tn === $$4.U) {
                  callAdoptionAgency(p, token);
              } else if (tn === $$4.P) {
                  pEndTagInBody(p);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 2:
              if (tn === $$4.DL || tn === $$4.UL || tn === $$4.OL) {
                  addressEndTagInBody(p, token);
              } else if (tn === $$4.LI) {
                  liEndTagInBody(p);
              } else if (tn === $$4.DD || tn === $$4.DT) {
                  ddEndTagInBody(p, token);
              } else if (tn === $$4.H1 || tn === $$4.H2 || tn === $$4.H3 || tn === $$4.H4 || tn === $$4.H5 || tn === $$4.H6) {
                  numberedHeaderEndTagInBody(p);
              } else if (tn === $$4.BR) {
                  brEndTagInBody(p);
              } else if (tn === $$4.EM || tn === $$4.TT) {
                  callAdoptionAgency(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 3:
              if (tn === $$4.BIG) {
                  callAdoptionAgency(p, token);
              } else if (tn === $$4.DIR || tn === $$4.DIV || tn === $$4.NAV || tn === $$4.PRE) {
                  addressEndTagInBody(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 4:
              if (tn === $$4.BODY) {
                  bodyEndTagInBody(p);
              } else if (tn === $$4.HTML) {
                  htmlEndTagInBody(p, token);
              } else if (tn === $$4.FORM) {
                  formEndTagInBody(p);
              } else if (tn === $$4.CODE || tn === $$4.FONT || tn === $$4.NOBR) {
                  callAdoptionAgency(p, token);
              } else if (tn === $$4.MAIN || tn === $$4.MENU) {
                  addressEndTagInBody(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 5:
              if (tn === $$4.ASIDE) {
                  addressEndTagInBody(p, token);
              } else if (tn === $$4.SMALL) {
                  callAdoptionAgency(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 6:
              if (
                  tn === $$4.CENTER ||
                  tn === $$4.FIGURE ||
                  tn === $$4.FOOTER ||
                  tn === $$4.HEADER ||
                  tn === $$4.HGROUP ||
                  tn === $$4.DIALOG
              ) {
                  addressEndTagInBody(p, token);
              } else if (tn === $$4.APPLET || tn === $$4.OBJECT) {
                  appletEndTagInBody(p, token);
              } else if (tn === $$4.STRIKE || tn === $$4.STRONG) {
                  callAdoptionAgency(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 7:
              if (
                  tn === $$4.ADDRESS ||
                  tn === $$4.ARTICLE ||
                  tn === $$4.DETAILS ||
                  tn === $$4.SECTION ||
                  tn === $$4.SUMMARY ||
                  tn === $$4.LISTING
              ) {
                  addressEndTagInBody(p, token);
              } else if (tn === $$4.MARQUEE) {
                  appletEndTagInBody(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 8:
              if (tn === $$4.FIELDSET) {
                  addressEndTagInBody(p, token);
              } else if (tn === $$4.TEMPLATE) {
                  endTagInHead(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          case 10:
              if (tn === $$4.BLOCKQUOTE || tn === $$4.FIGCAPTION) {
                  addressEndTagInBody(p, token);
              } else {
                  genericEndTagInBody(p, token);
              }
  
              break;
  
          default:
              genericEndTagInBody(p, token);
      }
  }
  
  function eofInBody(p, token) {
      if (p.tmplInsertionModeStackTop > -1) {
          eofInTemplate(p, token);
      } else {
          p.stopped = true;
      }
  }
  
  // The "text" insertion mode
  //------------------------------------------------------------------
  function endTagInText(p, token) {
      if (token.tagName === $$4.SCRIPT) {
          p.pendingScript = p.openElements.current;
      }
  
      p.openElements.pop();
      p.insertionMode = p.originalInsertionMode;
  }
  
  function eofInText(p, token) {
      p._err(errorCodes.eofInElementThatCanContainOnlyText);
      p.openElements.pop();
      p.insertionMode = p.originalInsertionMode;
      p._processToken(token);
  }
  
  // The "in table" insertion mode
  //------------------------------------------------------------------
  function characterInTable(p, token) {
      const curTn = p.openElements.currentTagName;
  
      if (curTn === $$4.TABLE || curTn === $$4.TBODY || curTn === $$4.TFOOT || curTn === $$4.THEAD || curTn === $$4.TR) {
          p.pendingCharacterTokens = [];
          p.hasNonWhitespacePendingCharacterToken = false;
          p.originalInsertionMode = p.insertionMode;
          p.insertionMode = IN_TABLE_TEXT_MODE;
          p._processToken(token);
      } else {
          tokenInTable(p, token);
      }
  }
  
  function captionStartTagInTable(p, token) {
      p.openElements.clearBackToTableContext();
      p.activeFormattingElements.insertMarker();
      p._insertElement(token, NS$1.HTML);
      p.insertionMode = IN_CAPTION_MODE;
  }
  
  function colgroupStartTagInTable(p, token) {
      p.openElements.clearBackToTableContext();
      p._insertElement(token, NS$1.HTML);
      p.insertionMode = IN_COLUMN_GROUP_MODE;
  }
  
  function colStartTagInTable(p, token) {
      p.openElements.clearBackToTableContext();
      p._insertFakeElement($$4.COLGROUP);
      p.insertionMode = IN_COLUMN_GROUP_MODE;
      p._processToken(token);
  }
  
  function tbodyStartTagInTable(p, token) {
      p.openElements.clearBackToTableContext();
      p._insertElement(token, NS$1.HTML);
      p.insertionMode = IN_TABLE_BODY_MODE;
  }
  
  function tdStartTagInTable(p, token) {
      p.openElements.clearBackToTableContext();
      p._insertFakeElement($$4.TBODY);
      p.insertionMode = IN_TABLE_BODY_MODE;
      p._processToken(token);
  }
  
  function tableStartTagInTable(p, token) {
      if (p.openElements.hasInTableScope($$4.TABLE)) {
          p.openElements.popUntilTagNamePopped($$4.TABLE);
          p._resetInsertionMode();
          p._processToken(token);
      }
  }
  
  function inputStartTagInTable(p, token) {
      const inputType = tokenizer.getTokenAttr(token, ATTRS.TYPE);
  
      if (inputType && inputType.toLowerCase() === HIDDEN_INPUT_TYPE) {
          p._appendElement(token, NS$1.HTML);
      } else {
          tokenInTable(p, token);
      }
  
      token.ackSelfClosing = true;
  }
  
  function formStartTagInTable(p, token) {
      if (!p.formElement && p.openElements.tmplCount === 0) {
          p._insertElement(token, NS$1.HTML);
          p.formElement = p.openElements.current;
          p.openElements.pop();
      }
  }
  
  function startTagInTable(p, token) {
      const tn = token.tagName;
  
      switch (tn.length) {
          case 2:
              if (tn === $$4.TD || tn === $$4.TH || tn === $$4.TR) {
                  tdStartTagInTable(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 3:
              if (tn === $$4.COL) {
                  colStartTagInTable(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 4:
              if (tn === $$4.FORM) {
                  formStartTagInTable(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 5:
              if (tn === $$4.TABLE) {
                  tableStartTagInTable(p, token);
              } else if (tn === $$4.STYLE) {
                  startTagInHead(p, token);
              } else if (tn === $$4.TBODY || tn === $$4.TFOOT || tn === $$4.THEAD) {
                  tbodyStartTagInTable(p, token);
              } else if (tn === $$4.INPUT) {
                  inputStartTagInTable(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 6:
              if (tn === $$4.SCRIPT) {
                  startTagInHead(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 7:
              if (tn === $$4.CAPTION) {
                  captionStartTagInTable(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          case 8:
              if (tn === $$4.COLGROUP) {
                  colgroupStartTagInTable(p, token);
              } else if (tn === $$4.TEMPLATE) {
                  startTagInHead(p, token);
              } else {
                  tokenInTable(p, token);
              }
  
              break;
  
          default:
              tokenInTable(p, token);
      }
  }
  
  function endTagInTable(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TABLE) {
          if (p.openElements.hasInTableScope($$4.TABLE)) {
              p.openElements.popUntilTagNamePopped($$4.TABLE);
              p._resetInsertionMode();
          }
      } else if (tn === $$4.TEMPLATE) {
          endTagInHead(p, token);
      } else if (
          tn !== $$4.BODY &&
          tn !== $$4.CAPTION &&
          tn !== $$4.COL &&
          tn !== $$4.COLGROUP &&
          tn !== $$4.HTML &&
          tn !== $$4.TBODY &&
          tn !== $$4.TD &&
          tn !== $$4.TFOOT &&
          tn !== $$4.TH &&
          tn !== $$4.THEAD &&
          tn !== $$4.TR
      ) {
          tokenInTable(p, token);
      }
  }
  
  function tokenInTable(p, token) {
      const savedFosterParentingState = p.fosterParentingEnabled;
  
      p.fosterParentingEnabled = true;
      p._processTokenInBodyMode(token);
      p.fosterParentingEnabled = savedFosterParentingState;
  }
  
  // The "in table text" insertion mode
  //------------------------------------------------------------------
  function whitespaceCharacterInTableText(p, token) {
      p.pendingCharacterTokens.push(token);
  }
  
  function characterInTableText(p, token) {
      p.pendingCharacterTokens.push(token);
      p.hasNonWhitespacePendingCharacterToken = true;
  }
  
  function tokenInTableText(p, token) {
      let i = 0;
  
      if (p.hasNonWhitespacePendingCharacterToken) {
          for (; i < p.pendingCharacterTokens.length; i++) {
              tokenInTable(p, p.pendingCharacterTokens[i]);
          }
      } else {
          for (; i < p.pendingCharacterTokens.length; i++) {
              p._insertCharacters(p.pendingCharacterTokens[i]);
          }
      }
  
      p.insertionMode = p.originalInsertionMode;
      p._processToken(token);
  }
  
  // The "in caption" insertion mode
  //------------------------------------------------------------------
  function startTagInCaption(p, token) {
      const tn = token.tagName;
  
      if (
          tn === $$4.CAPTION ||
          tn === $$4.COL ||
          tn === $$4.COLGROUP ||
          tn === $$4.TBODY ||
          tn === $$4.TD ||
          tn === $$4.TFOOT ||
          tn === $$4.TH ||
          tn === $$4.THEAD ||
          tn === $$4.TR
      ) {
          if (p.openElements.hasInTableScope($$4.CAPTION)) {
              p.openElements.generateImpliedEndTags();
              p.openElements.popUntilTagNamePopped($$4.CAPTION);
              p.activeFormattingElements.clearToLastMarker();
              p.insertionMode = IN_TABLE_MODE;
              p._processToken(token);
          }
      } else {
          startTagInBody(p, token);
      }
  }
  
  function endTagInCaption(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.CAPTION || tn === $$4.TABLE) {
          if (p.openElements.hasInTableScope($$4.CAPTION)) {
              p.openElements.generateImpliedEndTags();
              p.openElements.popUntilTagNamePopped($$4.CAPTION);
              p.activeFormattingElements.clearToLastMarker();
              p.insertionMode = IN_TABLE_MODE;
  
              if (tn === $$4.TABLE) {
                  p._processToken(token);
              }
          }
      } else if (
          tn !== $$4.BODY &&
          tn !== $$4.COL &&
          tn !== $$4.COLGROUP &&
          tn !== $$4.HTML &&
          tn !== $$4.TBODY &&
          tn !== $$4.TD &&
          tn !== $$4.TFOOT &&
          tn !== $$4.TH &&
          tn !== $$4.THEAD &&
          tn !== $$4.TR
      ) {
          endTagInBody(p, token);
      }
  }
  
  // The "in column group" insertion mode
  //------------------------------------------------------------------
  function startTagInColumnGroup(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.COL) {
          p._appendElement(token, NS$1.HTML);
          token.ackSelfClosing = true;
      } else if (tn === $$4.TEMPLATE) {
          startTagInHead(p, token);
      } else {
          tokenInColumnGroup(p, token);
      }
  }
  
  function endTagInColumnGroup(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.COLGROUP) {
          if (p.openElements.currentTagName === $$4.COLGROUP) {
              p.openElements.pop();
              p.insertionMode = IN_TABLE_MODE;
          }
      } else if (tn === $$4.TEMPLATE) {
          endTagInHead(p, token);
      } else if (tn !== $$4.COL) {
          tokenInColumnGroup(p, token);
      }
  }
  
  function tokenInColumnGroup(p, token) {
      if (p.openElements.currentTagName === $$4.COLGROUP) {
          p.openElements.pop();
          p.insertionMode = IN_TABLE_MODE;
          p._processToken(token);
      }
  }
  
  // The "in table body" insertion mode
  //------------------------------------------------------------------
  function startTagInTableBody(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TR) {
          p.openElements.clearBackToTableBodyContext();
          p._insertElement(token, NS$1.HTML);
          p.insertionMode = IN_ROW_MODE;
      } else if (tn === $$4.TH || tn === $$4.TD) {
          p.openElements.clearBackToTableBodyContext();
          p._insertFakeElement($$4.TR);
          p.insertionMode = IN_ROW_MODE;
          p._processToken(token);
      } else if (
          tn === $$4.CAPTION ||
          tn === $$4.COL ||
          tn === $$4.COLGROUP ||
          tn === $$4.TBODY ||
          tn === $$4.TFOOT ||
          tn === $$4.THEAD
      ) {
          if (p.openElements.hasTableBodyContextInTableScope()) {
              p.openElements.clearBackToTableBodyContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_MODE;
              p._processToken(token);
          }
      } else {
          startTagInTable(p, token);
      }
  }
  
  function endTagInTableBody(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TBODY || tn === $$4.TFOOT || tn === $$4.THEAD) {
          if (p.openElements.hasInTableScope(tn)) {
              p.openElements.clearBackToTableBodyContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_MODE;
          }
      } else if (tn === $$4.TABLE) {
          if (p.openElements.hasTableBodyContextInTableScope()) {
              p.openElements.clearBackToTableBodyContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_MODE;
              p._processToken(token);
          }
      } else if (
          (tn !== $$4.BODY && tn !== $$4.CAPTION && tn !== $$4.COL && tn !== $$4.COLGROUP) ||
          (tn !== $$4.HTML && tn !== $$4.TD && tn !== $$4.TH && tn !== $$4.TR)
      ) {
          endTagInTable(p, token);
      }
  }
  
  // The "in row" insertion mode
  //------------------------------------------------------------------
  function startTagInRow(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TH || tn === $$4.TD) {
          p.openElements.clearBackToTableRowContext();
          p._insertElement(token, NS$1.HTML);
          p.insertionMode = IN_CELL_MODE;
          p.activeFormattingElements.insertMarker();
      } else if (
          tn === $$4.CAPTION ||
          tn === $$4.COL ||
          tn === $$4.COLGROUP ||
          tn === $$4.TBODY ||
          tn === $$4.TFOOT ||
          tn === $$4.THEAD ||
          tn === $$4.TR
      ) {
          if (p.openElements.hasInTableScope($$4.TR)) {
              p.openElements.clearBackToTableRowContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_BODY_MODE;
              p._processToken(token);
          }
      } else {
          startTagInTable(p, token);
      }
  }
  
  function endTagInRow(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TR) {
          if (p.openElements.hasInTableScope($$4.TR)) {
              p.openElements.clearBackToTableRowContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_BODY_MODE;
          }
      } else if (tn === $$4.TABLE) {
          if (p.openElements.hasInTableScope($$4.TR)) {
              p.openElements.clearBackToTableRowContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_BODY_MODE;
              p._processToken(token);
          }
      } else if (tn === $$4.TBODY || tn === $$4.TFOOT || tn === $$4.THEAD) {
          if (p.openElements.hasInTableScope(tn) || p.openElements.hasInTableScope($$4.TR)) {
              p.openElements.clearBackToTableRowContext();
              p.openElements.pop();
              p.insertionMode = IN_TABLE_BODY_MODE;
              p._processToken(token);
          }
      } else if (
          (tn !== $$4.BODY && tn !== $$4.CAPTION && tn !== $$4.COL && tn !== $$4.COLGROUP) ||
          (tn !== $$4.HTML && tn !== $$4.TD && tn !== $$4.TH)
      ) {
          endTagInTable(p, token);
      }
  }
  
  // The "in cell" insertion mode
  //------------------------------------------------------------------
  function startTagInCell(p, token) {
      const tn = token.tagName;
  
      if (
          tn === $$4.CAPTION ||
          tn === $$4.COL ||
          tn === $$4.COLGROUP ||
          tn === $$4.TBODY ||
          tn === $$4.TD ||
          tn === $$4.TFOOT ||
          tn === $$4.TH ||
          tn === $$4.THEAD ||
          tn === $$4.TR
      ) {
          if (p.openElements.hasInTableScope($$4.TD) || p.openElements.hasInTableScope($$4.TH)) {
              p._closeTableCell();
              p._processToken(token);
          }
      } else {
          startTagInBody(p, token);
      }
  }
  
  function endTagInCell(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.TD || tn === $$4.TH) {
          if (p.openElements.hasInTableScope(tn)) {
              p.openElements.generateImpliedEndTags();
              p.openElements.popUntilTagNamePopped(tn);
              p.activeFormattingElements.clearToLastMarker();
              p.insertionMode = IN_ROW_MODE;
          }
      } else if (tn === $$4.TABLE || tn === $$4.TBODY || tn === $$4.TFOOT || tn === $$4.THEAD || tn === $$4.TR) {
          if (p.openElements.hasInTableScope(tn)) {
              p._closeTableCell();
              p._processToken(token);
          }
      } else if (tn !== $$4.BODY && tn !== $$4.CAPTION && tn !== $$4.COL && tn !== $$4.COLGROUP && tn !== $$4.HTML) {
          endTagInBody(p, token);
      }
  }
  
  // The "in select" insertion mode
  //------------------------------------------------------------------
  function startTagInSelect(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.OPTION) {
          if (p.openElements.currentTagName === $$4.OPTION) {
              p.openElements.pop();
          }
  
          p._insertElement(token, NS$1.HTML);
      } else if (tn === $$4.OPTGROUP) {
          if (p.openElements.currentTagName === $$4.OPTION) {
              p.openElements.pop();
          }
  
          if (p.openElements.currentTagName === $$4.OPTGROUP) {
              p.openElements.pop();
          }
  
          p._insertElement(token, NS$1.HTML);
      } else if (tn === $$4.INPUT || tn === $$4.KEYGEN || tn === $$4.TEXTAREA || tn === $$4.SELECT) {
          if (p.openElements.hasInSelectScope($$4.SELECT)) {
              p.openElements.popUntilTagNamePopped($$4.SELECT);
              p._resetInsertionMode();
  
              if (tn !== $$4.SELECT) {
                  p._processToken(token);
              }
          }
      } else if (tn === $$4.SCRIPT || tn === $$4.TEMPLATE) {
          startTagInHead(p, token);
      }
  }
  
  function endTagInSelect(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.OPTGROUP) {
          const prevOpenElement = p.openElements.items[p.openElements.stackTop - 1];
          const prevOpenElementTn = prevOpenElement && p.treeAdapter.getTagName(prevOpenElement);
  
          if (p.openElements.currentTagName === $$4.OPTION && prevOpenElementTn === $$4.OPTGROUP) {
              p.openElements.pop();
          }
  
          if (p.openElements.currentTagName === $$4.OPTGROUP) {
              p.openElements.pop();
          }
      } else if (tn === $$4.OPTION) {
          if (p.openElements.currentTagName === $$4.OPTION) {
              p.openElements.pop();
          }
      } else if (tn === $$4.SELECT && p.openElements.hasInSelectScope($$4.SELECT)) {
          p.openElements.popUntilTagNamePopped($$4.SELECT);
          p._resetInsertionMode();
      } else if (tn === $$4.TEMPLATE) {
          endTagInHead(p, token);
      }
  }
  
  //12.2.5.4.17 The "in select in table" insertion mode
  //------------------------------------------------------------------
  function startTagInSelectInTable(p, token) {
      const tn = token.tagName;
  
      if (
          tn === $$4.CAPTION ||
          tn === $$4.TABLE ||
          tn === $$4.TBODY ||
          tn === $$4.TFOOT ||
          tn === $$4.THEAD ||
          tn === $$4.TR ||
          tn === $$4.TD ||
          tn === $$4.TH
      ) {
          p.openElements.popUntilTagNamePopped($$4.SELECT);
          p._resetInsertionMode();
          p._processToken(token);
      } else {
          startTagInSelect(p, token);
      }
  }
  
  function endTagInSelectInTable(p, token) {
      const tn = token.tagName;
  
      if (
          tn === $$4.CAPTION ||
          tn === $$4.TABLE ||
          tn === $$4.TBODY ||
          tn === $$4.TFOOT ||
          tn === $$4.THEAD ||
          tn === $$4.TR ||
          tn === $$4.TD ||
          tn === $$4.TH
      ) {
          if (p.openElements.hasInTableScope(tn)) {
              p.openElements.popUntilTagNamePopped($$4.SELECT);
              p._resetInsertionMode();
              p._processToken(token);
          }
      } else {
          endTagInSelect(p, token);
      }
  }
  
  // The "in template" insertion mode
  //------------------------------------------------------------------
  function startTagInTemplate(p, token) {
      const tn = token.tagName;
  
      if (
          tn === $$4.BASE ||
          tn === $$4.BASEFONT ||
          tn === $$4.BGSOUND ||
          tn === $$4.LINK ||
          tn === $$4.META ||
          tn === $$4.NOFRAMES ||
          tn === $$4.SCRIPT ||
          tn === $$4.STYLE ||
          tn === $$4.TEMPLATE ||
          tn === $$4.TITLE
      ) {
          startTagInHead(p, token);
      } else {
          const newInsertionMode = TEMPLATE_INSERTION_MODE_SWITCH_MAP[tn] || IN_BODY_MODE;
  
          p._popTmplInsertionMode();
          p._pushTmplInsertionMode(newInsertionMode);
          p.insertionMode = newInsertionMode;
          p._processToken(token);
      }
  }
  
  function endTagInTemplate(p, token) {
      if (token.tagName === $$4.TEMPLATE) {
          endTagInHead(p, token);
      }
  }
  
  function eofInTemplate(p, token) {
      if (p.openElements.tmplCount > 0) {
          p.openElements.popUntilTagNamePopped($$4.TEMPLATE);
          p.activeFormattingElements.clearToLastMarker();
          p._popTmplInsertionMode();
          p._resetInsertionMode();
          p._processToken(token);
      } else {
          p.stopped = true;
      }
  }
  
  // The "after body" insertion mode
  //------------------------------------------------------------------
  function startTagAfterBody(p, token) {
      if (token.tagName === $$4.HTML) {
          startTagInBody(p, token);
      } else {
          tokenAfterBody(p, token);
      }
  }
  
  function endTagAfterBody(p, token) {
      if (token.tagName === $$4.HTML) {
          if (!p.fragmentContext) {
              p.insertionMode = AFTER_AFTER_BODY_MODE;
          }
      } else {
          tokenAfterBody(p, token);
      }
  }
  
  function tokenAfterBody(p, token) {
      p.insertionMode = IN_BODY_MODE;
      p._processToken(token);
  }
  
  // The "in frameset" insertion mode
  //------------------------------------------------------------------
  function startTagInFrameset(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.FRAMESET) {
          p._insertElement(token, NS$1.HTML);
      } else if (tn === $$4.FRAME) {
          p._appendElement(token, NS$1.HTML);
          token.ackSelfClosing = true;
      } else if (tn === $$4.NOFRAMES) {
          startTagInHead(p, token);
      }
  }
  
  function endTagInFrameset(p, token) {
      if (token.tagName === $$4.FRAMESET && !p.openElements.isRootHtmlElementCurrent()) {
          p.openElements.pop();
  
          if (!p.fragmentContext && p.openElements.currentTagName !== $$4.FRAMESET) {
              p.insertionMode = AFTER_FRAMESET_MODE;
          }
      }
  }
  
  // The "after frameset" insertion mode
  //------------------------------------------------------------------
  function startTagAfterFrameset(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.NOFRAMES) {
          startTagInHead(p, token);
      }
  }
  
  function endTagAfterFrameset(p, token) {
      if (token.tagName === $$4.HTML) {
          p.insertionMode = AFTER_AFTER_FRAMESET_MODE;
      }
  }
  
  // The "after after body" insertion mode
  //------------------------------------------------------------------
  function startTagAfterAfterBody(p, token) {
      if (token.tagName === $$4.HTML) {
          startTagInBody(p, token);
      } else {
          tokenAfterAfterBody(p, token);
      }
  }
  
  function tokenAfterAfterBody(p, token) {
      p.insertionMode = IN_BODY_MODE;
      p._processToken(token);
  }
  
  // The "after after frameset" insertion mode
  //------------------------------------------------------------------
  function startTagAfterAfterFrameset(p, token) {
      const tn = token.tagName;
  
      if (tn === $$4.HTML) {
          startTagInBody(p, token);
      } else if (tn === $$4.NOFRAMES) {
          startTagInHead(p, token);
      }
  }
  
  // The rules for parsing tokens in foreign content
  //------------------------------------------------------------------
  function nullCharacterInForeignContent(p, token) {
      token.chars = unicode.REPLACEMENT_CHARACTER;
      p._insertCharacters(token);
  }
  
  function characterInForeignContent(p, token) {
      p._insertCharacters(token);
      p.framesetOk = false;
  }
  
  function startTagInForeignContent(p, token) {
      if (foreignContent.causesExit(token) && !p.fragmentContext) {
          while (
              p.treeAdapter.getNamespaceURI(p.openElements.current) !== NS$1.HTML &&
              !p._isIntegrationPoint(p.openElements.current)
          ) {
              p.openElements.pop();
          }
  
          p._processToken(token);
      } else {
          const current = p._getAdjustedCurrentElement();
          const currentNs = p.treeAdapter.getNamespaceURI(current);
  
          if (currentNs === NS$1.MATHML) {
              foreignContent.adjustTokenMathMLAttrs(token);
          } else if (currentNs === NS$1.SVG) {
              foreignContent.adjustTokenSVGTagName(token);
              foreignContent.adjustTokenSVGAttrs(token);
          }
  
          foreignContent.adjustTokenXMLAttrs(token);
  
          if (token.selfClosing) {
              p._appendElement(token, currentNs);
          } else {
              p._insertElement(token, currentNs);
          }
  
          token.ackSelfClosing = true;
      }
  }
  
  function endTagInForeignContent(p, token) {
      for (let i = p.openElements.stackTop; i > 0; i--) {
          const element = p.openElements.items[i];
  
          if (p.treeAdapter.getNamespaceURI(element) === NS$1.HTML) {
              p._processToken(token);
              break;
          }
  
          if (p.treeAdapter.getTagName(element).toLowerCase() === token.tagName) {
              p.openElements.popUntilElementPopped(element);
              break;
          }
      }
  }
  
  //Aliases
  const $$5 = html.TAG_NAMES;
  const NS$2 = html.NAMESPACES;
  
  // Shorthands
  var parse = function parse(html, options) {
      const parser$1 = new parser(options);
  
      return parser$1.parse(html);
  };
  
  var parseFragment = function parseFragment(fragmentContext, html, options) {
      if (typeof fragmentContext === 'string') {
          options = html;
          html = fragmentContext;
          fragmentContext = null;
      }
  
      const parser$1 = new parser(options);
  
      return parser$1.parseFragment(html, fragmentContext);
  };
  
  const docParser = new WeakMap();
  function parseDocumentUtil(ownerDocument, html) {
      const doc = parse(html.trim(), getParser(ownerDocument));
      doc.documentElement = doc.firstElementChild;
      doc.head = doc.documentElement.firstElementChild;
      doc.body = doc.head.nextElementSibling;
      return doc;
  }
  function parseFragmentUtil(ownerDocument, html) {
      if (typeof html === 'string') {
          html = html.trim();
      }
      else {
          html = '';
      }
      const frag = parseFragment(html, getParser(ownerDocument));
      return frag;
  }
  function getParser(ownerDocument) {
      let parseOptions = docParser.get(ownerDocument);
      if (parseOptions != null) {
          return parseOptions;
      }
      const treeAdapter = {
          createDocument() {
              const doc = ownerDocument.createElement("#document");
              doc['x-mode'] = 'no-quirks';
              return doc;
          },
          createDocumentFragment() {
              return ownerDocument.createDocumentFragment();
          },
          createElement(tagName, namespaceURI, attrs) {
              const elm = ownerDocument.createElementNS(namespaceURI, tagName);
              for (let i = 0; i < attrs.length; i++) {
                  const attr = attrs[i];
                  if (attr.namespace == null || attr.namespace === 'http://www.w3.org/1999/xhtml') {
                      elm.setAttribute(attr.name, attr.value);
                  }
                  else {
                      elm.setAttributeNS(attr.namespace, attr.name, attr.value);
                  }
              }
              return elm;
          },
          createCommentNode(data) {
              return ownerDocument.createComment(data);
          },
          appendChild(parentNode, newNode) {
              parentNode.appendChild(newNode);
          },
          insertBefore(parentNode, newNode, referenceNode) {
              parentNode.insertBefore(newNode, referenceNode);
          },
          setTemplateContent(templateElement, contentElement) {
              templateElement.content = contentElement;
          },
          getTemplateContent(templateElement) {
              return templateElement.content;
          },
          setDocumentType(doc, name, publicId, systemId) {
              let doctypeNode = doc.childNodes.find(n => n.nodeType === 10);
              if (doctypeNode == null) {
                  doctypeNode = ownerDocument.createDocumentTypeNode();
                  doc.insertBefore(doctypeNode, doc.firstChild);
              }
              doctypeNode.nodeValue = '!DOCTYPE';
              doctypeNode['x-name'] = name;
              doctypeNode['x-publicId'] = publicId;
              doctypeNode['x-systemId'] = systemId;
          },
          setDocumentMode(doc, mode) {
              doc['x-mode'] = mode;
          },
          getDocumentMode(doc) {
              return doc['x-mode'];
          },
          detachNode(node) {
              node.remove();
          },
          insertText(parentNode, text) {
              const lastChild = parentNode.lastChild;
              if (lastChild != null && lastChild.nodeType === 3) {
                  lastChild.nodeValue += text;
              }
              else {
                  parentNode.appendChild(ownerDocument.createTextNode(text));
              }
          },
          insertTextBefore(parentNode, text, referenceNode) {
              const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
              if (prevNode != null && prevNode.nodeType === 3) {
                  prevNode.nodeValue += text;
              }
              else {
                  parentNode.insertBefore(ownerDocument.createTextNode(text), referenceNode);
              }
          },
          adoptAttributes(recipient, attrs) {
              for (let i = 0; i < attrs.length; i++) {
                  const attr = attrs[i];
                  if (recipient.hasAttributeNS(attr.namespace, attr.name) === false) {
                      recipient.setAttributeNS(attr.namespace, attr.name, attr.value);
                  }
              }
          },
          getFirstChild(node) {
              return node.childNodes[0];
          },
          getChildNodes(node) {
              return node.childNodes;
          },
          getParentNode(node) {
              return node.parentNode;
          },
          getAttrList(element) {
              const attrs = element.attributes.items.map(attr => {
                  return {
                      name: attr.name,
                      value: attr.value,
                      namespace: attr.namespaceURI,
                      prefix: null
                  };
              });
              return attrs;
          },
          getTagName(element) {
              if (element.namespaceURI === 'http://www.w3.org/1999/xhtml') {
                  return element.nodeName.toLowerCase();
              }
              else {
                  return element.nodeName;
              }
          },
          getNamespaceURI(element) {
              return element.namespaceURI;
          },
          getTextNodeContent(textNode) {
              return textNode.nodeValue;
          },
          getCommentNodeContent(commentNode) {
              return commentNode.nodeValue;
          },
          getDocumentTypeNodeName(doctypeNode) {
              return doctypeNode['x-name'];
          },
          getDocumentTypeNodePublicId(doctypeNode) {
              return doctypeNode['x-publicId'];
          },
          getDocumentTypeNodeSystemId(doctypeNode) {
              return doctypeNode['x-systemId'];
          },
          isTextNode(node) {
              return node.nodeType === 3;
          },
          isCommentNode(node) {
              return node.nodeType === 8;
          },
          isDocumentTypeNode(node) {
              return node.nodeType === 10;
          },
          isElementNode(node) {
              return node.nodeType === 1;
          }
      };
      parseOptions = {
          treeAdapter: treeAdapter
      };
      docParser.set(ownerDocument, parseOptions);
      return parseOptions;
  }
  
  class MockNode {
      constructor(ownerDocument, nodeType, nodeName, nodeValue) {
          this.ownerDocument = ownerDocument;
          this.nodeType = nodeType;
          this.nodeName = nodeName;
          this.nodeValue = nodeValue;
          this.parentNode = null;
          this.childNodes = [];
      }
      appendChild(newNode) {
          if (newNode.nodeType === 11) {
              const nodes = newNode.childNodes.slice();
              for (const child of nodes) {
                  this.appendChild(child);
              }
          }
          else {
              newNode.remove();
              newNode.parentNode = this;
              this.childNodes.push(newNode);
              connectNode(this.ownerDocument, newNode);
          }
          return newNode;
      }
      append(...items) {
          items.forEach(item => {
              const isNode = typeof item === 'object' && item !== null && 'nodeType' in item;
              this.appendChild(isNode ? item : this.ownerDocument.createTextNode(String(item)));
          });
      }
      prepend(...items) {
          const firstChild = this.firstChild;
          items.forEach(item => {
              const isNode = typeof item === 'object' && item !== null && 'nodeType' in item;
              this.insertBefore(isNode ? item : this.ownerDocument.createTextNode(String(item)), firstChild);
          });
      }
      cloneNode(deep) {
          throw new Error(`invalid node type to clone: ${this.nodeType}, deep: ${deep}`);
      }
      get firstChild() {
          return this.childNodes[0] || null;
      }
      insertBefore(newNode, referenceNode) {
          if (newNode.nodeType === 11) {
              for (let i = 0, ii = newNode.childNodes.length; i < ii; i++) {
                  insertBefore(this, newNode.childNodes[i], referenceNode);
              }
          }
          else {
              insertBefore(this, newNode, referenceNode);
          }
          return newNode;
      }
      get isConnected() {
          let node = this;
          while (node != null) {
              if (node.nodeType === 9) {
                  return true;
              }
              node = node.parentNode;
              if (node != null && node.nodeType === 11) {
                  node = node.host;
              }
          }
          return false;
      }
      isSameNode(node) {
          return this === node;
      }
      get lastChild() {
          return this.childNodes[this.childNodes.length - 1] || null;
      }
      get nextSibling() {
          if (this.parentNode != null) {
              const index = this.parentNode.childNodes.indexOf(this) + 1;
              return this.parentNode.childNodes[index] || null;
          }
          return null;
      }
      get parentElement() {
          return this.parentNode || null;
      }
      set parentElement(value) {
          this.parentNode = value;
      }
      get previousSibling() {
          if (this.parentNode != null) {
              const index = this.parentNode.childNodes.indexOf(this) - 1;
              return this.parentNode.childNodes[index] || null;
          }
          return null;
      }
      contains(otherNode) {
          return this.childNodes.includes(otherNode);
      }
      removeChild(childNode) {
          const index = this.childNodes.indexOf(childNode);
          if (index > -1) {
              this.childNodes.splice(index, 1);
              if (this.nodeType === 1) {
                  const wasConnected = this.isConnected;
                  childNode.parentNode = null;
                  if (wasConnected === true) {
                      disconnectNode(childNode);
                  }
              }
              else {
                  childNode.parentNode = null;
              }
          }
          else {
              throw new Error(`node not found within childNodes during removeChild`);
          }
          return childNode;
      }
      remove() {
          if (this.parentNode != null) {
              this.parentNode.removeChild(this);
          }
      }
      replaceChild(newChild, oldChild) {
          if (oldChild.parentNode === this) {
              this.insertBefore(newChild, oldChild);
              oldChild.remove();
              return newChild;
          }
          return null;
      }
      get textContent() {
          return this.nodeValue;
      }
      set textContent(value) {
          this.nodeValue = String(value);
      }
  }
  MockNode.ELEMENT_NODE = 1;
  MockNode.TEXT_NODE = 3;
  MockNode.PROCESSING_INSTRUCTION_NODE = 7;
  MockNode.COMMENT_NODE = 8;
  MockNode.DOCUMENT_NODE = 9;
  MockNode.DOCUMENT_TYPE_NODE = 10;
  MockNode.DOCUMENT_FRAGMENT_NODE = 11;
  class MockNodeList {
      constructor(ownerDocument, childNodes, length) {
          this.ownerDocument = ownerDocument;
          this.childNodes = childNodes;
          this.length = length;
      }
  }
  const attrsMap = new WeakMap();
  const shadowRootMap = new WeakMap();
  const stylesMap = new WeakMap();
  class MockElement extends MockNode {
      constructor(ownerDocument, nodeName) {
          super(ownerDocument, 1, typeof nodeName === 'string' ? nodeName : null, null);
          this.namespaceURI = null;
      }
      addEventListener(type, handler) {
          addEventListener(this, type, handler);
      }
      attachShadow(_opts) {
          const shadowRoot = this.ownerDocument.createDocumentFragment();
          this.shadowRoot = shadowRoot;
          return shadowRoot;
      }
      get shadowRoot() {
          return shadowRootMap.get(this) || null;
      }
      set shadowRoot(shadowRoot) {
          if (shadowRoot != null) {
              shadowRoot.host = this;
              shadowRootMap.set(this, shadowRoot);
          }
          else {
              shadowRootMap.delete(this);
          }
      }
      get attributes() {
          let attrs = attrsMap.get(this);
          if (attrs == null) {
              attrs = new MockAttributeMap();
              attrsMap.set(this, attrs);
          }
          return attrs;
      }
      set attributes(attrs) {
          attrsMap.set(this, attrs);
      }
      get children() {
          return this.childNodes.filter(n => n.nodeType === 1);
      }
      get childElementCount() {
          return this.childNodes.filter(n => n.nodeType === 1).length;
      }
      get className() { return this.getAttributeNS(null, 'class') || ''; }
      set className(value) { this.setAttributeNS(null, 'class', value); }
      get classList() {
          return new MockClassList(this);
      }
      click() {
          dispatchEvent(this, new MockEvent('click', { bubbles: true, cancelable: true, composed: true }));
      }
      cloneNode(_deep) {
          return null;
      }
      closest(selector) {
          return closest(selector, this);
      }
      get dataset() {
          return dataset(this);
      }
      get dir() { return this.getAttributeNS(null, 'dir') || ''; }
      set dir(value) { this.setAttributeNS(null, 'dir', value); }
      dispatchEvent(ev) {
          return dispatchEvent(this, ev);
      }
      get firstElementChild() {
          return this.children[0] || null;
      }
      getAttribute(attrName) {
          if (attrName === 'style') {
              const style = stylesMap.get(this);
              if (style != null && style.length > 0) {
                  return this.style.cssText;
              }
              return null;
          }
          const attr = this.attributes.getNamedItem(attrName);
          if (attr != null) {
              return attr.value;
          }
          return null;
      }
      getAttributeNS(namespaceURI, attrName) {
          const attr = this.attributes.getNamedItemNS(namespaceURI, attrName);
          if (attr != null) {
              return attr.value;
          }
          return null;
      }
      getBoundingClientRect() {
          return { bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0, x: 0, y: 0 };
      }
      getRootNode(opts) {
          const isComposed = (opts != null && opts.composed === true);
          let node = this;
          while (node.parentNode != null) {
              node = node.parentNode;
              if (isComposed === true && node.parentNode == null && node.host != null) {
                  node = node.host;
              }
          }
          return node;
      }
      hasChildNodes() {
          return (this.childNodes.length > 0);
      }
      get id() { return this.getAttributeNS(null, 'id') || ''; }
      set id(value) { this.setAttributeNS(null, 'id', value); }
      get innerHTML() {
          if (this.childNodes.length === 0) {
              return '';
          }
          return serializeNodeToHtml(this, {
              newLines: false,
              indentSpaces: 0
          });
      }
      set innerHTML(html) {
          if (NON_ESCAPABLE_CONTENT.has(this.nodeName) === true) {
              setTextContent(this, html);
          }
          else {
              for (let i = this.childNodes.length - 1; i >= 0; i--) {
                  this.removeChild(this.childNodes[i]);
              }
              if (typeof html === 'string') {
                  const frag = parseFragmentUtil(this.ownerDocument, html);
                  while (frag.childNodes.length > 0) {
                      this.appendChild(frag.childNodes[0]);
                  }
              }
          }
      }
      get innerText() {
          const text = [];
          getTextContent(this.childNodes, text);
          return text.join('');
      }
      set innerText(value) {
          setTextContent(this, value);
      }
      hasAttribute(attrName) {
          if (attrName === 'style') {
              const style = stylesMap.get(this);
              return (style != null && style.length > 0);
          }
          return this.getAttribute(attrName) !== null;
      }
      hasAttributeNS(namespaceURI, name) {
          return this.getAttributeNS(namespaceURI, name) !== null;
      }
      get hidden() { return this.hasAttributeNS(null, 'hidden'); }
      set hidden(isHidden) {
          if (isHidden === true) {
              this.setAttributeNS(null, 'hidden', '');
          }
          else {
              this.removeAttributeNS(null, 'hidden');
          }
      }
      get lang() { return this.getAttributeNS(null, 'lang') || ''; }
      set lang(value) { this.setAttributeNS(null, 'lang', value); }
      get lastElementChild() {
          const children = this.children;
          return children[children.length - 1] || null;
      }
      matches(selector) {
          return matches(selector, this);
      }
      get nextElementSibling() {
          const parentElement = this.parentElement;
          if (parentElement != null && (parentElement.nodeType === 1 || parentElement.nodeType === 11 || parentElement.nodeType === 9)) {
              const children = parentElement.children;
              const index = children.indexOf(this) + 1;
              return parentElement.children[index] || null;
          }
          return null;
      }
      get outerHTML() {
          return serializeNodeToHtml(this, {
              newLines: false,
              outerHtml: true,
              indentSpaces: 0
          });
      }
      get previousElementSibling() {
          const parentElement = this.parentElement;
          if (parentElement != null && (parentElement.nodeType === 1 || parentElement.nodeType === 11 || parentElement.nodeType === 9)) {
              const children = parentElement.children;
              const index = children.indexOf(this) - 1;
              return parentElement.children[index] || null;
          }
          return null;
      }
      querySelector(selector) {
          return selectOne(selector, this);
      }
      querySelectorAll(selector) {
          return selectAll(selector, this);
      }
      removeAttribute(attrName) {
          if (attrName === 'style') {
              stylesMap.delete(this);
          }
          else {
              const attr = this.attributes.getNamedItem(attrName);
              if (attr != null) {
                  this.attributes.removeNamedItemNS(attr);
                  if (checkAttributeChanged(this) === true) {
                      attributeChanged(this, attrName, attr.value, null);
                  }
              }
          }
      }
      removeAttributeNS(namespaceURI, attrName) {
          const attr = this.attributes.getNamedItemNS(namespaceURI, attrName);
          if (attr != null) {
              this.attributes.removeNamedItemNS(attr);
              if (checkAttributeChanged(this) === true) {
                  attributeChanged(this, attrName, attr.value, null);
              }
          }
      }
      removeEventListener(type, handler) {
          removeEventListener(this, type, handler);
      }
      setAttribute(attrName, value) {
          if (attrName === 'style') {
              this.style = value;
          }
          else {
              const attributes = this.attributes;
              let attr = attributes.getNamedItem(attrName);
              const checkAttrChanged = checkAttributeChanged(this);
              if (attr != null) {
                  if (checkAttrChanged === true) {
                      const oldValue = attr.value;
                      attr.value = value;
                      if (oldValue !== attr.value) {
                          attributeChanged(this, attr.name, oldValue, attr.value);
                      }
                  }
                  else {
                      attr.value = value;
                  }
              }
              else {
                  if (attributes.caseInsensitive) {
                      attrName = attrName.toLowerCase();
                  }
                  attr = new MockAttr(attrName, value);
                  attributes.items.push(attr);
                  if (checkAttrChanged === true) {
                      attributeChanged(this, attrName, null, attr.value);
                  }
              }
          }
      }
      setAttributeNS(namespaceURI, attrName, value) {
          const attributes = this.attributes;
          let attr = attributes.getNamedItemNS(namespaceURI, attrName);
          const checkAttrChanged = checkAttributeChanged(this);
          if (attr != null) {
              if (checkAttrChanged === true) {
                  const oldValue = attr.value;
                  attr.value = value;
                  if (oldValue !== attr.value) {
                      attributeChanged(this, attr.name, oldValue, attr.value);
                  }
              }
              else {
                  attr.value = value;
              }
          }
          else {
              attr = new MockAttr(attrName, value, namespaceURI);
              attributes.items.push(attr);
              if (checkAttrChanged === true) {
                  attributeChanged(this, attrName, null, attr.value);
              }
          }
      }
      get style() {
          let style = stylesMap.get(this);
          if (style == null) {
              style = createCSSStyleDeclaration();
              stylesMap.set(this, style);
          }
          return style;
      }
      set style(val) {
          if (typeof val === 'string') {
              let style = stylesMap.get(this);
              if (style == null) {
                  style = createCSSStyleDeclaration();
                  stylesMap.set(this, style);
              }
              style.cssText = val;
          }
          else {
              stylesMap.set(this, val);
          }
      }
      get tabIndex() { return parseInt(this.getAttributeNS(null, 'tabindex') || '-1', 10); }
      set tabIndex(value) { this.setAttributeNS(null, 'tabindex', value); }
      get tagName() { return this.nodeName; }
      set tagName(value) { this.nodeName = value; }
      get textContent() {
          const text = [];
          getTextContent(this.childNodes, text);
          return text.join('');
      }
      set textContent(value) {
          setTextContent(this, value);
      }
      get title() { return this.getAttributeNS(null, 'title') || ''; }
      set title(value) { this.setAttributeNS(null, 'title', value); }
      onanimationstart() { }
      onanimationend() { }
      onanimationiteration() { }
      onabort() { }
      onauxclick() { }
      onbeforecopy() { }
      onbeforecut() { }
      onbeforepaste() { }
      onblur() { }
      oncancel() { }
      oncanplay() { }
      oncanplaythrough() { }
      onchange() { }
      onclick() { }
      onclose() { }
      oncontextmenu() { }
      oncopy() { }
      oncuechange() { }
      oncut() { }
      ondblclick() { }
      ondrag() { }
      ondragend() { }
      ondragenter() { }
      ondragleave() { }
      ondragover() { }
      ondragstart() { }
      ondrop() { }
      ondurationchange() { }
      onemptied() { }
      onended() { }
      onerror() { }
      onfocus() { }
      onformdata() { }
      onfullscreenchange() { }
      onfullscreenerror() { }
      ongotpointercapture() { }
      oninput() { }
      oninvalid() { }
      onkeydown() { }
      onkeypress() { }
      onkeyup() { }
      onload() { }
      onloadeddata() { }
      onloadedmetadata() { }
      onloadstart() { }
      onlostpointercapture() { }
      onmousedown() { }
      onmouseenter() { }
      onmouseleave() { }
      onmousemove() { }
      onmouseout() { }
      onmouseover() { }
      onmouseup() { }
      onmousewheel() { }
      onpaste() { }
      onpause() { }
      onplay() { }
      onplaying() { }
      onpointercancel() { }
      onpointerdown() { }
      onpointerenter() { }
      onpointerleave() { }
      onpointermove() { }
      onpointerout() { }
      onpointerover() { }
      onpointerup() { }
      onprogress() { }
      onratechange() { }
      onreset() { }
      onresize() { }
      onscroll() { }
      onsearch() { }
      onseeked() { }
      onseeking() { }
      onselect() { }
      onselectstart() { }
      onstalled() { }
      onsubmit() { }
      onsuspend() { }
      ontimeupdate() { }
      ontoggle() { }
      onvolumechange() { }
      onwaiting() { }
      onwebkitfullscreenchange() { }
      onwebkitfullscreenerror() { }
      onwheel() { }
      toString(opts) {
          return serializeNodeToHtml(this, opts);
      }
  }
  function resetElement(elm) {
      resetEventListeners(elm);
      attrsMap.delete(elm);
      shadowRootMap.delete(elm);
      stylesMap.delete(elm);
  }
  function insertBefore(parentNode, newNode, referenceNode) {
      if (newNode !== referenceNode) {
          newNode.remove();
          newNode.parentNode = parentNode;
          newNode.ownerDocument = parentNode.ownerDocument;
          if (referenceNode != null) {
              const index = parentNode.childNodes.indexOf(referenceNode);
              if (index > -1) {
                  parentNode.childNodes.splice(index, 0, newNode);
              }
              else {
                  throw new Error(`referenceNode not found in parentNode.childNodes`);
              }
          }
          else {
              parentNode.childNodes.push(newNode);
          }
          connectNode(parentNode.ownerDocument, newNode);
      }
      return newNode;
  }
  class MockHTMLElement extends MockElement {
      constructor(ownerDocument, nodeName) {
          super(ownerDocument, typeof nodeName === 'string' ? nodeName.toUpperCase() : null);
          this.namespaceURI = 'http://www.w3.org/1999/xhtml';
      }
      get tagName() { return this.nodeName; }
      set tagName(value) { this.nodeName = value; }
      get attributes() {
          let attrs = attrsMap.get(this);
          if (attrs == null) {
              attrs = new MockAttributeMap(true);
              attrsMap.set(this, attrs);
          }
          return attrs;
      }
      set attributes(attrs) {
          attrsMap.set(this, attrs);
      }
  }
  class MockTextNode extends MockNode {
      constructor(ownerDocument, text) {
          super(ownerDocument, 3, "#text", text);
      }
      cloneNode(_deep) {
          return new MockTextNode(null, this.nodeValue);
      }
      get textContent() {
          return this.nodeValue;
      }
      set textContent(text) {
          this.nodeValue = text;
      }
      get data() {
          return this.nodeValue;
      }
      set data(text) {
          this.nodeValue = text;
      }
      get wholeText() {
          if (this.parentNode != null) {
              const text = [];
              for (let i = 0, ii = this.parentNode.childNodes.length; i < ii; i++) {
                  const childNode = this.parentNode.childNodes[i];
                  if (childNode.nodeType === 3) {
                      text.push(childNode.nodeValue);
                  }
              }
              return text.join('');
          }
          return this.nodeValue;
      }
  }
  function getTextContent(childNodes, text) {
      for (let i = 0, ii = childNodes.length; i < ii; i++) {
          const childNode = childNodes[i];
          if (childNode.nodeType === 3) {
              text.push(childNode.nodeValue);
          }
          else if (childNode.nodeType === 1) {
              getTextContent(childNode.childNodes, text);
          }
      }
  }
  function setTextContent(elm, text) {
      for (let i = elm.childNodes.length - 1; i >= 0; i--) {
          elm.removeChild(elm.childNodes[i]);
      }
      const textNode = new MockTextNode(elm.ownerDocument, text);
      elm.appendChild(textNode);
  }
  
  class MockComment extends MockNode {
      constructor(ownerDocument, data) {
          super(ownerDocument, 8, "#comment", data);
      }
      cloneNode(_deep) {
          return new MockComment(null, this.nodeValue);
      }
      get textContent() {
          return this.nodeValue;
      }
      set textContent(text) {
          this.nodeValue = text;
      }
  }
  
  class MockDocumentFragment extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, null);
          this.nodeName = "#document-fragment";
          this.nodeType = 11;
      }
      cloneNode(deep) {
          const cloned = new MockDocumentFragment(null);
          if (deep) {
              for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
                  const childNode = this.childNodes[i];
                  if (childNode.nodeType === 1 || childNode.nodeType === 3 || childNode.nodeType === 8) {
                      const clonedChildNode = this.childNodes[i].cloneNode(true);
                      cloned.appendChild(clonedChildNode);
                  }
              }
          }
          return cloned;
      }
  }
  
  class MockDocumentTypeNode extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, '!DOCTYPE');
          this.nodeType = 10;
          this.setAttribute('html', '');
      }
  }
  
  function createElement(ownerDocument, tagName) {
      if (typeof tagName !== 'string' || tagName === '' || !(/^[a-z0-9-_:]+$/i.test(tagName))) {
          throw new Error(`The tag name provided (${tagName}) is not a valid name.`);
      }
      tagName = tagName.toLowerCase();
      switch (tagName) {
          case 'a':
              return new MockAnchorElement(ownerDocument);
          case 'base':
              return new MockBaseElement(ownerDocument);
          case 'button':
              return new MockButtonElement(ownerDocument);
          case 'form':
              return new MockFormElement(ownerDocument);
          case 'img':
              return new MockImgElement(ownerDocument);
          case 'input':
              return new MockInputElement(ownerDocument);
          case 'link':
              return new MockLinkElement(ownerDocument);
          case 'meta':
              return new MockMetaElement(ownerDocument);
          case 'script':
              return new MockScriptElement(ownerDocument);
          case 'template':
              return new MockTemplateElement(ownerDocument);
          case 'title':
              return new MockTitleElement(ownerDocument);
          case 'canvas':
              return new MockCanvasElement(ownerDocument);
      }
      if (ownerDocument != null && tagName.includes('-')) {
          const win = ownerDocument.defaultView;
          if (win != null && win.customElements != null) {
              return createCustomElement(win.customElements, ownerDocument, tagName);
          }
      }
      return new MockHTMLElement(ownerDocument, tagName);
  }
  function createElementNS(ownerDocument, namespaceURI, tagName) {
      if (namespaceURI === 'http://www.w3.org/1999/xhtml') {
          return createElement(ownerDocument, tagName);
      }
      else if (namespaceURI === 'http://www.w3.org/2000/svg') {
          return new MockSVGElement(ownerDocument, tagName);
      }
      else {
          return new MockElement(ownerDocument, tagName);
      }
  }
  class MockAnchorElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'a');
      }
      get href() {
          return fullUrl(this, 'href');
      }
      set href(value) {
          this.setAttribute('href', value);
      }
  }
  class MockButtonElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'button');
      }
  }
  patchPropAttributes(MockButtonElement.prototype, {
      type: String
  }, {
      type: 'submit'
  });
  class MockImgElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'img');
      }
      get src() {
          return fullUrl(this, 'src');
      }
      set src(value) {
          this.setAttribute('src', value);
      }
  }
  patchPropAttributes(MockImgElement.prototype, {
      height: Number,
      width: Number
  });
  class MockInputElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'input');
      }
  }
  patchPropAttributes(MockInputElement.prototype, {
      accept: String,
      autocomplete: String,
      autofocus: Boolean,
      capture: String,
      checked: Boolean,
      disabled: Boolean,
      form: String,
      formaction: String,
      formenctype: String,
      formmethod: String,
      formnovalidate: String,
      formtarget: String,
      height: Number,
      inputmode: String,
      list: String,
      max: String,
      maxLength: Number,
      min: String,
      minLength: Number,
      multiple: Boolean,
      name: String,
      pattern: String,
      placeholder: String,
      required: Boolean,
      readOnly: Boolean,
      size: Number,
      spellCheck: Boolean,
      src: String,
      step: String,
      type: String,
      value: String,
      width: Number
  }, {
      type: 'text'
  });
  class MockFormElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'form');
      }
  }
  patchPropAttributes(MockFormElement.prototype, {
      name: String
  });
  class MockLinkElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'link');
      }
      get href() {
          return fullUrl(this, 'href');
      }
      set href(value) {
          this.setAttribute('href', value);
      }
  }
  patchPropAttributes(MockLinkElement.prototype, {
      crossorigin: String,
      media: String,
      rel: String,
      type: String
  });
  class MockMetaElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'meta');
      }
  }
  patchPropAttributes(MockMetaElement.prototype, {
      charset: String,
      content: String,
      name: String
  });
  class MockScriptElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'script');
      }
      get src() {
          return fullUrl(this, 'src');
      }
      set src(value) {
          this.setAttribute('src', value);
      }
  }
  patchPropAttributes(MockScriptElement.prototype, {
      type: String
  });
  class MockSVGElement extends MockElement {
      get ownerSVGElement() { return null; }
      get viewportElement() { return null; }
      focus() { }
      onunload() { }
      get pathLength() { return 0; }
      isPointInFill(_pt) { return false; }
      isPointInStroke(_pt) { return false; }
      getTotalLength() { return 0; }
  }
  class MockBaseElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'base');
      }
      get href() {
          return fullUrl(this, 'href');
      }
      set href(value) {
          this.setAttribute('href', value);
      }
  }
  class MockTemplateElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'template');
          this.content = new MockDocumentFragment(ownerDocument);
      }
      get innerHTML() {
          return this.content.innerHTML;
      }
      set innerHTML(html) {
          this.content.innerHTML = html;
      }
      cloneNode(deep) {
          const cloned = new MockTemplateElement(null);
          cloned.attributes = cloneAttributes(this.attributes);
          const styleCssText = this.getAttribute('style');
          if (styleCssText != null && styleCssText.length > 0) {
              cloned.setAttribute('style', styleCssText);
          }
          cloned.content = this.content.cloneNode(deep);
          if (deep) {
              for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
                  const clonedChildNode = this.childNodes[i].cloneNode(true);
                  cloned.appendChild(clonedChildNode);
              }
          }
          return cloned;
      }
  }
  class MockTitleElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'title');
      }
      get text() {
          return this.textContent;
      }
      set text(value) {
          this.textContent = value;
      }
  }
  class MockCanvasElement extends MockHTMLElement {
      constructor(ownerDocument) {
          super(ownerDocument, 'canvas');
      }
      getContext() {
          return {
              fillRect: function () { return; },
              clearRect: function () { return; },
              getImageData: function (_, __, w, h) {
                  return {
                      data: new Array(w * h * 4)
                  };
              },
              putImageData: function () { return; },
              createImageData: function () { return []; },
              setTransform: function () { return; },
              drawImage: function () { return; },
              save: function () { return; },
              fillText: function () { return; },
              restore: function () { return; },
              beginPath: function () { return; },
              moveTo: function () { return; },
              lineTo: function () { return; },
              closePath: function () { return; },
              stroke: function () { return; },
              translate: function () { return; },
              scale: function () { return; },
              rotate: function () { return; },
              arc: function () { return; },
              fill: function () { return; },
              measureText: function () {
                  return { width: 0 };
              },
              transform: function () { return; },
              rect: function () { return; },
              clip: function () { return; },
          };
      }
  }
  function fullUrl(elm, attrName) {
      const val = elm.getAttribute(attrName) || '';
      if (elm.ownerDocument != null) {
          const win = elm.ownerDocument.defaultView;
          if (win != null) {
              const loc = win.location;
              if (loc != null) {
                  const url = new URL_(val, loc.href);
                  return url.href;
              }
          }
      }
      return val.replace(/\'|\"/g, '').trim();
  }
  function patchPropAttributes(prototype, attrs, defaults = {}) {
      Object.keys(attrs).forEach(propName => {
          const attr = attrs[propName];
          const defaultValue = defaults[propName];
          if (attr === Boolean) {
              Object.defineProperty(prototype, propName, {
                  get() {
                      return this.hasAttribute(propName);
                  },
                  set(value) {
                      if (value) {
                          this.setAttribute(propName, '');
                      }
                      else {
                          this.removeAttribute(propName);
                      }
                  }
              });
          }
          else if (attr === Number) {
              Object.defineProperty(prototype, propName, {
                  get() {
                      const value = this.getAttribute(propName);
                      return (value
                          ? parseInt(value, 10)
                          : defaultValue === undefined ? 0 : defaultValue);
                  },
                  set(value) {
                      this.setAttribute(propName, value);
                  }
              });
          }
          else {
              Object.defineProperty(prototype, propName, {
                  get() {
                      return this.hasAttribute(propName)
                          ? this.getAttribute(propName)
                          : defaultValue || '';
                  },
                  set(value) {
                      this.setAttribute(propName, value);
                  }
              });
          }
      });
  }
  MockElement.prototype.cloneNode = function (deep) {
      const cloned = createElement(null, this.nodeName);
      cloned.attributes = cloneAttributes(this.attributes);
      const styleCssText = this.getAttribute('style');
      if (styleCssText != null && styleCssText.length > 0) {
          cloned.setAttribute('style', styleCssText);
      }
      if (deep) {
          for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
              const clonedChildNode = this.childNodes[i].cloneNode(true);
              cloned.appendChild(clonedChildNode);
          }
      }
      return cloned;
  };
  
  const consoleNoop = () => { };
  function createConsole() {
      return {
          debug: consoleNoop,
          error: consoleNoop,
          info: consoleNoop,
          log: consoleNoop,
          warn: consoleNoop,
          dir: consoleNoop,
          dirxml: consoleNoop,
          table: consoleNoop,
          trace: consoleNoop,
          group: consoleNoop,
          groupCollapsed: consoleNoop,
          groupEnd: consoleNoop,
          clear: consoleNoop,
          count: consoleNoop,
          countReset: consoleNoop,
          assert: consoleNoop,
          profile: consoleNoop,
          profileEnd: consoleNoop,
          time: consoleNoop,
          timeLog: consoleNoop,
          timeEnd: consoleNoop,
          timeStamp: consoleNoop,
          context: consoleNoop,
          memory: consoleNoop
      };
  }
  
  class MockHistory {
      constructor() {
          this.items = [];
      }
      get length() {
          return this.items.length;
      }
      back() {
          this.go(-1);
      }
      forward() {
          this.go(1);
      }
      go(_value) {
      }
      pushState(_state, _title, _url) {
      }
      replaceState(_state, _title, _url) {
      }
  }
  
  class MockLocation {
      constructor() {
          this.ancestorOrigins = null;
          this.protocol = '';
          this.host = '';
          this.hostname = '';
          this.port = '';
          this.pathname = '';
          this.search = '';
          this.hash = '';
          this.username = '';
          this.password = '';
          this.origin = '';
          this._href = '';
      }
      get href() {
          return this._href;
      }
      set href(value) {
          const url = new URL_(value, 'http://mockdoc.stenciljs.com');
          this._href = url.href;
          this.protocol = url.protocol;
          this.host = url.host;
          this.port = url.port;
          this.pathname = url.pathname;
          this.search = url.search;
          this.hash = url.hash;
          this.username = url.username;
          this.password = url.password;
          this.origin = url.origin;
      }
      assign(_url) {
      }
      reload(_forcedReload) {
      }
      replace(_url) {
      }
      toString() {
          return this.href;
      }
  }
  
  class MockNavigator {
      constructor() {
          this.appCodeName = 'MockNavigator';
          this.appName = 'MockNavigator';
          this.appVersion = 'MockNavigator';
          this.platform = 'MockNavigator';
          this.userAgent = 'MockNavigator';
      }
  }
  
  class MockPerformance {
      constructor() {
          this.timeOrigin = Date.now();
      }
      addEventListener() {
      }
      clearMarks() {
      }
      clearMeasures() {
      }
      clearResourceTimings() {
      }
      dispatchEvent() {
          return true;
      }
      getEntries() {
          return [];
      }
      getEntriesByName() {
          return [];
      }
      getEntriesByType() {
          return [];
      }
      mark() {
      }
      measure() {
      }
      get navigation() {
          return {};
      }
      now() {
          return Date.now() - this.timeOrigin;
      }
      get onresourcetimingbufferfull() {
          return null;
      }
      removeEventListener() {
      }
      setResourceTimingBufferSize() {
      }
      get timing() {
          return {};
      }
      toJSON() {
      }
  }
  function resetPerformance(perf) {
      if (perf != null) {
          try {
              perf.timeOrigin = Date.now();
          }
          catch (e) { }
      }
  }
  
  class MockStorage {
      constructor() {
          this.items = new Map();
      }
      key(_value) {
      }
      getItem(key) {
          key = String(key);
          if (this.items.has(key)) {
              return this.items.get(key);
          }
          return null;
      }
      setItem(key, value) {
          if (value == null) {
              value = 'null';
          }
          this.items.set(String(key), String(value));
      }
      removeItem(key) {
          this.items.delete(String(key));
      }
      clear() {
          this.items.clear();
      }
  }
  
  const historyMap = new WeakMap();
  const elementCstrMap = new WeakMap();
  const htmlElementCstrMap = new WeakMap();
  const nodeListCstrMap = new WeakMap();
  const localStorageMap = new WeakMap();
  const locMap = new WeakMap();
  const navMap = new WeakMap();
  const sessionStorageMap = new WeakMap();
  const eventClassMap = new WeakMap();
  const customEventClassMap = new WeakMap();
  const keyboardEventClassMap = new WeakMap();
  const mouseEventClassMap = new WeakMap();
  const nativeClearInterval = clearInterval;
  const nativeClearTimeout = clearTimeout;
  const nativeSetInterval = setInterval;
  const nativeSetTimeout = setTimeout;
  const nativeURL = URL_;
  class MockWindow {
      constructor(html = null) {
          if (html !== false) {
              this.document = new MockDocument(html, this);
          }
          else {
              this.document = null;
          }
          this.performance = new MockPerformance();
          this.customElements = new MockCustomElementRegistry(this);
          this.console = createConsole();
          resetWindowDefaults(this);
          resetWindowDimensions(this);
      }
      addEventListener(type, handler) {
          addEventListener(this, type, handler);
      }
      alert(msg) {
          this.console.debug(msg);
      }
      cancelAnimationFrame(id) {
          this.__clearTimeout(id);
      }
      cancelIdleCallback(id) {
          this.__clearTimeout(id);
      }
      clearInterval(id) {
          this.__clearInterval(id);
      }
      clearTimeout(id) {
          this.__clearTimeout(id);
      }
      close() {
          resetWindow(this);
      }
      confirm() {
          return false;
      }
      get CSS() {
          return {
              supports: () => true
          };
      }
      get CustomEvent() {
          const custEvClass = customEventClassMap.get(this);
          if (custEvClass != null) {
              return custEvClass;
          }
          return MockCustomEvent;
      }
      set CustomEvent(custEvClass) {
          customEventClassMap.set(this, custEvClass);
      }
      get KeyboardEvent() {
          const kbEvClass = keyboardEventClassMap.get(this);
          if (kbEvClass != null) {
              return kbEvClass;
          }
          return MockKeyboardEvent;
      }
      set KeyboardEvent(kbEvClass) {
          keyboardEventClassMap.set(this, kbEvClass);
      }
      get MouseEvent() {
          const mouseEvClass = mouseEventClassMap.get(this);
          if (mouseEvClass != null) {
              return mouseEvClass;
          }
          return MockMouseEvent;
      }
      set MouseEvent(mouseEvClass) {
          mouseEventClassMap.set(this, mouseEvClass);
      }
      dispatchEvent(ev) {
          return dispatchEvent(this, ev);
      }
      get JSON() {
          return JSON;
      }
      get Event() {
          const evClass = eventClassMap.get(this);
          if (evClass != null) {
              return evClass;
          }
          return MockEvent;
      }
      set Event(ev) {
          eventClassMap.set(this, ev);
      }
      getComputedStyle(_) {
          return {
              cssText: '',
              length: 0,
              parentRule: null,
              getPropertyPriority() {
                  return null;
              },
              getPropertyValue() {
                  return '';
              },
              item() {
                  return null;
              },
              removeProperty() {
                  return null;
              },
              setProperty() {
                  return null;
              }
          };
      }
      get globalThis() {
          return this;
      }
      get history() {
          let hsty = historyMap.get(this);
          if (hsty == null) {
              hsty = new MockHistory();
              historyMap.set(this, hsty);
          }
          return hsty;
      }
      set history(hsty) {
          historyMap.set(this, hsty);
      }
      get Element() {
          let ElementCstr = elementCstrMap.get(this);
          if (ElementCstr == null) {
              const ownerDocument = this.document;
              ElementCstr = class extends MockElement {
                  constructor() {
                      super(ownerDocument, '');
                      throw (new Error('Illegal constructor: cannot construct Element'));
                  }
              };
              elementCstrMap.set(this, ElementCstr);
          }
          return ElementCstr;
      }
      get NodeList() {
          let NodeListCstr = nodeListCstrMap.get(this);
          if (NodeListCstr == null) {
              const ownerDocument = this.document;
              NodeListCstr = class extends MockNodeList {
                  constructor() {
                      super(ownerDocument, [], 0);
                      throw (new Error('Illegal constructor: cannot constructor'));
                  }
              };
              return NodeListCstr;
          }
      }
      get HTMLElement() {
          let HtmlElementCstr = htmlElementCstrMap.get(this);
          if (HtmlElementCstr == null) {
              const ownerDocument = this.document;
              HtmlElementCstr = class extends MockHTMLElement {
                  constructor() {
                      super(ownerDocument, '');
                      const observedAttributes = this.constructor.observedAttributes;
                      if (Array.isArray(observedAttributes) && typeof this.attributeChangedCallback === 'function') {
                          observedAttributes.forEach(attrName => {
                              const attrValue = this.getAttribute(attrName);
                              if (attrValue != null) {
                                  this.attributeChangedCallback(attrName, null, attrValue);
                              }
                          });
                      }
                  }
              };
              htmlElementCstrMap.set(this, HtmlElementCstr);
          }
          return HtmlElementCstr;
      }
      get localStorage() {
          let locStorage = localStorageMap.get(this);
          if (locStorage == null) {
              locStorage = new MockStorage();
              localStorageMap.set(this, locStorage);
          }
          return locStorage;
      }
      set localStorage(locStorage) {
          localStorageMap.set(this, locStorage);
      }
      get location() {
          let loc = locMap.get(this);
          if (loc == null) {
              loc = new MockLocation();
              locMap.set(this, loc);
          }
          return loc;
      }
      set location(val) {
          if (typeof val === 'string') {
              let loc = locMap.get(this);
              if (loc == null) {
                  loc = new MockLocation();
                  locMap.set(this, loc);
              }
              loc.href = val;
          }
          else {
              locMap.set(this, val);
          }
      }
      matchMedia() {
          return {
              matches: false
          };
      }
      get navigator() {
          let nav = navMap.get(this);
          if (nav == null) {
              nav = new MockNavigator();
              navMap.set(this, nav);
          }
          return nav;
      }
      set navigator(nav) {
          navMap.set(this, nav);
      }
      get parent() {
          return null;
      }
      prompt() {
          return '';
      }
      get origin() {
          return this.location.origin;
      }
      removeEventListener(type, handler) {
          removeEventListener(this, type, handler);
      }
      requestAnimationFrame(callback) {
          return this.setTimeout(() => {
              callback(Date.now());
          }, 0);
      }
      requestIdleCallback(callback) {
          return this.setTimeout(() => {
              callback({
                  didTimeout: false,
                  timeRemaining: () => 0
              });
          }, 0);
      }
      scroll(_x, _y) { }
      scrollBy(_x, _y) { }
      scrollTo(_x, _y) { }
      get self() {
          return this;
      }
      get sessionStorage() {
          let sessStorage = sessionStorageMap.get(this);
          if (sessStorage == null) {
              sessStorage = new MockStorage();
              sessionStorageMap.set(this, sessStorage);
          }
          return sessStorage;
      }
      set sessionStorage(locStorage) {
          sessionStorageMap.set(this, locStorage);
      }
      setInterval(callback, ms, ...args) {
          ms = Math.min(ms, this.__maxTimeout);
          if (this.__allowInterval) {
              return this.__setInterval(() => {
                  try {
                      callback(...args);
                  }
                  catch (e) {
                      this.console.error(e);
                  }
              }, ms);
          }
          return this.__setTimeout(() => {
              try {
                  callback(...args);
              }
              catch (e) {
                  this.console.error(e);
              }
          }, ms);
      }
      setTimeout(callback, ms, ...args) {
          ms = Math.min(ms, this.__maxTimeout);
          return this.__setTimeout(() => {
              try {
                  callback(...args);
              }
              catch (e) {
                  this.console.error(e);
              }
          }, ms);
      }
      get top() {
          return this;
      }
      get window() {
          return this;
      }
      onanimationstart() { }
      onanimationend() { }
      onanimationiteration() { }
      onabort() { }
      onauxclick() { }
      onbeforecopy() { }
      onbeforecut() { }
      onbeforepaste() { }
      onblur() { }
      oncancel() { }
      oncanplay() { }
      oncanplaythrough() { }
      onchange() { }
      onclick() { }
      onclose() { }
      oncontextmenu() { }
      oncopy() { }
      oncuechange() { }
      oncut() { }
      ondblclick() { }
      ondrag() { }
      ondragend() { }
      ondragenter() { }
      ondragleave() { }
      ondragover() { }
      ondragstart() { }
      ondrop() { }
      ondurationchange() { }
      onemptied() { }
      onended() { }
      onerror() { }
      onfocus() { }
      onformdata() { }
      onfullscreenchange() { }
      onfullscreenerror() { }
      ongotpointercapture() { }
      oninput() { }
      oninvalid() { }
      onkeydown() { }
      onkeypress() { }
      onkeyup() { }
      onload() { }
      onloadeddata() { }
      onloadedmetadata() { }
      onloadstart() { }
      onlostpointercapture() { }
      onmousedown() { }
      onmouseenter() { }
      onmouseleave() { }
      onmousemove() { }
      onmouseout() { }
      onmouseover() { }
      onmouseup() { }
      onmousewheel() { }
      onpaste() { }
      onpause() { }
      onplay() { }
      onplaying() { }
      onpointercancel() { }
      onpointerdown() { }
      onpointerenter() { }
      onpointerleave() { }
      onpointermove() { }
      onpointerout() { }
      onpointerover() { }
      onpointerup() { }
      onprogress() { }
      onratechange() { }
      onreset() { }
      onresize() { }
      onscroll() { }
      onsearch() { }
      onseeked() { }
      onseeking() { }
      onselect() { }
      onselectstart() { }
      onstalled() { }
      onsubmit() { }
      onsuspend() { }
      ontimeupdate() { }
      ontoggle() { }
      onvolumechange() { }
      onwaiting() { }
      onwebkitfullscreenchange() { }
      onwebkitfullscreenerror() { }
      onwheel() { }
  }
  function resetWindowDefaults(win) {
      win.__clearInterval = nativeClearInterval;
      win.__clearTimeout = nativeClearTimeout;
      win.__setInterval = nativeSetInterval;
      win.__setTimeout = nativeSetTimeout;
      win.__maxTimeout = 30000;
      win.__allowInterval = true;
      win.URL = nativeURL;
  }
  function constrainTimeouts(win) {
      win.__allowInterval = false;
      win.__maxTimeout = 0;
  }
  function resetWindow(win) {
      if (win != null) {
          resetCustomElementRegistry(win.customElements);
          resetDocument(win.document);
          resetPerformance(win.performance);
          for (const key in win) {
              if (win.hasOwnProperty(key) && key !== 'document' && key !== 'performance' && key !== 'customElements') {
                  delete win[key];
              }
          }
          resetWindowDefaults(win);
          resetWindowDimensions(win);
          resetEventListeners(win);
          historyMap.delete(win);
          htmlElementCstrMap.delete(win);
          elementCstrMap.delete(win);
          nodeListCstrMap.delete(win);
          localStorageMap.delete(win);
          locMap.delete(win);
          navMap.delete(win);
          sessionStorageMap.delete(win);
          eventClassMap.delete(win);
          customEventClassMap.delete(win);
          keyboardEventClassMap.delete(win);
          mouseEventClassMap.delete(win);
          if (win.document != null) {
              try {
                  win.document.defaultView = win;
              }
              catch (e) { }
          }
      }
  }
  function resetWindowDimensions(win) {
      try {
          win.devicePixelRatio = 1;
          win.innerHeight = 768;
          win.innerWidth = 1366;
          win.pageXOffset = 0;
          win.pageYOffset = 0;
          win.screenLeft = 0;
          win.screenTop = 0;
          win.screenX = 0;
          win.screenY = 0;
          win.scrollX = 0;
          win.scrollY = 0;
          win.screen = {
              availHeight: win.innerHeight,
              availLeft: 0,
              availTop: 0,
              availWidth: win.innerWidth,
              colorDepth: 24,
              height: win.innerHeight,
              keepAwake: false,
              orientation: {
                  angle: 0,
                  type: 'portrait-primary'
              },
              pixelDepth: 24,
              width: win.innerWidth
          };
      }
      catch (e) { }
  }
  
  class MockDocument extends MockHTMLElement {
      constructor(html = null, win = null) {
          super(null, null);
          this.nodeName = "#document";
          this.nodeType = 9;
          this.defaultView = win;
          this.cookie = '';
          this.referrer = '';
          this.appendChild(this.createDocumentTypeNode());
          if (typeof html === 'string') {
              const parsedDoc = parseDocumentUtil(this, html);
              const documentElement = parsedDoc.children.find(elm => elm.nodeName === 'HTML');
              if (documentElement != null) {
                  this.appendChild(documentElement);
                  setOwnerDocument(documentElement, this);
              }
          }
          else if (html !== false) {
              const documentElement = new MockHTMLElement(this, 'html');
              this.appendChild(documentElement);
              documentElement.appendChild(new MockHTMLElement(this, 'head'));
              documentElement.appendChild(new MockHTMLElement(this, 'body'));
          }
      }
      get location() {
          if (this.defaultView != null) {
              return this.defaultView.location;
          }
          return null;
      }
      set location(val) {
          if (this.defaultView != null) {
              this.defaultView.location = val;
          }
      }
      get baseURI() {
          const baseNode = this.head.childNodes.find(node => node.nodeName === 'BASE');
          if (baseNode) {
              return baseNode.href;
          }
          return this.URL;
      }
      get URL() {
          return this.location.href;
      }
      get styleSheets() {
          return this.querySelectorAll('style');
      }
      get scripts() {
          return this.querySelectorAll('script');
      }
      get forms() {
          return this.querySelectorAll('form');
      }
      get images() {
          return this.querySelectorAll('img');
      }
      get scrollingElement() {
          return this.documentElement;
      }
      get documentElement() {
          for (let i = this.childNodes.length - 1; i >= 0; i--) {
              if (this.childNodes[i].nodeName === 'HTML') {
                  return this.childNodes[i];
              }
          }
          const documentElement = new MockHTMLElement(this, 'html');
          this.appendChild(documentElement);
          return documentElement;
      }
      set documentElement(documentElement) {
          for (let i = this.childNodes.length - 1; i >= 0; i--) {
              if (this.childNodes[i].nodeType !== 10) {
                  this.childNodes[i].remove();
              }
          }
          if (documentElement != null) {
              this.appendChild(documentElement);
              setOwnerDocument(documentElement, this);
          }
      }
      get head() {
          const documentElement = this.documentElement;
          for (let i = 0; i < documentElement.childNodes.length; i++) {
              if (documentElement.childNodes[i].nodeName === 'HEAD') {
                  return documentElement.childNodes[i];
              }
          }
          const head = new MockHTMLElement(this, 'head');
          documentElement.insertBefore(head, documentElement.firstChild);
          return head;
      }
      set head(head) {
          const documentElement = this.documentElement;
          for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
              if (documentElement.childNodes[i].nodeName === 'HEAD') {
                  documentElement.childNodes[i].remove();
              }
          }
          if (head != null) {
              documentElement.insertBefore(head, documentElement.firstChild);
              setOwnerDocument(head, this);
          }
      }
      get body() {
          const documentElement = this.documentElement;
          for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
              if (documentElement.childNodes[i].nodeName === 'BODY') {
                  return documentElement.childNodes[i];
              }
          }
          const body = new MockHTMLElement(this, 'body');
          documentElement.appendChild(body);
          return body;
      }
      set body(body) {
          const documentElement = this.documentElement;
          for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
              if (documentElement.childNodes[i].nodeName === 'BODY') {
                  documentElement.childNodes[i].remove();
              }
          }
          if (body != null) {
              documentElement.appendChild(body);
              setOwnerDocument(body, this);
          }
      }
      appendChild(newNode) {
          newNode.remove();
          newNode.parentNode = this;
          this.childNodes.push(newNode);
          return newNode;
      }
      createComment(data) {
          return new MockComment(this, data);
      }
      createAttribute(attrName) {
          return new MockAttr(attrName.toLowerCase(), '');
      }
      createAttributeNS(namespaceURI, attrName) {
          return new MockAttr(attrName, '', namespaceURI);
      }
      createElement(tagName) {
          if (tagName === "#document") {
              const doc = new MockDocument(false);
              doc.nodeName = tagName;
              doc.parentNode = null;
              return doc;
          }
          return createElement(this, tagName);
      }
      createElementNS(namespaceURI, tagName) {
          const elmNs = createElementNS(this, namespaceURI, tagName);
          elmNs.namespaceURI = namespaceURI;
          return elmNs;
      }
      createTextNode(text) {
          return new MockTextNode(this, text);
      }
      createDocumentFragment() {
          return new MockDocumentFragment(this);
      }
      createDocumentTypeNode() {
          return new MockDocumentTypeNode(this);
      }
      getElementById(id) {
          return getElementById(this, id);
      }
      getElementsByClassName(classNames) {
          const foundElms = [];
          const classes = classNames.trim().split(' ').filter(c => c.length > 0);
          getElementsByClassName(this, classes, foundElms);
          return foundElms;
      }
      getElementsByTagName(tagName) {
          const foundElms = [];
          getElementsByTagName(this, tagName.toLowerCase(), foundElms);
          return foundElms;
      }
      getElementsByName(elmName) {
          const foundElms = [];
          getElementsByName(this, elmName.toLowerCase(), foundElms);
          return foundElms;
      }
      get title() {
          const title = this.head.childNodes.find(elm => elm.nodeName === 'TITLE');
          if (title != null) {
              return title.textContent;
          }
          return '';
      }
      set title(value) {
          const head = this.head;
          let title = head.childNodes.find(elm => elm.nodeName === 'TITLE');
          if (title == null) {
              title = this.createElement('title');
              head.appendChild(title);
          }
          title.textContent = value;
      }
  }
  function resetDocument(doc) {
      if (doc != null) {
          resetEventListeners(doc);
          const documentElement = doc.documentElement;
          if (documentElement != null) {
              resetElement(documentElement);
              for (let i = 0, ii = documentElement.childNodes.length; i < ii; i++) {
                  const childNode = documentElement.childNodes[i];
                  resetElement(childNode);
                  childNode.childNodes.length = 0;
              }
          }
          for (const key in doc) {
              if (doc.hasOwnProperty(key) && !DOC_KEY_KEEPERS.has(key)) {
                  delete doc[key];
              }
          }
          try {
              doc.nodeName = "#document";
          }
          catch (e) { }
          try {
              doc.nodeType = 9;
          }
          catch (e) { }
          try {
              doc.cookie = '';
          }
          catch (e) { }
          try {
              doc.referrer = '';
          }
          catch (e) { }
      }
  }
  const DOC_KEY_KEEPERS = new Set([
      'nodeName',
      'nodeType',
      'nodeValue',
      'ownerDocument',
      'parentNode',
      'childNodes',
      '_shadowRoot'
  ]);
  function getElementById(elm, id) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          const childElm = children[i];
          if (childElm.id === id) {
              return childElm;
          }
          const childElmFound = getElementById(childElm, id);
          if (childElmFound != null) {
              return childElmFound;
          }
      }
      return null;
  }
  function getElementsByClassName(elm, classNames, foundElms) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          const childElm = children[i];
          for (let j = 0, jj = classNames.length; j < jj; j++) {
              if (childElm.classList.contains(classNames[j])) {
                  foundElms.push(childElm);
              }
          }
          getElementsByClassName(childElm, classNames, foundElms);
      }
  }
  function getElementsByTagName(elm, tagName, foundElms) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          const childElm = children[i];
          if (childElm.nodeName.toLowerCase() === tagName) {
              foundElms.push(childElm);
          }
          getElementsByTagName(childElm, tagName, foundElms);
      }
  }
  function getElementsByName(elm, elmName, foundElms) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          const childElm = children[i];
          if (childElm.name && childElm.name.toLowerCase() === elmName) {
              foundElms.push(childElm);
          }
          getElementsByName(childElm, elmName, foundElms);
      }
  }
  function setOwnerDocument(elm, ownerDocument) {
      for (let i = 0, ii = elm.childNodes.length; i < ii; i++) {
          elm.childNodes[i].ownerDocument = ownerDocument;
          if (elm.childNodes[i].nodeType === 1) {
              setOwnerDocument(elm.childNodes[i], ownerDocument);
          }
      }
  }
  
  function patchWindow(winToBePatched) {
      const mockWin = new MockWindow(false);
      WINDOW_FUNCTIONS.forEach(fnName => {
          if (typeof winToBePatched[fnName] !== 'function') {
              winToBePatched[fnName] = mockWin[fnName].bind(mockWin);
          }
      });
      WINDOW_PROPS$1.forEach(propName => {
          if (winToBePatched === undefined) {
              Object.defineProperty(winToBePatched, propName, {
                  get() { return mockWin[propName]; },
                  set(val) { mockWin[propName] = val; },
                  configurable: true,
                  enumerable: true
              });
          }
      });
  }
  const WINDOW_FUNCTIONS = [
      'addEventListener',
      'cancelAnimationFrame',
      'cancelIdleCallback',
      'dispatchEvent',
      'matchMedia',
      'removeEventListener',
      'requestAnimationFrame',
      'requestIdleCallback',
      'URL'
  ];
  const WINDOW_PROPS$1 = [
      'customElements',
      'devicePixelRatio',
      'document',
      'history',
      'innerHeight',
      'innerWidth',
      'localStorage',
      'location',
      'navigator',
      'pageXOffset',
      'pageYOffset',
      'performance',
      'screenLeft',
      'screenTop',
      'screenX',
      'screenY',
      'scrollX',
      'scrollY',
      'sessionStorage',
      'CSS',
      'CustomEvent',
      'Event',
      'Element',
      'HTMLElement',
      'NodeList',
      'KeyboardEvent',
      'MouseEvent'
  ];
  
  function initializeWindow(win, doc, opts, results) {
      try {
          win.location.href = results.url;
      }
      catch (e) {
          renderCatchError(results, e);
      }
      if (typeof opts.userAgent === 'string') {
          try {
              win.navigator.userAgent = opts.userAgent;
          }
          catch (e) { }
      }
      if (typeof opts.cookie === 'string') {
          try {
              doc.cookie = opts.cookie;
          }
          catch (e) { }
      }
      if (typeof opts.referrer === 'string') {
          try {
              doc.referrer = opts.referrer;
          }
          catch (e) { }
      }
      if (typeof opts.direction === 'string') {
          try {
              doc.documentElement.setAttribute('dir', opts.direction);
          }
          catch (e) { }
      }
      if (typeof opts.language === 'string') {
          try {
              doc.documentElement.setAttribute('lang', opts.language);
          }
          catch (e) { }
      }
      try {
          win.customElements = null;
      }
      catch (e) { }
      if (opts.constrainTimeouts) {
          constrainTimeouts(win);
      }
      try {
          win.console.error = function () {
              const diagnostic = {
                  level: 'error',
                  type: 'runtime',
                  header: 'Hydrate Error',
                  messageText: [...arguments].join(', '),
                  relFilePath: null,
                  absFilePath: null,
                  lines: []
              };
              if (typeof results.pathname === 'string') {
                  diagnostic.header += `: ${results.pathname}`;
              }
              results.diagnostics.push(diagnostic);
          };
          win.console.debug = function () {
              const diagnostic = {
                  level: 'debug',
                  type: 'build',
                  header: 'Hydrate Debug',
                  messageText: [...arguments].join(', '),
                  relFilePath: null,
                  absFilePath: null,
                  lines: []
              };
              if (typeof results.pathname === 'string') {
                  diagnostic.header += `: ${results.pathname}`;
              }
              results.diagnostics.push(diagnostic);
          };
      }
      catch (e) {
          renderCatchError(results, e);
      }
  }
  
  function inspectElement(results, elm, depth) {
      const children = elm.children;
      for (let i = 0, ii = children.length; i < ii; i++) {
          const childElm = children[i];
          const tagName = childElm.tagName.toLowerCase();
          if (tagName.includes('-')) {
              const cmp = results.components.find(c => c.tag === tagName);
              if (cmp != null) {
                  cmp.count++;
                  if (depth > cmp.depth) {
                      cmp.depth = depth;
                  }
              }
          }
          else {
              switch (tagName) {
                  case 'a':
                      const anchor = collectAttributes(childElm);
                      anchor.href = childElm.href;
                      if (typeof anchor.href === 'string') {
                          if (!results.anchors.some(a => a.href === anchor.href)) {
                              results.anchors.push(anchor);
                          }
                      }
                      break;
                  case 'img':
                      const img = collectAttributes(childElm);
                      img.src = childElm.src;
                      if (typeof img.src === 'string') {
                          if (!results.imgs.some(a => a.src === img.src)) {
                              results.imgs.push(img);
                          }
                      }
                      break;
                  case 'link':
                      const link = collectAttributes(childElm);
                      link.href = childElm.href;
                      if (typeof link.rel === 'string' && link.rel.toLowerCase() === 'stylesheet') {
                          if (typeof link.href === 'string') {
                              if (!results.styles.some(s => s.link === link.href)) {
                                  delete link.rel;
                                  delete link.type;
                                  results.styles.push(link);
                              }
                          }
                      }
                      break;
                  case 'script':
                      const script = collectAttributes(childElm);
                      script.src = childElm.src;
                      if (typeof script.src === 'string') {
                          if (!results.scripts.some(s => s.src === script.src)) {
                              results.scripts.push(script);
                          }
                      }
                      break;
              }
          }
          depth++;
          inspectElement(results, childElm, depth);
      }
  }
  function collectAttributes(node) {
      const parsedElm = {};
      const attrs = node.attributes;
      for (let i = 0, ii = attrs.length; i < ii; i++) {
          const attr = attrs.item(i);
          const attrName = attr.nodeName.toLowerCase();
          if (SKIP_ATTRS.has(attrName)) {
              continue;
          }
          const attrValue = attr.nodeValue;
          if (attrName === 'class' && attrValue === '') {
              continue;
          }
          parsedElm[attrName] = attrValue;
      }
      return parsedElm;
  }
  const SKIP_ATTRS = new Set([
      's-id', 'c-id'
  ]);
  
  function patchDomImplementation(doc) {
      let win;
      if (doc.defaultView != null) {
          patchWindow(doc.defaultView);
          win = doc.defaultView;
      }
      else {
          win = new MockWindow(false);
      }
      if (win.document !== doc) {
          win.document = doc;
      }
      if (doc.defaultView !== win) {
          doc.defaultView = win;
      }
      const HTMLElement = doc.documentElement.constructor.prototype;
      if (typeof HTMLElement.getRootNode !== 'function') {
          const elm = doc.createElement('unknown-element');
          const HTMLUnknownElement = elm.constructor.prototype;
          HTMLUnknownElement.getRootNode = getRootNode;
      }
      if (typeof doc.createEvent === 'function') {
          const CustomEvent = doc.createEvent('CustomEvent').constructor;
          if (win.CustomEvent !== CustomEvent) {
              win.CustomEvent = CustomEvent;
          }
      }
      try {
          doc.baseURI;
      }
      catch (e) {
          Object.defineProperty(doc, 'baseURI', {
              get() {
                  const baseElm = doc.querySelector('base[href]');
                  if (baseElm) {
                      return (new URL(baseElm.getAttribute('href'), win.location.href)).href;
                  }
                  return win.location.href;
              }
          });
      }
      return win;
  }
  function getRootNode(opts) {
      const isComposed = (opts != null && opts.composed === true);
      let node = this;
      while (node.parentNode != null) {
          node = node.parentNode;
          if (isComposed === true && node.parentNode == null && node.host != null) {
              node = node.host;
          }
      }
      return node;
  }
  
  async function renderToString(html, opts = {}) {
      opts = normalizeHydrateOptions(opts);
      const results = generateHydrateResults(opts);
      if (results.diagnostics.length > 0) {
          return results;
      }
      if (typeof html !== 'string') {
          renderBuildError(results, `Invalid html`);
          return results;
      }
      try {
          const win = new MockWindow(html);
          const doc = win.document;
          if (typeof opts.beforeHydrate === 'function') {
              try {
                  const rtn = opts.beforeHydrate(win);
                  if (rtn != null && typeof rtn.then === 'function') {
                      await rtn;
                  }
              }
              catch (e) {
                  renderCatchError(results, e);
              }
          }
          await render(win, doc, opts, results);
          if (typeof opts.afterHydrate === 'function') {
              try {
                  const rtn = opts.afterHydrate(win);
                  if (rtn != null && typeof rtn.then === 'function') {
                      await rtn;
                  }
              }
              catch (e) {
                  renderCatchError(results, e);
              }
          }
          if (!results.diagnostics.some(d => d.type === 'error')) {
              results.html = serializeNodeToHtml(doc, {
                  approximateLineWidth: opts.approximateLineWidth,
                  outerHtml: false,
                  prettyHtml: opts.prettyHtml,
                  removeAttributeQuotes: opts.removeAttributeQuotes,
                  removeBooleanAttributeQuotes: opts.removeBooleanAttributeQuotes,
                  removeEmptyAttributes: opts.removeEmptyAttributes,
                  removeHtmlComments: opts.removeHtmlComments,
                  serializeShadowRoot: false
              });
          }
      }
      catch (e) {
          renderCatchError(results, e);
      }
      return results;
  }
  async function hydrateDocument(doc, opts = {}) {
      opts = normalizeHydrateOptions(opts);
      const results = generateHydrateResults(opts);
      if (results.diagnostics.length > 0) {
          return results;
      }
      if (doc == null || doc.nodeType !== 9 || doc.documentElement == null || doc.documentElement.nodeType !== 1) {
          renderBuildError(results, `Invalid document`);
          return results;
      }
      try {
          const win = patchDomImplementation(doc);
          await render(win, win.document, opts, results);
      }
      catch (e) {
          renderCatchError(results, e);
      }
      return results;
  }
  async function render(win, doc, opts, results) {
      catchUnhandledErrors(results);
      initializeWindow(win, doc, opts, results);
      await new Promise(resolve => {
          const tmr = setTimeout(() => {
              renderBuildError(results, `Hydrate exceeded timeout`);
              resolve();
          }, opts.timeout);
          try {
              const sandbox = createHydrateAppSandbox(win);
              sandbox.bootstrapHydrate(win, opts, (bootstrapResults) => {
                  clearTimeout(tmr);
                  try {
                      results.hydratedCount = bootstrapResults.hydratedCount;
                      bootstrapResults.hydratedComponents.forEach(component => {
                          results.components.push({
                              tag: component.tag,
                              mode: component.mode,
                              count: 0,
                              depth: -1
                          });
                      });
                  }
                  catch (e) {
                      renderCatchError(results, e);
                  }
                  bootstrapResults = null;
                  resolve();
              });
          }
          catch (e) {
              renderCatchError(results, e);
              clearTimeout(tmr);
              resolve();
          }
      });
      inspectElement(results, doc.documentElement, 0);
      finalizeWindow(doc, opts, results);
  }
  function catchUnhandledErrors(results) {
      if (process.__stencilErrors) {
          return;
      }
      process.__stencilErrors = true;
      process.on('unhandledRejection', e => {
          renderCatchError(results, e);
      });
  }
  
  exports.hydrateDocument = hydrateDocument;
  exports.renderToString = renderToString;
  