/**
 * Tags whose direct children are always phrasing (inline) content (P, H1-H6, LI).
 *
 * This is spec knowledge from the HTML Living Standard — these grouping-content
 * elements have a phrasing-content content model and cannot contain block-level
 * descendants. It cannot be derived from the strategy registry and must be
 * maintained alongside the HTML spec.
 *
 * @see https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
 */
export const BLOCK_TEXT_CONTAINER_TAGS = new Set([
  'P',
  'H1',
  'H2',
  'H3',
  'H4',
  'H5',
  'H6',
  'LI',
]);
/**
 * Tags with dedicated element-to-DTO block strategies
 * (P, H1-H6, LI, UL, OL, IMG, CODE).
 *
 * HtmlBlockStrategy skips these to avoid double-processing or overriding their
 * specialized block semantics.
 *
 * Why hard-coded: strategies use heterogeneous matching (`tagName ===`,
 * `matchTextBlockType` via font-size/class, etc.) so there is no single
 * declarative contract to derive this set from. It must be kept in sync with
 * the strategies registered in `dto/setup.ts`.
 *
 * Intentionally independent of {@link BLOCK_TEXT_CONTAINER_TAGS} — the two
 * sets encode different concepts (app architecture vs. HTML spec) and must
 * be maintained separately.
 */
export const DEDICATED_STRATEGY_TAGS = new Set([
  'P',
  'H1',
  'H2',
  'H3',
  'H4',
  'H5',
  'H6',
  'LI',
  'UL',
  'OL',
  'IMG',
  'CODE',
]);
/**
 * Tags that are always treated as phrasing (inline) content, even when they
 * also appear in {@link DEDICATED_STRATEGY_TAGS} (CODE).
 * A tag in this set overrides the dedicated-strategy skip in HtmlBlockStrategy.
 *
 * Mix of HTML5 spec phrasing-content elements (BR, CODE, A) and
 * RTE-internal custom elements (VEGA-RICH-TEXT-LINK-EDITOR).
 */
export const ALWAYS_INLINE_TAGS = new Set(['BR', 'VEGA-RICH-TEXT-LINK-EDITOR', 'CODE', 'A']);
/**
 * Tags whose content model requires each child to be a distinct block-level
 * element (table model and definition list).
 *
 * TABLE expects CAPTION/THEAD/TBODY/TFOOT/TR; TR expects TH/TD;
 * THEAD/TBODY/TFOOT expect TR; DL expects DT/DD.
 *
 * Used by HtmlBlockStrategy to prevent text-only children (e.g. CAPTION,
 * TH, TD) from being treated as inline — they must become html-blocks so
 * the table structure round-trips correctly.
 *
 * Note: COLGROUP is intentionally excluded. Its only permitted child is the
 * void element COL, which can never produce text-node children, so the
 * text-only heuristic in HtmlBlockStrategy can never fire for a COLGROUP
 * parent.
 *
 * @see https://html.spec.whatwg.org/multipage/tables.html#the-table-element
 * @see https://html.spec.whatwg.org/multipage/grouping-content.html#the-dl-element
 */
export const STRUCTURED_CONTAINER_TAGS = new Set([
  'TABLE',
  'THEAD',
  'TBODY',
  'TFOOT',
  'TR',
  'DL',
]);
/**
 * Formatting phrasing-content elements that CAN remain inline even when empty.
 *
 * Any element NOT in this set (DIV, SECTION, ARTICLE, custom elements, etc.)
 * is treated as a block separator. Phrasing content is a closed, finite set
 * per the HTML Living Standard, making an allowlist safer than blocklisting
 * block containers (which is open-ended — custom elements default to block).
 *
 * Intentionally excludes:
 * - BR, CODE, A, VEGA-RICH-TEXT-LINK-EDITOR → handled by {@link ALWAYS_INLINE_TAGS}
 * - P, H1-H6, LI, UL, OL, IMG → handled by {@link DEDICATED_STRATEGY_TAGS}
 * - VIDEO, AUDIO, EMBED → embedded content that carries media even when empty;
 *   must be treated as block-level, not as inline formatting artifacts
 *
 * @see https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
 */
export const PHRASING_CONTENT_TAGS = new Set([
  'ABBR',
  'B',
  'BDI',
  'BDO',
  'CITE',
  'DEL',
  'DFN',
  'EM',
  'I',
  'INS',
  'KBD',
  'MARK',
  'METER',
  'OUTPUT',
  'PROGRESS',
  'Q',
  'S',
  'SAMP',
  'SMALL',
  'SPAN',
  'STRONG',
  'SUB',
  'SUP',
  'TIME',
  'U',
  'VAR',
]);
/**
 * Returns true when the element is a direct child of a block text container
 * (P, H1-H6, LI), meaning it must be treated as phrasing content regardless
 * of its own DOM structure.
 *
 * @param {HTMLElement} element - Element to test.
 * @returns {boolean} True if the element is inside a block text container.
 */
export function isInBlockTextContext(element) {
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  return BLOCK_TEXT_CONTAINER_TAGS.has(element.parentElement.nodeName);
}
