/** * Slot Contract Validator * * Detects the silent-drop class of bug filed under #595, #627, #639: Eddie * markup that uses a `slot="X"` attribute referencing a slot the component * doesn't declare. The unknown slot reaches the shadow DOM with no matching * ``, the content is dropped, and nothing in the browser * surfaces the failure. * * Scope: * - `.html` files (consumer projects, boilerplates) * - Lit `html\`...\`` template regions inside `.ts` / `.tsx` files * * Strategy: * - Find every `` opening tag * - Walk forward to its matching close tag (depth-tracked) * - Inside that range, find every immediate-child element with a * `slot="NAME"` attribute * - Look up the parent component in the index; if NAME is not in the * declared slot list, emit a finding * * The check is intentionally conservative: false positives are worse than * false negatives because validators run in tight CI loops and noisy * output gets ignored. Components missing from the index are skipped * (rather than flagged as unknown), and the regex is forgiving about * whitespace and quote style. */ import type { ComponentEntry, HealthIssue } from '../types.js'; interface ComponentLookup { getComponent(tagName: string): ComponentEntry | undefined; } export declare class SlotContractValidator { private readonly index; constructor(index: ComponentLookup); /** * Validate a single file for slot-contract violations. * Returns an empty array for files we don't scan (e.g. .scss). */ validateFile(filePath: string): Promise; /** * Scan one chunk of markup for slot-contract violations. * `startLine` is the 0-based line offset of the chunk within the file — * issue line numbers are reported relative to the file, not the chunk. */ private scanRegion; /** * Look up the component, then check the `slot="NAME"` attribute on each of * its **immediate children**. Emit a finding for each NAME that the * component doesn't declare. * * Scoping to immediate children is the whole correctness story here. The * `slot` attribute binds a child to a slot on its *direct* parent's shadow * root — a `slot="footer"` on an `` inside an `` is a * contract between the button and the *card*, and says nothing about the * `ed-section` / `ed-grid-item` / `ed-main` that happen to be ancestors. * * The previous implementation ran a global `slot=` regex over the entire * descendant subtree of every `` open tag, so a single correctly-placed * `slot="footer"` was re-reported against every ancestor that lacked a * `footer` slot. On a valid page that turned 6 legitimate slot usages into * 33 false positives (eddie-design-system #1015), which buries any real * invented-slot bug in noise. Walking only depth-0 children fixes it: each * `slot=` attribute is now judged by exactly one component — its real parent. */ private scanInner; /** * Yield the immediate (depth-0) child elements of a chunk of inner markup, * each with the `slot="NAME"` value found on its opening tag (or undefined). * Descendants are skipped by jumping past each element's matching close tag, * so a slotted grandchild never surfaces as a child of the outer element. */ private immediateChildren; } export {}; //# sourceMappingURL=slot-contract-validator.d.ts.map