/** * Markup helpers shared by every validator that reads Eddie markup. * * Before #1912 five validators each carried a private copy of "find the Lit * `html\`…\`` regions of a file", and only one of them had the #1727 fix — * the other four still ended a region at the first NESTED template close * (#1529), so a `${items.map((item) => html\`…\`)}` silently exempted every * line after it from the slot-contract, accessibility, placement and * anti-pattern checks. One copy here, one fix, one fixture set. * * What lives here: * - `stripBlockComments` — blank block comments, keeping line numbers. * - `extractLitTemplates` — the #1727 stack-based region extractor (template / * expression / brace nesting tracked across lines), lifted verbatim from * the naming validator. * - `findMatchingClose`, `lineOf`, `VOID_ELEMENTS` — the tag-walking helpers * the regex validators share. * - `tokenizeMarkup` / `buildMarkupTree` and the `TagToken` / `MarkupNode` * shapes — the tolerant tokenizer + tree the placement validator and the * product analyzer walk. * * Deliberately a tokenizer, not a parser (see each validator's conservatism * note): string literals and regexes inside expressions can still carry an * unbalanced brace or backtick. `@brad-frost-web/eddie-render/validate` * carries a third, selector-oriented parser (`parseMarkup`) that the * anti-pattern validator uses; unifying the two tree shapes is a separate * decision, not this module's job. */ /** HTML void elements — no closing tag, no subtree to walk. */ export declare const VOID_ELEMENTS: Set; /** One element in a parsed markup tree. `line` is 0-based within the parsed region. */ export interface MarkupNode { tag: string; attrs: string; line: number; parent: MarkupNode | null; children: MarkupNode[]; /** A `${…}` expression sits among this node's direct children (Lit templates only). */ dynamicChildren: boolean; } /** The tag stream shape the product analyzer's `scanHtml` already produces. */ export interface TagToken { tag: string; kind: 'open' | 'close' | 'void'; attrs: string; /** Line as the tokenizer counted it (0- or 1-based — passed through untouched). */ line: number; /** Text between this token and the previous one held a `${…}` expression. */ dynamicBefore?: boolean; } /** * Build a tree from a token stream. Tolerant of unbalanced markup: a close * tag pops to its nearest matching open ancestor, or is ignored when none * exists. Returns the root-level nodes. */ export declare function buildMarkupTree(tokens: TagToken[]): MarkupNode[]; /** * Tokenize a chunk of markup (HTML or a Lit template region). Comments, * `