/**
 * Removes whitespace between tags, except preserves ALL whitespace between matching opening/closing tag pairs.
 *
 * This processor scans for patterns of `<tag>(whitespace)<tag>` and:
 * - If the first tag is an opening tag and the second tag is its matching closing tag (e.g., `<span> </span>`),
 *   preserves ALL the whitespace between them (including spaces, tabs, newlines)
 * - Otherwise, removes all the whitespace between the tags
 *
 * Examples:
 * - `</p>\n\t<div>` → `</p><div>` (different tags: closing p, opening div - whitespace removed)
 * - `<div>\n\t<span>` → `<div><span>` (different tags: opening div, opening span - whitespace removed)
 * - `<span> </span>` → `<span> </span>` (matching tags: opening span, closing span - space preserved)
 * - `<span>  </span>` → `<span>  </span>` (matching tags - multiple spaces preserved)
 * - `<span>\n\t</span>` → `<span>\n\t</span>` (matching tags - \n\t preserved)
 * - `<code> </code>` → `<code> </code>` (matching tags - space preserved)
 * - `</div> <p>` → `</div><p>` (different tags: closing div, opening p - whitespace removed)
 */
export class RemoveWhitespaceBetweenTagsProcessor {
  /**
   * Process the HTML string to remove whitespace between non-matching tags.
   *
   * @param {string} html - The HTML string to process.
   * @returns {string} The processed HTML string.
   */
  process(html) {
    return html.replace(/(<[^>]+>)(\s+)(<[^>]+>)/g, (_match, tag1, whitespace, tag2) => {
      const openingTagName = this.extractOpeningTagName(tag1);
      const closingTagName = this.extractClosingTagName(tag2);
      // Preserve all whitespace if tags match (e.g., <span> </span>)
      if (openingTagName && closingTagName && openingTagName === closingTagName) {
        return `${tag1}${whitespace}${tag2}`;
      }
      // Remove whitespace for non-matching tags
      return `${tag1}${tag2}`;
    });
  }
  /**
   * Extracts the tag name from an opening HTML tag.
   *
   * Supports standard HTML tags (div, span, h1, etc.) and custom elements with hyphens (my-component).
   *
   * Examples:
   * - `<span>` → `span`
   * - `<div class="test">` → `div`
   * - `<my-component id="123">` → `my-component`
   * - `</span>` → `null` (not an opening tag)
   *
   * @param {string} tag - The tag string to extract from (e.g., '<span>', '<div class="test">').
   * @returns {string | null} The tag name or null if not an opening tag.
   * @private
   */
  extractOpeningTagName(tag) {
    // Pattern: <(tag name) where tag name starts with letter, followed by letters/numbers/hyphens
    const match = tag.match(/<(\w[\w-]*)/);
    return match ? match[1] : null;
  }
  /**
   * Extracts the tag name from a closing HTML tag.
   *
   * Supports standard HTML tags (div, span, h1, etc.) and custom elements with hyphens (my-component).
   *
   * Examples:
   * - `</span>` → `span`
   * - `</div>` → `div`
   * - `</my-component>` → `my-component`
   * - `<span>` → `null` (not a closing tag)
   *
   * @param {string} tag - The tag string to extract from (e.g., '</span>', '</div>').
   * @returns {string | null} The tag name or null if not a closing tag.
   * @private
   */
  extractClosingTagName(tag) {
    // Pattern: </(tag name) where tag name starts with letter, followed by letters/numbers/hyphens
    const match = tag.match(/<\/(\w[\w-]*)/);
    return match ? match[1] : null;
  }
}
