text: import {devAssert} from '#core/assert';
  import {map} from '#core/types/object';
  
  let htmlContainer;
  let svgContainer;
  
  /**
   * Creates the html helper for the doc.
   *
   * @param {HTMLElement|Document} nodeOrDoc
   * @return {function(readonly string[]):HTMLElement}
   */
  export function htmlFor(nodeOrDoc) {
    const doc = nodeOrDoc.ownerDocument || /** @type {Document} */ (nodeOrDoc);
    if (!htmlContainer || htmlContainer.ownerDocument !== doc) {
      htmlContainer = doc.createElement('div');
    }
  
    return html;
  }
  
  /**
   * Creates the svg helper for the doc.
   *
   * @param {HTMLElement|Document} nodeOrDoc
   * @return {function(readonly string[]):HTMLElement}
   */
  export function svgFor(nodeOrDoc) {
    const doc = nodeOrDoc.ownerDocument || /** @type {Document} */ (nodeOrDoc);
    if (!svgContainer || svgContainer.ownerDocument !== svgContainer) {
      svgContainer = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
    }
  
    return svg;
  }
  
  /**
   * A tagged template literal helper to generate static SVG trees.
   * This must be used as a tagged template, ie
   *
   * ```
   * const circle = svg`<circle cx="60" cy="60" r="22"></circle>`;
   * ```
   *
   * Only the root element and its subtree will be returned. DO NOT use this to
   * render subtree's with dynamic content, it WILL result in an error!
   *
   * @param {readonly string[]} strings
   * @return {HTMLElement}
   */
  function svg(strings) {
    return createNode(svgContainer, strings);
  }
  
  /**
   * A tagged template literal helper to generate static DOM trees.
   * This must be used as a tagged template, ie
   *
   * ```
   * const div = html`<div><span></span></div>`;
   * ```
   *
   * Only the root element and its subtree will be returned. DO NOT use this to
   * render subtree's with dynamic content, it WILL result in an error!
   *
   * @param {readonly string[]} strings
   * @return {HTMLElement}
   */
  function html(strings) {
    return createNode(htmlContainer, strings);
  }
  
  /**
   * Helper used by html and svg string literal functions.
   * @param {HTMLElement} container
   * @param {readonly string[]} strings
   * @return {HTMLElement}
   */
  function createNode(container, strings) {
    devAssert(strings.length === 1, 'Improper html template tag usage.');
    container./*OK*/ innerHTML = strings[0];
  
    const el = /** @type {HTMLElement} */ (container.firstElementChild);
    devAssert(el, 'No elements in template');
    devAssert(!el.nextElementSibling, 'Too many root elements in template');
  
    // Clear to free memory.
    container.removeChild(el);
  
    return el;
  }
  
  /**
   * Queries an element for all elements with a "ref" attribute, removing
   * the attribute afterwards.
   * Returns a named map of all ref elements.
   *
   * @param {HTMLElement} root
   * @return {Object<string, HTMLElement>}
   */
  export function htmlRefs(root) {
    const elements = root.querySelectorAll('[ref]');
    const refs = map();
  
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i];
      const ref = devAssert(element.getAttribute('ref'), 'Empty ref attr');
      element.removeAttribute('ref');
      devAssert(refs[ref] === undefined, 'Duplicate ref');
      refs[ref] = element;
    }
  
    return refs;
  }
  