stimeo-ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +163 -0
- package/dist/cable/index.d.ts +16 -16
- package/dist/cable/index.js.map +1 -1
- package/dist/controllers/accordion_controller.d.ts +3 -2
- package/dist/controllers/accordion_controller.js +10 -0
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +64 -0
- package/dist/controllers/alert_dialog_controller.js +318 -0
- package/dist/controllers/alert_dialog_controller.js.map +1 -0
- package/dist/controllers/breadcrumb_controller.d.ts +97 -10
- package/dist/controllers/breadcrumb_controller.js +225 -13
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +11 -1
- package/dist/controllers/calendar_controller.js +89 -22
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +115 -0
- package/dist/controllers/carousel_controller.js +313 -0
- package/dist/controllers/carousel_controller.js.map +1 -0
- package/dist/controllers/clipboard_controller.d.ts +72 -0
- package/dist/controllers/clipboard_controller.js +144 -0
- package/dist/controllers/clipboard_controller.js.map +1 -0
- package/dist/controllers/collapsible_controller.d.ts +70 -0
- package/dist/controllers/collapsible_controller.js +327 -0
- package/dist/controllers/collapsible_controller.js.map +1 -0
- package/dist/controllers/color_picker_controller.d.ts +87 -0
- package/dist/controllers/color_picker_controller.js +252 -0
- package/dist/controllers/color_picker_controller.js.map +1 -0
- package/dist/controllers/combobox_controller.d.ts +14 -1
- package/dist/controllers/combobox_controller.js +162 -23
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +2 -0
- package/dist/controllers/command_palette_controller.js +194 -17
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +7 -6
- package/dist/controllers/context_menu_controller.js +32 -10
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.js +8 -1
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +72 -0
- package/dist/controllers/currency_input_controller.js +147 -0
- package/dist/controllers/currency_input_controller.js.map +1 -0
- package/dist/controllers/data_grid_controller.d.ts +89 -0
- package/dist/controllers/data_grid_controller.js +246 -0
- package/dist/controllers/data_grid_controller.js.map +1 -0
- package/dist/controllers/date_range_picker_controller.d.ts +88 -0
- package/dist/controllers/date_range_picker_controller.js +441 -0
- package/dist/controllers/date_range_picker_controller.js.map +1 -0
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +57 -0
- package/dist/controllers/dismissible_controller.js +117 -0
- package/dist/controllers/dismissible_controller.js.map +1 -0
- package/dist/controllers/drawer_controller.d.ts +96 -0
- package/dist/controllers/drawer_controller.js +630 -0
- package/dist/controllers/drawer_controller.js.map +1 -0
- package/dist/controllers/dropdown_controller.d.ts +1 -2
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +73 -0
- package/dist/controllers/editable_controller.js +169 -0
- package/dist/controllers/editable_controller.js.map +1 -0
- package/dist/controllers/file_dropzone_controller.d.ts +92 -0
- package/dist/controllers/file_dropzone_controller.js +165 -0
- package/dist/controllers/file_dropzone_controller.js.map +1 -0
- package/dist/controllers/filter_controller.d.ts +60 -0
- package/dist/controllers/filter_controller.js +86 -0
- package/dist/controllers/filter_controller.js.map +1 -0
- package/dist/controllers/flash_controller.js +36 -5
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +1 -1
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.js +1 -1
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.js +6 -4
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +1 -1
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.js +67 -19
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.js +54 -11
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +9 -2
- package/dist/controllers/listbox_controller.js +257 -53
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.js +2 -2
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +54 -0
- package/dist/controllers/masonry_controller.js +142 -0
- package/dist/controllers/masonry_controller.js.map +1 -0
- package/dist/controllers/menu_controller.d.ts +29 -11
- package/dist/controllers/menu_controller.js +104 -17
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +142 -0
- package/dist/controllers/menubar_controller.js +785 -0
- package/dist/controllers/menubar_controller.js.map +1 -0
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +141 -0
- package/dist/controllers/multi_select_controller.js +755 -0
- package/dist/controllers/multi_select_controller.js.map +1 -0
- package/dist/controllers/navigation_menu_controller.d.ts +146 -0
- package/dist/controllers/navigation_menu_controller.js +511 -0
- package/dist/controllers/navigation_menu_controller.js.map +1 -0
- package/dist/controllers/nested_form_controller.d.ts +4 -5
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +1 -1
- package/dist/controllers/number_input_controller.js +7 -0
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/otp_controller.js +18 -1
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +15 -6
- package/dist/controllers/overflow_indicator_controller.js +246 -27
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +78 -19
- package/dist/controllers/overflow_menu_controller.js +381 -57
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +36 -5
- package/dist/controllers/pagination_controller.js +163 -32
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +49 -0
- package/dist/controllers/password_reveal_controller.js +117 -0
- package/dist/controllers/password_reveal_controller.js.map +1 -0
- package/dist/controllers/persist_controller.js +6 -6
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +2 -3
- package/dist/controllers/pointer_drag_controller.js +9 -1
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +1 -2
- package/dist/controllers/popover_controller.js +2 -2
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +4 -4
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.js +22 -3
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +97 -0
- package/dist/controllers/range_slider_controller.js +192 -0
- package/dist/controllers/range_slider_controller.js.map +1 -0
- package/dist/controllers/rating_controller.js +16 -2
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +52 -0
- package/dist/controllers/read_more_controller.js +238 -0
- package/dist/controllers/read_more_controller.js.map +1 -0
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +3 -1
- package/dist/controllers/resizable_controller.js +65 -1
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.js +17 -2
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.js +101 -14
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +54 -0
- package/dist/controllers/scroll_restore_controller.js +93 -0
- package/dist/controllers/scroll_restore_controller.js.map +1 -0
- package/dist/controllers/scroll_visibility_controller.d.ts +6 -3
- package/dist/controllers/scroll_visibility_controller.js +40 -6
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +64 -15
- package/dist/controllers/scrollspy_controller.js +369 -74
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +69 -0
- package/dist/controllers/separator_controller.js +96 -0
- package/dist/controllers/separator_controller.js.map +1 -0
- package/dist/controllers/sidebar_controller.d.ts +107 -0
- package/dist/controllers/sidebar_controller.js +761 -0
- package/dist/controllers/sidebar_controller.js.map +1 -0
- package/dist/controllers/skeleton_controller.js +1 -1
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +11 -1
- package/dist/controllers/slider_controller.js +32 -6
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +3 -1
- package/dist/controllers/sortable_controller.js +34 -3
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.js +1 -1
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +4 -0
- package/dist/controllers/stepper_controller.js +28 -12
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +5 -6
- package/dist/controllers/stick_to_bottom_controller.js +9 -4
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +17 -4
- package/dist/controllers/sticky_observer_controller.js +109 -20
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +2 -2
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.js +1 -0
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +13 -4
- package/dist/controllers/tabs_controller.js +26 -3
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +91 -0
- package/dist/controllers/tags_input_controller.js +295 -0
- package/dist/controllers/tags_input_controller.js.map +1 -0
- package/dist/controllers/theme_controller.d.ts +1 -1
- package/dist/controllers/theme_controller.js +42 -13
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +67 -0
- package/dist/controllers/time_picker_controller.js +231 -0
- package/dist/controllers/time_picker_controller.js.map +1 -0
- package/dist/controllers/toast_controller.d.ts +5 -14
- package/dist/controllers/toast_controller.js +40 -14
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.js +23 -2
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +53 -13
- package/dist/controllers/toolbar_controller.js +230 -31
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +1 -1
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +14 -8
- package/dist/controllers/transition_controller.js +153 -38
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +135 -0
- package/dist/controllers/tree_view_controller.js +691 -0
- package/dist/controllers/tree_view_controller.js.map +1 -0
- package/dist/index.d.ts +27 -1818
- package/dist/index.js +4256 -915
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +375 -39
- package/dist/inspector/cli.js +228 -14
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +419 -48
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +26 -26
- package/dist/inspector/manifest.json +1054 -127
- package/package.json +5 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/inspector/erb.ts","../../src/inspector/extract.ts","../../src/inspector/html_parser.ts","../../src/inspector/types.ts","../../src/inspector/check.ts","../../src/inspector/examples.ts","../../src/inspector/files.ts","../../src/inspector/manifest_io.ts","../../src/inspector/cli.ts"],"names":["j","readFileSync","manifest"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Neutralizes ERB so the HTML parser only ever sees static markup.\n *\n * Every ERB tag — `<% %>`, `<%= %>`, `<%# %>`, plus the whitespace-trimming\n * variants `<%- -%>` — is replaced with spaces. Newlines inside the tag are\n * preserved so that 1-based line/column positions used in diagnostics line up\n * with the original source.\n *\n * Because ERB is blanked rather than interpreted, dynamically-generated markup\n * is naturally excluded from checking: a dynamic identifier such as\n * `data-controller=\"<%= id %>\"` collapses to an empty attribute value and a\n * dynamic attribute name such as `data-<%= x %>-target` no longer matches the\n * `stimeo--*` patterns. This is the intended \"dynamic attributes are out of\n * scope\" behavior.\n *\n * @param source - Raw HTML/ERB source.\n * @returns The source with all ERB tags replaced by position-preserving spaces.\n */\nexport function neutralizeErb(source: string): string {\n return source.replace(/<%[\\s\\S]*?%>/g, (match) => match.replace(/[^\\n]/g, \" \"));\n}\n","/**\n * Pure helpers for recognizing `stimeo--*` attributes within parsed markup.\n *\n * These functions know nothing about files or the manifest — they only decode\n * Stimulus's attribute conventions, scoped strictly to the `stimeo--`\n * namespace so a consumer's own controllers are never inspected.\n */\n\nconst NAMESPACE_PREFIX = \"stimeo--\";\n\n/**\n * Converts a Stimulus value name to its attribute token, mirroring Stimulus's\n * own dasherize (e.g. `rootMargin` → `root-margin`).\n */\nexport function dasherize(value: string): string {\n return value.replace(/([A-Z])/g, (_match, char: string) => `-${char.toLowerCase()}`);\n}\n\n/** Extracts the `stimeo--*` identifiers listed in a `data-controller` value.\n * Duplicates are collapsed (Stimulus connects a repeated identifier once), which\n * keeps downstream scope-based diagnostics from being reported multiple times. */\nexport function controllerIdentifiers(dataControllerValue: string): string[] {\n const seen = new Set<string>();\n for (const token of dataControllerValue.split(/\\s+/)) {\n if (token.startsWith(NAMESPACE_PREFIX)) seen.add(token);\n }\n return [...seen];\n}\n\n/**\n * If `attrName` is an Stimeo target attribute (`data-{identifier}-target`),\n * returns the controller identifier; otherwise `null`.\n */\nexport function parseTargetAttr(attrName: string): string | null {\n const match = /^data-(stimeo--[a-z0-9][a-z0-9-]*)-target$/.exec(attrName);\n return match?.[1] ?? null;\n}\n\n/** Result of decoding a `data-{identifier}-{value}-value` attribute. */\nexport interface ParsedValueAttr {\n /** Resolved identifier, or `null` when it matches no known controller. */\n readonly identifier: string | null;\n /** The dasherized value token (e.g. `root-margin`), best-effort when unresolved. */\n readonly valueToken: string;\n}\n\n/**\n * Decodes an Stimeo value attribute (`data-{identifier}-{value}-value`).\n *\n * Identifiers may themselves contain hyphens (e.g. `stimeo--command-palette`),\n * so the boundary between identifier and value name is ambiguous from the\n * attribute name alone. We disambiguate against the set of known identifiers,\n * preferring the longest match.\n *\n * @param attrName - The lowercased attribute name.\n * @param knownIdentifiers - All identifiers present in the manifest.\n * @returns The decoded attribute, or `null` if it is not an Stimeo value attr.\n */\nexport function parseValueAttr(\n attrName: string,\n knownIdentifiers: readonly string[],\n): ParsedValueAttr | null {\n const match = /^data-(stimeo--[a-z0-9-]+)-value$/.exec(attrName);\n if (!match) return null;\n const inner = match[1] ?? \"\"; // identifier + \"-\" + valueToken\n\n let best: { identifier: string; valueToken: string } | null = null;\n for (const id of knownIdentifiers) {\n if (inner.startsWith(`${id}-`)) {\n const valueToken = inner.slice(id.length + 1);\n if (valueToken.length > 0 && (!best || id.length > best.identifier.length)) {\n best = { identifier: id, valueToken };\n }\n }\n }\n if (best) return best;\n\n // Unknown identifier: best-effort split at the first segment after the prefix.\n const rest = inner.slice(NAMESPACE_PREFIX.length);\n const dash = rest.indexOf(\"-\");\n const identifierGuess = dash === -1 ? inner : `${NAMESPACE_PREFIX}${rest.slice(0, dash)}`;\n const valueGuess = dash === -1 ? \"\" : rest.slice(dash + 1);\n return { identifier: null, valueToken: valueGuess || identifierGuess };\n}\n\n/** An Stimeo `data-action` descriptor decoded into its controller and method. */\nexport interface ActionDescriptor {\n /** The `stimeo--*` controller identifier (e.g. `stimeo--menu`). */\n readonly identifier: string;\n /** The action method name after `#` (e.g. `toggle`), or `\"\"` if absent. */\n readonly method: string;\n}\n\n/**\n * Decodes the Stimeo `data-action` descriptors in an attribute value, e.g.\n * `click->stimeo--menu#toggle keydown->stimeo--menu#onItemKeydown` yields one\n * entry per descriptor. Non-`stimeo--` controllers are skipped (their action\n * surface is out of scope). The method name is read up to the first action\n * option (`:prevent`, `:stop`, …), mirroring Stimulus's descriptor grammar.\n */\nexport function actionDescriptors(dataActionValue: string): ActionDescriptor[] {\n const descriptors: ActionDescriptor[] = [];\n for (const descriptor of dataActionValue.split(/\\s+/)) {\n const hash = descriptor.indexOf(\"#\");\n if (hash === -1) continue;\n let lhs = descriptor.slice(0, hash);\n const arrow = lhs.indexOf(\"->\");\n if (arrow !== -1) lhs = lhs.slice(arrow + 2);\n if (!lhs.startsWith(NAMESPACE_PREFIX)) continue;\n const method = /^[a-zA-Z_$][\\w$]*/.exec(descriptor.slice(hash + 1))?.[0] ?? \"\";\n descriptors.push({ identifier: lhs, method });\n }\n return descriptors;\n}\n\n/**\n * Extracts the `stimeo--*` controller identifiers referenced in a\n * `data-action` value, e.g. `click->stimeo--menu#toggle` yields\n * `[\"stimeo--menu\"]`. Convenience wrapper over {@link actionDescriptors}.\n */\nexport function actionIdentifiers(dataActionValue: string): string[] {\n return actionDescriptors(dataActionValue).map((d) => d.identifier);\n}\n\n/** Whether an attribute name belongs to the Stimeo namespace. */\nexport function isStimeoDataAttr(attrName: string): boolean {\n return attrName.startsWith(`data-${NAMESPACE_PREFIX}`);\n}\n","/**\n * A minimal, dependency-free HTML tokenizer/tree builder.\n *\n * The Inspector deliberately ships **zero runtime dependencies** beyond the\n * Stimulus peer (see project invariants), so rather than pull in a DOM library\n * we build just enough of a tree to answer the only questions the checker asks:\n * \"which `stimeo--*` attributes exist, where, and inside which controller\n * scope?\". The parser is intentionally lenient — real-world ERB output has\n * unclosed tags and stray markup — and never throws.\n *\n * It is **not** a spec-compliant HTML parser and should not be used for\n * anything beyond static attribute inspection.\n */\n\n/** A parsed attribute, with the source position of its name. */\nexport interface ParsedAttr {\n /** Lowercased attribute name (HTML attribute names are case-insensitive). */\n readonly name: string;\n /** Attribute value (without surrounding quotes); empty for boolean attrs. */\n readonly value: string;\n /** 1-based line of the attribute name. */\n readonly line: number;\n /** 1-based column of the attribute name. */\n readonly column: number;\n /**\n * Absolute source offset where the value text begins (inside the quotes);\n * absent for boolean attributes. ERB neutralization preserves offsets, so a\n * consumer can map the range back onto the *raw* source — this is how the\n * checker tells an authored value from a dynamically-generated one.\n */\n readonly valueStart?: number;\n /** Absolute source offset just past the value text; see {@link valueStart}. */\n readonly valueEnd?: number;\n}\n\n/** An element node in the lenient tree. */\nexport interface ElementNode {\n /** Lowercased tag name; the synthetic root uses `#root`. */\n readonly tag: string;\n readonly attrs: readonly ParsedAttr[];\n readonly children: ElementNode[];\n parent: ElementNode | null;\n /** 1-based line of the tag's `<`. */\n readonly line: number;\n /** 1-based column of the tag's `<`. */\n readonly column: number;\n}\n\n/** Elements that never have children and so are never pushed onto the stack. */\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\n/** Elements whose content is raw text (no nested elements to parse). */\nconst RAW_TEXT_ELEMENTS = new Set([\"script\", \"style\", \"textarea\", \"title\"]);\n\nconst WHITESPACE = new Set([\" \", \"\\t\", \"\\n\", \"\\r\", \"\\f\"]);\n\n/** Maps absolute string offsets to 1-based line/column positions. */\nclass PositionIndex {\n readonly #lineStarts: number[] = [0];\n\n constructor(source: string) {\n for (let i = 0; i < source.length; i++) {\n if (source[i] === \"\\n\") this.#lineStarts.push(i + 1);\n }\n }\n\n at(offset: number): { line: number; column: number } {\n // Binary search for the last line start that is <= offset.\n let lo = 0;\n let hi = this.#lineStarts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((this.#lineStarts[mid] ?? 0) <= offset) lo = mid;\n else hi = mid - 1;\n }\n return { line: lo + 1, column: offset - (this.#lineStarts[lo] ?? 0) + 1 };\n }\n}\n\n/**\n * Parses HTML (already ERB-neutralized) into a lenient element tree.\n *\n * @param source - HTML source to parse.\n * @returns The synthetic `#root` node whose children are the top-level elements.\n */\nexport function parseHtml(source: string): ElementNode {\n const pos = new PositionIndex(source);\n const len = source.length;\n /** Bounds-safe character access (out of range yields an empty string). */\n const ch = (k: number): string => (k >= 0 && k < len ? (source[k] as string) : \"\");\n\n const root: ElementNode = {\n tag: \"#root\",\n attrs: [],\n children: [],\n parent: null,\n line: 1,\n column: 1,\n };\n const stack: ElementNode[] = [root];\n let i = 0;\n\n const top = (): ElementNode => stack[stack.length - 1] as ElementNode;\n\n while (i < len) {\n if (ch(i) !== \"<\") {\n i++;\n continue;\n }\n\n const next = ch(i + 1);\n\n // Comment: <!-- ... -->\n if (source.startsWith(\"<!--\", i)) {\n const end = source.indexOf(\"-->\", i + 4);\n i = end === -1 ? len : end + 3;\n continue;\n }\n // Markup declaration (<!DOCTYPE ...>) or processing instruction (<? ... ?>).\n if (next === \"!\" || next === \"?\") {\n const end = source.indexOf(\">\", i);\n i = end === -1 ? len : end + 1;\n continue;\n }\n // End tag: </name>\n if (next === \"/\") {\n let j = i + 2;\n let name = \"\";\n while (j < len && ch(j) !== \">\" && !WHITESPACE.has(ch(j))) {\n name += ch(j);\n j++;\n }\n const end = source.indexOf(\">\", j);\n i = end === -1 ? len : end + 1;\n closeTag(stack, name.toLowerCase());\n continue;\n }\n // Not a tag start (e.g. a stray \"<\"); treat as text.\n if (!/[a-zA-Z]/.test(next)) {\n i++;\n continue;\n }\n\n // Start tag.\n const tagStart = i;\n let j = i + 1;\n let tagName = \"\";\n while (j < len && !WHITESPACE.has(ch(j)) && ch(j) !== \">\" && ch(j) !== \"/\") {\n tagName += ch(j);\n j++;\n }\n const lowerTag = tagName.toLowerCase();\n const attrs: ParsedAttr[] = [];\n\n // Parse attributes until the tag closes.\n let selfClosing = false;\n while (j < len) {\n while (j < len && WHITESPACE.has(ch(j))) j++;\n if (j >= len) break;\n if (ch(j) === \">\") {\n j++;\n break;\n }\n if (ch(j) === \"/\") {\n selfClosing = true;\n j++;\n continue;\n }\n\n // Attribute name.\n const nameStart = j;\n let attrName = \"\";\n while (j < len && !WHITESPACE.has(ch(j)) && ch(j) !== \"=\" && ch(j) !== \">\" && ch(j) !== \"/\") {\n attrName += ch(j);\n j++;\n }\n\n let attrValue = \"\";\n let valueStart: number | undefined;\n let valueEnd: number | undefined;\n // Optional value.\n let k = j;\n while (k < len && WHITESPACE.has(ch(k))) k++;\n if (ch(k) === \"=\") {\n k++;\n while (k < len && WHITESPACE.has(ch(k))) k++;\n const quote = ch(k);\n if (quote === '\"' || quote === \"'\") {\n k++;\n const valStart = k;\n while (k < len && ch(k) !== quote) k++;\n attrValue = source.slice(valStart, k);\n valueStart = valStart;\n valueEnd = k;\n k++; // skip closing quote\n } else {\n const valStart = k;\n while (k < len && !WHITESPACE.has(ch(k)) && ch(k) !== \">\") k++;\n attrValue = source.slice(valStart, k);\n valueStart = valStart;\n valueEnd = k;\n }\n j = k;\n }\n\n if (attrName.length > 0) {\n const p = pos.at(nameStart);\n attrs.push({\n name: attrName.toLowerCase(),\n value: attrValue,\n line: p.line,\n column: p.column,\n valueStart,\n valueEnd,\n });\n }\n }\n\n const startPos = pos.at(tagStart);\n const node: ElementNode = {\n tag: lowerTag,\n attrs,\n children: [],\n parent: top(),\n line: startPos.line,\n column: startPos.column,\n };\n top().children.push(node);\n\n i = j;\n\n if (selfClosing || VOID_ELEMENTS.has(lowerTag)) {\n continue;\n }\n\n if (RAW_TEXT_ELEMENTS.has(lowerTag)) {\n // Skip raw-text content so `<` inside scripts/styles is not parsed as markup.\n const closeNeedle = `</${lowerTag}`;\n const idx = source.toLowerCase().indexOf(closeNeedle, i);\n if (idx === -1) {\n i = len;\n } else {\n const gt = source.indexOf(\">\", idx);\n i = gt === -1 ? len : gt + 1;\n }\n continue;\n }\n\n stack.push(node);\n }\n\n return root;\n}\n\n/** Pops the stack down to (and including) the nearest matching open tag. */\nfunction closeTag(stack: ElementNode[], name: string): void {\n for (let depth = stack.length - 1; depth >= 1; depth--) {\n if (stack[depth]?.tag === name) {\n stack.length = depth;\n return;\n }\n }\n // No matching open tag — ignore the stray end tag.\n}\n\n/** Depth-first walk over every element node (excluding the synthetic root). */\nexport function walk(root: ElementNode, visit: (node: ElementNode) => void): void {\n for (const child of root.children) {\n visit(child);\n walk(child, visit);\n }\n}\n","/**\n * Shared types for the Stimeo Inspector CLI (`stimeo check`).\n *\n * The Inspector statically checks HTML/ERB against a *manifest* describing the\n * official `stimeo--` controllers. The same engine powers both the project's own\n * contract checks (e.g. `stimeo check app/views`) and the\n * user-facing product feature; it is therefore intentionally input-path\n * agnostic.\n */\n\n/**\n * Per-controller manifest entry.\n *\n * `targets` and `values` are reflected from the controller class\n * (`static targets` / `static values`). `actions` and `events` are reflected\n * from co-located `static actions` / `static events` declarations — Stimulus\n * keeps no registry of action methods, and TypeScript `private` survives on the\n * prototype, so the public action/event surface cannot be told apart from\n * internal helpers by reflection alone; it must be declared explicitly in the\n * implementation. `requiredTargets` is a hand-written structure rule (Stimulus\n * reflection cannot express \"required\").\n */\nexport interface ControllerManifest {\n /** Target names declared via `static targets`. */\n readonly targets: readonly string[];\n /** Value names (camelCase) declared via `static values`. */\n readonly values: readonly string[];\n /**\n * Public action method names declared via `static actions`, wired by\n * consumers as `data-action=\"…-><identifier>#<action>\"`.\n */\n readonly actions: readonly string[];\n /**\n * Logical event names declared via `static events`, dispatched as\n * `<identifier>:<event>` (Stimulus `this.dispatch(\"<event>\")`).\n */\n readonly events: readonly string[];\n /** Targets that must be present at least once inside the controller scope. */\n readonly requiredTargets: readonly string[];\n /**\n * Accessibility requirements the *consumer's markup* must satisfy (stage 3):\n * ARIA attributes the controller does **not** set at runtime and therefore\n * relies on the author to provide (e.g. a dialog's `role`/`aria-modal`/name).\n * Attributes the controller manages itself (e.g. tabs' `aria-selected`) are\n * deliberately excluded — requiring them would be noise.\n */\n readonly a11y: readonly A11yRequirement[];\n /**\n * Keyboard prerequisites (stage 3, schema v4): targets whose documented\n * contract makes the *author* responsible for focusability — the controller\n * moves focus (or relies on the Tab order) but never writes `tabindex` for\n * them. Each listed target must be natively focusable or carry `tabindex`.\n * Targets whose controller initializes a roving tabindex on connect (tabs,\n * toolbar, radio group, …) are deliberately excluded.\n */\n readonly keyboard: readonly KeyboardRequirement[];\n /**\n * Author-futile attributes (stage 3, schema v4): ARIA the controller\n * recomputes wholesale at runtime, where an authored value can neither\n * survive nor serve as pre-connect initial state (e.g. a combobox input's\n * `aria-activedescendant`). Authoring one is reported as a *warning*.\n * Attributes whose authored value is a legitimate initial (`aria-expanded`,\n * `aria-checked`, `aria-valuenow`, …) are deliberately excluded.\n */\n readonly managedAria: readonly ManagedAriaRule[];\n /**\n * Conditional cross-controller composition rules (stage 3, schema v5):\n * value-alignment contracts between this controller and a co-located\n * companion (e.g. sortable's sort axis vs roving's `orientation`). Prose-only\n * before v5, where a dropped or misaligned value silently broke keyboard\n * interaction while `stimeo check` passed.\n */\n readonly compositions: readonly CompositionRule[];\n}\n\n/**\n * A single accessibility requirement on a controller's markup (Inspector\n * stage 3). At least one of {@link attrs} must be present on the\n * {@link target} element; when {@link values} is given, the present\n * attribute's value must be one of them. {@link or} widens the requirement\n * with alternative attribute/value groups — the requirement is satisfied when\n * *any* group is (schema v4; e.g. `role=\"status\"` **or** `aria-live`).\n */\nexport interface A11yRequirement {\n /**\n * Target name the requirement applies to; the empty string `\"\"` means the\n * controller's own scope element (the `data-controller` node).\n */\n readonly target: string;\n /**\n * Candidate attribute names — at least one must be present. A list expresses\n * \"any of\" (e.g. `aria-labelledby` *or* `aria-label` for an accessible name).\n */\n readonly attrs: readonly string[];\n /** Allowed values for the matched attribute; omit to accept any value. */\n readonly values?: readonly string[];\n /**\n * Alternative attribute groups, each with its **own** allowed-value set —\n * something `attrs` alone cannot express (its `values` apply to every listed\n * attribute). A present attribute with a wrong value is still reported even\n * when another group is satisfied: an invalid authored value is an error in\n * its own right (e.g. `aria-live=\"off\"` silencing a satisfied `role=\"status\"`).\n */\n readonly or?: readonly A11yAlternative[];\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/** One alternative attribute group of an {@link A11yRequirement} (`or`). */\nexport interface A11yAlternative {\n /** Candidate attribute names — at least one must be present. */\n readonly attrs: readonly string[];\n /** Allowed values for the matched attribute; omit to accept any value. */\n readonly values?: readonly string[];\n}\n\n/**\n * A keyboard prerequisite (stage 3, schema v4): every present element of\n * {@link target} must be reachable by keyboard. What \"reachable\" means depends\n * on how the controller drives focus, expressed by {@link reach}:\n *\n * - `\"tab\"` (Tab stop): the element is a steady tab stop the user reaches with\n * Tab, so it must be natively tab-focusable (`button`, `input` except\n * `type=\"hidden\"`, `select`, `textarea`, `summary`, `a[href]`, `area[href]`,\n * or `contenteditable`) **or** carry `tabindex=\"0\"` (any non-negative value).\n * A `tabindex=\"-1\"` removes it from the Tab order and therefore **fails** —\n * this is the case a mere \"has tabindex\" presence check would miss.\n * - `\"focus\"` (roving / programmatic): the controller moves focus with\n * `element.focus()`, so the element only has to be focusable *at all* —\n * natively focusable **or** carrying any valid `tabindex` (including the\n * roving `-1`).\n *\n * Only the per-element floor is checked; the roving set-level invariant\n * (\"exactly one item is `tabindex=\"0\"`\") is runtime state owned by the\n * controller and deliberately out of scope.\n */\nexport interface KeyboardRequirement {\n /** Target name the requirement applies to (never the scope element). */\n readonly target: string;\n /**\n * How the user reaches the target. Defaults to `\"tab\"` (the common case —\n * most operation points are steady Tab stops); set `\"focus\"` only for\n * targets the controller roves via programmatic focus.\n */\n readonly reach?: \"tab\" | \"focus\";\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * An author-futile attribute rule (stage 3, schema v4): authoring any of\n * {@link attrs} on the {@link target} element draws a `managed-aria`\n * **warning** — the controller recomputes the attribute wholesale, so the\n * authored value is dead weight that misleads readers of the markup.\n */\nexport interface ManagedAriaRule {\n /**\n * Target name the rule applies to; the empty string `\"\"` means the\n * controller's own scope element.\n */\n readonly target: string;\n /** Attribute names the controller owns outright. */\n readonly attrs: readonly string[];\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * A conditional cross-controller composition rule (stage 3, schema v5): when a\n * companion controller is co-located on one of the host's elements, one of the\n * companion's values must align with a value of the host. The rule fires only\n * when {@link coController} is actually declared there — composition itself\n * stays optional (whether to compose is the author's call; the rule only\n * guards *how*).\n *\n * Both sides are compared by their **effective** value — the authored\n * attribute, or the declared default when the attribute is absent — because\n * the misalignments these rules exist for are default asymmetries (e.g.\n * sortable defaults its `orientation` to `vertical` while roving defaults to\n * `horizontal`, so a bare composition is silently broken). The defaults are\n * duplicated here from the controllers' `static values`; a manifest test\n * guards them against drift.\n */\nexport interface CompositionRule {\n /**\n * Host target whose element hosts the companion; the empty string `\"\"`\n * means the controller's own scope element.\n */\n readonly target: string;\n /**\n * Check the scope element when {@link target} is absent — for optional\n * container targets whose documented fallback is the scope element itself\n * (e.g. sortable's `list`).\n */\n readonly fallbackToScope?: boolean;\n /** Companion controller identifier expected in the element's `data-controller`. */\n readonly coController: string;\n /**\n * Condition on the host's own value (read from the scope element); omit for\n * unconditional rules. The rule applies only when the host's effective\n * value is one of `equals`.\n */\n readonly when?: {\n /** Host value name (camelCase, as declared in `static values`). */\n readonly value: string;\n /** Effective host values that arm the rule. */\n readonly equals: readonly string[];\n /** The host value's declared default, used when the attribute is absent. */\n readonly default: string;\n };\n /** Requirement on the companion's value (read from the companion's element). */\n readonly require: {\n /** Companion value name (camelCase, as declared in `static values`). */\n readonly value: string;\n /**\n * Allowed effective values, **ordered**: the first entry is the canonical\n * alignment and feeds the machine fix when an authored value is wrong.\n */\n readonly oneOf: readonly string[];\n /** The companion value's declared default, used when the attribute is absent. */\n readonly default: string;\n };\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * The bundled manifest. `schemaVersion` tracks the manifest *format*;\n * `packageVersion` tracks the `stimeo-ui` release it was generated from so a\n * consumer can confirm the check matches their installed version.\n */\nexport interface Manifest {\n readonly schemaVersion: number;\n readonly packageVersion: string;\n /** Keyed by controller identifier, e.g. `stimeo--menu`. */\n readonly controllers: Readonly<Record<string, ControllerManifest>>;\n}\n\n/** Hand-written structure rules, merged into the reflected manifest. */\nexport type StructureRules = Readonly<\n Record<string, { readonly requiredTargets?: readonly string[] }>\n>;\n\n/** Hand-written accessibility rules (stage 3), merged into the manifest. */\nexport type A11yRules = Readonly<Record<string, readonly A11yRequirement[]>>;\n\n/** Hand-written keyboard prerequisites (stage 3), merged into the manifest. */\nexport type KeyboardRules = Readonly<Record<string, readonly KeyboardRequirement[]>>;\n\n/** Hand-written author-futile attribute rules, merged into the manifest. */\nexport type ManagedAriaRules = Readonly<Record<string, readonly ManagedAriaRule[]>>;\n\n/** Hand-written composition rules (stage 3), merged into the manifest. */\nexport type CompositionRules = Readonly<Record<string, readonly CompositionRule[]>>;\n\n/** Severity of a diagnostic. Only `error` affects the process exit code. */\nexport type DiagnosticSeverity = \"error\" | \"warning\";\n\n/**\n * Stable identifiers for the kinds of problems the Inspector reports. Useful\n * for testing, machine-readable output, and `data-stimeo-ignore` suppression\n * lists (which is why the set also exists as a runtime array).\n */\nexport const DIAGNOSTIC_CODES = [\n \"unknown-controller\",\n \"unknown-target\",\n \"unknown-value\",\n \"unknown-action-controller\",\n \"unknown-action-method\",\n \"orphan-target\",\n \"missing-required-target\",\n \"missing-aria\",\n \"invalid-aria-value\",\n \"keyboard-inaccessible\",\n \"unresolved-idref\",\n \"managed-aria\",\n \"composition-mismatch\",\n \"unknown-ignore-code\",\n] as const;\n\n/** See {@link DIAGNOSTIC_CODES}. */\nexport type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];\n\n/**\n * A machine-applicable fix for a diagnostic: replace the source text in\n * `[start, end)` with `text`. Only emitted when the engine can compute the\n * exact range with confidence — a typo'd token inside an attribute value, or\n * a single-valued ARIA correction. Editors surface it as a quick fix; the\n * human-readable `suggestion` stays the fallback for everything else.\n */\nexport interface DiagnosticFix {\n /** Absolute source offset where the replacement starts. */\n readonly start: number;\n /** Absolute source offset just past the replaced text. */\n readonly end: number;\n /** Replacement text. */\n readonly text: string;\n /** Short imperative label for editor UI, e.g. `Replace with \"stimeo--menu\"`. */\n readonly title: string;\n}\n\n/** A single problem found in a source file. */\nexport interface Diagnostic {\n readonly code: DiagnosticCode;\n readonly severity: DiagnosticSeverity;\n readonly message: string;\n /** 1-based line where the problem was detected. */\n readonly line: number;\n /** 1-based column where the problem was detected. */\n readonly column: number;\n /**\n * Length in source characters of the anchored token starting at `column` —\n * the attribute name for attribute-anchored diagnostics, or the opening\n * `<tag` for element-anchored ones. Lets editors underline the exact token\n * instead of guessing a word boundary. Optional so hand-built or historical\n * reports without it stay valid; consumers should fall back to `1`.\n */\n readonly length?: number;\n /**\n * Optional fix suggestion (stage 4): the corrected attribute to add, or the\n * nearest known name for a likely typo. Rendered on its own line by the CLI.\n */\n readonly suggestion?: string;\n /** Machine-applicable replacement (stage 4), when one can be computed safely. */\n readonly fix?: DiagnosticFix;\n}\n\n/** Diagnostics grouped by the file they came from. */\nexport interface FileReport {\n readonly file: string;\n readonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * Machine-readable result of `stimeo check --json`: the structured counterpart\n * of the human report, for editor tooling and CI. `files` lists only sources\n * that produced diagnostics; `ok` is\n * true when no error-severity diagnostic was found (mirrors the exit code).\n */\nexport interface CheckReport {\n /** True when no error-severity diagnostics were found. */\n readonly ok: boolean;\n /** Total number of HTML/ERB files scanned. */\n readonly checkedFiles: number;\n /** Count of error-severity diagnostics across all files. */\n readonly errorCount: number;\n /** Count of warning-severity diagnostics across all files. */\n readonly warningCount: number;\n /** Per-file reports, limited to files that produced at least one diagnostic. */\n readonly files: readonly FileReport[];\n}\n","import { neutralizeErb } from \"./erb\";\nimport {\n actionDescriptors,\n controllerIdentifiers,\n dasherize,\n isStimeoDataAttr,\n parseTargetAttr,\n parseValueAttr,\n} from \"./extract\";\nimport { type ElementNode, type ParsedAttr, parseHtml, walk } from \"./html_parser\";\nimport {\n type A11yAlternative,\n type A11yRequirement,\n DIAGNOSTIC_CODES,\n type Diagnostic,\n type DiagnosticCode,\n type DiagnosticFix,\n type DiagnosticSeverity,\n type Manifest,\n} from \"./types\";\n\n/**\n * The core Inspector engine: checks a single HTML/ERB source string against the\n * manifest and returns diagnostics. It is **input-path agnostic** — the same\n * function backs both the project's own contract checks and the user-facing CLI.\n *\n * The check runs in staged passes:\n * - **Stage 1 (names/spelling):** every `stimeo--*` controller, target, value,\n * and `data-action` controller **and method** must exist in the manifest.\n * - **Stage 2 (structure):** required targets must be present within their\n * controller scope, and targets must have an owning controller.\n * - **Stage 3 (accessibility):** ARIA the controller relies on but does not set\n * itself (e.g. a dialog's `role`/`aria-modal`/name) must be present on the\n * relevant target, with the expected value (alternative groups via `or`).\n * Three sibling passes extend it: **keyboard prerequisites** (declared\n * targets must be focusable), **managed-aria** (author-futile attributes the\n * controller owns draw warnings), and **idref resolution** (ARIA reference\n * attributes on scope/target elements must point at an id declared in the\n * same file — a *warning*, since a reference may legitimately cross a\n * partial boundary the checker cannot see).\n * - **Stage 4 (fix suggestions):** diagnostics carry a `suggestion` — the\n * nearest known name for a likely typo, or the exact ARIA to add.\n *\n * Any element may opt out via {@link IGNORE_ATTR} (`data-stimeo-ignore`): an\n * empty value suppresses every diagnostic anchored at the element or its\n * descendants; a whitespace-separated {@link DiagnosticCode} list narrows the\n * suppression to those codes. Unknown codes in the list are themselves\n * reported (`unknown-ignore-code`, never suppressible).\n *\n * @remarks\n * Scope is resolved within a single source string. A controller and its targets\n * split across separate Rails partials cannot be correlated, so stage-2 checks\n * assume self-contained markup (Stimeo's recommended demo/partial structure).\n * Server-rendered **fragments** — markup a controller fetches and appends at\n * runtime (Turbo Streams, incrementally loaded list pages) — are the\n * legitimate exception:\n * declare the runtime host with {@link FRAGMENT_ATTR} on the fragment root and\n * `orphan-target` is suppressed for that identifier (names are still checked).\n * ERB is neutralized first, so dynamically-generated attributes are skipped.\n *\n * @param source - Raw HTML/ERB source.\n * @param manifest - The bundled controller manifest to check against.\n * @returns Diagnostics sorted by line then column.\n */\nexport function checkSource(source: string, manifest: Manifest): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const tree = parseHtml(neutralizeErb(source));\n const known = manifest.controllers;\n const knownIdentifiers = Object.keys(known);\n\n /** `[start, end)` offsets of every ERB tag in the raw source. */\n const erbRanges = [...source.matchAll(/<%[\\s\\S]*?%>/g)].map(\n (m) => [m.index ?? 0, (m.index ?? 0) + m[0].length] as const,\n );\n\n /**\n * Whether the attribute's value text was (even partially) ERB-generated.\n * Neutralization preserves offsets, so the parser's value range maps 1:1\n * onto the raw source.\n */\n const isDynamicValue = (attr: ParsedAttr): boolean => {\n const { valueStart, valueEnd } = attr;\n if (valueStart === undefined || valueEnd === undefined) return false;\n return erbRanges.some(([start, end]) => start < valueEnd && end > valueStart);\n };\n\n /** True when `node` or an ancestor opts out of `code` via the ignore attr. */\n const suppressed = (node: ElementNode, code: DiagnosticCode): boolean => {\n if (code === \"unknown-ignore-code\") return false; // meta-diagnostic: never suppressible\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const ignore = current.attrs.find((a) => a.name === IGNORE_ATTR);\n if (ignore) {\n const codes = ignore.value.trim();\n if (codes.length === 0 || codes.split(/\\s+/).includes(code)) return true;\n }\n current = current.parent;\n }\n return false;\n };\n\n /** Suppression-aware diagnostic sink; `owner` anchors the ignore lookup. */\n const report: Reporter = (owner, code, severity, message, at, suggestion, fix): void => {\n if (!suppressed(owner, code)) push(diagnostics, code, severity, message, at, suggestion, fix);\n };\n\n /** Controller scope registrations: a node declaring `data-controller`. */\n const scopes: Array<{ node: ElementNode; identifier: string }> = [];\n /** Target names found within each scope, keyed by scope node then identifier. */\n const presence = new Map<ElementNode, Map<string, Set<string>>>();\n /** Target *elements* per scope/identifier/target name, for stage-3 ARIA checks. */\n const targetNodes = new Map<ElementNode, Map<string, Map<string, ElementNode[]>>>();\n\n const recordPresence = (owner: ElementNode, identifier: string, target: string): void => {\n let byId = presence.get(owner);\n if (!byId) {\n byId = new Map();\n presence.set(owner, byId);\n }\n let set = byId.get(identifier);\n if (!set) {\n set = new Set();\n byId.set(identifier, set);\n }\n set.add(target);\n };\n\n const recordTargetNode = (\n owner: ElementNode,\n identifier: string,\n target: string,\n el: ElementNode,\n ): void => {\n let byId = targetNodes.get(owner);\n if (!byId) {\n byId = new Map();\n targetNodes.set(owner, byId);\n }\n let byName = byId.get(identifier);\n if (!byName) {\n byName = new Map();\n byId.set(identifier, byName);\n }\n const found = byName.get(target);\n if (found) found.push(el);\n else byName.set(target, [el]);\n };\n\n walk(tree, (node) => {\n for (const attr of node.attrs) {\n // --- suppression declaration: data-stimeo-ignore ---------------------\n if (attr.name === IGNORE_ATTR) {\n // Spell-check the code list so a typo'd suppression cannot silently\n // fail open. Reported directly: this meta-diagnostic is unsuppressible.\n for (const token of attr.value.split(/\\s+/).filter((t) => t.length > 0)) {\n if (!(DIAGNOSTIC_CODES as readonly string[]).includes(token)) {\n const best = nearestName(token, DIAGNOSTIC_CODES);\n push(\n diagnostics,\n \"unknown-ignore-code\",\n \"warning\",\n `Unknown diagnostic code \"${token}\" in ${IGNORE_ATTR}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, token, best),\n );\n }\n }\n continue;\n }\n\n // --- fragment declaration: data-stimeo-fragment ----------------------\n if (attr.name === FRAGMENT_ATTR) {\n const identifiers = attr.value.split(/\\s+/).filter((token) => token.length > 0);\n if (identifiers.length === 0) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `\"${FRAGMENT_ATTR}\" must name the fragment's runtime host controller(s).`,\n attr,\n );\n }\n for (const identifier of identifiers) {\n if (!(identifier in known)) {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Fragment declaration references unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n }\n }\n continue;\n }\n\n // --- data-controller -------------------------------------------------\n if (attr.name === \"data-controller\") {\n for (const identifier of controllerIdentifiers(attr.value)) {\n if (identifier in known) {\n scopes.push({ node, identifier });\n } else {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n }\n }\n continue;\n }\n\n // --- target attribute: data-{identifier}-target ----------------------\n const targetIdentifier = parseTargetAttr(attr.name);\n if (targetIdentifier) {\n const controller = known[targetIdentifier];\n if (!controller) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Target attribute \"${attr.name}\" references unknown Stimeo controller \"${targetIdentifier}\".`,\n attr,\n didYouMean(targetIdentifier, knownIdentifiers),\n );\n continue;\n }\n const targetName = attr.value.trim();\n if (targetName.length > 0 && !controller.targets.includes(targetName)) {\n const best = nearestName(targetName, controller.targets);\n report(\n node,\n \"unknown-target\",\n \"error\",\n `Unknown target \"${targetName}\" for \"${targetIdentifier}\". Known targets: ${list(controller.targets)}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, targetName, best),\n );\n }\n const owner = findOwner(node, targetIdentifier);\n if (owner) {\n if (targetName.length > 0) {\n recordPresence(owner, targetIdentifier, targetName);\n recordTargetNode(owner, targetIdentifier, targetName, node);\n }\n } else if (!inDeclaredFragment(node, targetIdentifier)) {\n report(\n node,\n \"orphan-target\",\n \"error\",\n `Target \"${attr.name}\" has no enclosing controller \"${targetIdentifier}\".`,\n attr,\n );\n }\n continue;\n }\n\n // --- value attribute: data-{identifier}-{value}-value ----------------\n if (isStimeoDataAttr(attr.name) && attr.name.endsWith(\"-value\")) {\n const parsed = parseValueAttr(attr.name, knownIdentifiers);\n if (parsed) {\n if (parsed.identifier === null) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Value attribute \"${attr.name}\" references unknown Stimeo controller.`,\n attr,\n );\n } else {\n const controller = known[parsed.identifier];\n const valid =\n controller?.values.some((v) => dasherize(v) === parsed.valueToken) ?? false;\n if (!valid) {\n report(\n node,\n \"unknown-value\",\n \"error\",\n `Unknown value \"${parsed.valueToken}\" for \"${parsed.identifier}\". Known values: ${list((controller?.values ?? []).map(dasherize))}.`,\n attr,\n didYouMean(parsed.valueToken, (controller?.values ?? []).map(dasherize)),\n );\n }\n }\n continue;\n }\n }\n\n // --- data-action descriptors: controller + method --------------------\n if (attr.name === \"data-action\") {\n for (const { identifier, method } of actionDescriptors(attr.value)) {\n const controller = known[identifier];\n if (!controller) {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-action-controller\",\n \"error\",\n `Action references unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n } else if (method.length > 0 && !controller.actions.includes(method)) {\n const best = nearestName(method, controller.actions);\n report(\n node,\n \"unknown-action-method\",\n \"error\",\n `Unknown action \"${method}\" for \"${identifier}\". Known actions: ${list(controller.actions)}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, method, best),\n );\n }\n }\n }\n }\n });\n\n // --- Stage 2: required targets per scope ---------------------------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n const present = presence.get(node)?.get(identifier) ?? new Set<string>();\n for (const required of controller.requiredTargets) {\n if (!present.has(required)) {\n report(\n node,\n \"missing-required-target\",\n \"error\",\n `\"${identifier}\" is missing required target \"${required}\".`,\n node,\n );\n }\n }\n }\n\n // --- Stage 3: accessibility (ARIA) per scope -----------------------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const req of controller.a11y) {\n // The root scope (\"\") is the controller element; otherwise the target's\n // own element(s). Targets that are absent are stage 2's concern, not ours\n // — we only judge accessibility of markup that is actually present.\n const elements =\n req.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(req.target) ?? []);\n for (const el of elements) {\n checkA11y(report, el, identifier, req);\n }\n }\n }\n\n // --- Stage 3: keyboard prerequisites per scope ---------------------------\n // Declared targets whose contract makes the author responsible for\n // focusability must be natively focusable or carry tabindex/contenteditable.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const req of controller.keyboard) {\n const reach = req.reach ?? \"tab\";\n const elements = targetNodes.get(node)?.get(identifier)?.get(req.target) ?? [];\n for (const el of elements) {\n if (!isFocusable(el, reach)) {\n const problem =\n reach === \"tab\"\n ? 'not in the Tab order (needs a native control or tabindex=\"0\")'\n : \"not focusable (needs a native control or tabindex)\";\n report(\n el,\n \"keyboard-inaccessible\",\n \"error\",\n `The \"${req.target}\" target of \"${identifier}\" is ${problem}.`,\n el,\n req.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: author-futile (controller-managed) attributes --------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.managedAria) {\n const elements =\n rule.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? []);\n const where = rule.target === \"\" ? \"scope element\" : `\"${rule.target}\" target`;\n for (const el of elements) {\n for (const name of rule.attrs) {\n const attr = el.attrs.find((a) => a.name === name);\n if (!attr) continue;\n report(\n el,\n \"managed-aria\",\n \"warning\",\n `${name} on the ${where} of \"${identifier}\" is managed by the controller at runtime.`,\n attr,\n rule.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: cross-controller composition values ------------------------\n // Value-alignment contracts between a host controller and a co-located\n // companion (e.g. sortable's sort axis vs roving's orientation). Both sides\n // are judged by their *effective* value — the authored attribute, or the\n // rule's declared default when absent — because these contracts exist\n // precisely where the companion's default does not match the host's. An\n // ERB-generated value on either side makes the rule undecidable, so it is\n // skipped rather than guessed at.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.compositions) {\n const targeted = targetNodes.get(node)?.get(identifier)?.get(rule.target);\n // An absent optional container target falls back to the scope element\n // when the rule says the runtime does the same (e.g. sortable's `list`).\n const elements =\n rule.target === \"\" ? [node] : (targeted ?? (rule.fallbackToScope ? [node] : []));\n const where = rule.target === \"\" || !targeted ? \"scope element\" : `\"${rule.target}\" target`;\n const when = rule.when;\n if (when) {\n const hostAttr = node.attrs.find(\n (a) => a.name === `data-${identifier}-${dasherize(when.value)}-value`,\n );\n if (hostAttr && isDynamicValue(hostAttr)) continue;\n const hostEffective = hostAttr ? hostAttr.value.trim() : when.default;\n if (!when.equals.includes(hostEffective)) continue;\n }\n const hostContext = when ? ` (${when.value} ${list(when.equals)})` : \"\";\n for (const el of elements) {\n const declared = el.attrs.find((a) => a.name === \"data-controller\");\n if (!declared || !controllerIdentifiers(declared.value).includes(rule.coController)) {\n continue;\n }\n const coAttrName = `data-${rule.coController}-${dasherize(rule.require.value)}-value`;\n const coAttr = el.attrs.find((a) => a.name === coAttrName);\n if (coAttr && isDynamicValue(coAttr)) continue;\n const effective = coAttr ? coAttr.value.trim() : rule.require.default;\n if (rule.require.oneOf.includes(effective)) continue;\n const [canonical] = rule.require.oneOf;\n if (!coAttr) {\n report(\n el,\n \"composition-mismatch\",\n \"error\",\n `\"${identifier}\"${hostContext} requires the co-located \"${rule.coController}\" on its ${where} to set ${coAttrName} to ${list(rule.require.oneOf)} (its default is \"${rule.require.default}\").`,\n el,\n rule.suggestion,\n );\n } else {\n report(\n el,\n \"composition-mismatch\",\n \"error\",\n `${coAttrName}=\"${coAttr.value}\" on the ${where} of \"${identifier}\"${hostContext} must be ${list(rule.require.oneOf)}.`,\n coAttr,\n rule.suggestion,\n canonical !== undefined\n ? valueFix(coAttr, canonical, `Set ${coAttrName} to \"${canonical}\"`)\n : undefined,\n );\n }\n }\n }\n }\n\n // --- Stage 3: ARIA idref resolution --------------------------------------\n // Scope/target elements are where the rules above push authors to write\n // reference attributes; a token that resolves to no id in the same file is\n // (at best) split across partials and (at worst) a typo that silently\n // empties an accessible name. Warning severity: only this file is visible.\n const ids = new Set<string>();\n walk(tree, (node) => {\n const id = node.attrs.find((a) => a.name === \"id\");\n if (!id || isDynamicValue(id)) return;\n const value = id.value.trim();\n if (value.length > 0 && !/\\s/.test(value)) ids.add(value);\n });\n\n const anchored = new Set<ElementNode>(scopes.map((scope) => scope.node));\n for (const byIdentifier of targetNodes.values()) {\n for (const byName of byIdentifier.values()) {\n for (const els of byName.values()) {\n for (const el of els) anchored.add(el);\n }\n }\n }\n for (const el of anchored) {\n for (const attr of el.attrs) {\n if (!IDREF_ATTRS.has(attr.name) || isDynamicValue(attr)) continue;\n for (const token of attr.value.split(/\\s+/).filter((t) => t.length > 0)) {\n if (!ids.has(token)) {\n const best = nearestName(token, [...ids]);\n report(\n el,\n \"unresolved-idref\",\n \"warning\",\n `${attr.name} references id \"${token}\", but no element in this file declares it.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, token, best),\n );\n }\n }\n }\n }\n\n diagnostics.sort((a, b) => a.line - b.line || a.column - b.column);\n return diagnostics;\n}\n\n/**\n * Where a diagnostic is anchored in the source: an attribute (position of the\n * attribute name) or an element (position of the tag's `<`). Knowing which of\n * the two it is lets {@link push} derive the anchored token's length.\n */\ntype Anchor = ParsedAttr | ElementNode;\n\n/** Suppression-aware diagnostic sink bound to a source's ignore declarations. */\ntype Reporter = (\n owner: ElementNode,\n code: DiagnosticCode,\n severity: DiagnosticSeverity,\n message: string,\n at: Anchor,\n suggestion?: string,\n fix?: DiagnosticFix,\n) => void;\n\n/**\n * Checks one accessibility requirement against a present element. The base\n * `attrs`/`values` pair and each `or` alternative are alternatives (OR): the\n * requirement is met when at least one candidate attribute is present.\n *\n * Value checking is resolved **per attribute name** by unioning the allowed\n * values across every group that lists that name — so a value valid in *any*\n * of its groups is accepted (a group without `values` accepts anything). This\n * matters when the same attribute appears in more than one group: a value\n * that is valid in one group must not be flagged just because another group\n * lists a different set. Distinct attributes still stand alone, so an authored\n * `aria-live=\"off\"` is flagged even next to a valid `role=\"status\"`.\n */\nfunction checkA11y(\n report: Reporter,\n el: ElementNode,\n identifier: string,\n req: A11yRequirement,\n): void {\n const groups: readonly A11yAlternative[] = [\n { attrs: req.attrs, values: req.values },\n ...(req.or ?? []),\n ];\n const where = req.target === \"\" ? \"scope element\" : `\"${req.target}\" target`;\n\n // Per attribute name: the union of allowed values across the groups that\n // list it (`anyValue` when some group leaves the value unconstrained).\n const allowedByAttr = new Map<string, { anyValue: boolean; values: Set<string> }>();\n for (const group of groups) {\n for (const name of group.attrs) {\n let entry = allowedByAttr.get(name);\n if (!entry) {\n entry = { anyValue: false, values: new Set() };\n allowedByAttr.set(name, entry);\n }\n if (!group.values) entry.anyValue = true;\n else for (const value of group.values) entry.values.add(value);\n }\n }\n\n const invalid: Array<{ attr: ParsedAttr; values: readonly string[] }> = [];\n let anyPresent = false;\n for (const [name, allowed] of allowedByAttr) {\n const attr = el.attrs.find((a) => a.name === name);\n if (!attr) continue;\n anyPresent = true;\n if (!allowed.anyValue && !allowed.values.has(attr.value.trim())) {\n invalid.push({ attr, values: [...allowed.values] });\n }\n }\n\n if (!anyPresent) {\n report(\n el,\n \"missing-aria\",\n \"error\",\n `\"${identifier}\" requires ${describeAttrs([...allowedByAttr.keys()])} on its ${where}.`,\n el,\n req.suggestion,\n );\n return;\n }\n for (const { attr, values } of invalid) {\n // The attribute exists but holds a wrong value, so the rule's \"Add …\"\n // suggestion would mislead — point at the value fix instead. When exactly\n // one value is allowed the correction is unambiguous, so emit it as a\n // machine fix too; multi-valued rules stay a human decision.\n const [only] = values;\n report(\n el,\n \"invalid-aria-value\",\n \"error\",\n `${attr.name}=\"${attr.value}\" is not valid on the ${where} of \"${identifier}\". Expected ${list(values)}.`,\n attr,\n `Set ${attr.name} to ${list(values)}.`,\n values.length === 1 && only !== undefined\n ? valueFix(attr, only, `Set ${attr.name} to \"${only}\"`)\n : undefined,\n );\n }\n}\n\n/** Tags focusable without an authored `tabindex` (input handled separately). */\nconst NATIVE_FOCUSABLE_TAGS = new Set([\"button\", \"select\", \"textarea\", \"summary\"]);\n\n/**\n * Whether the tag is natively focusable **as authored**. `input` is focusable\n * *unless* `type=\"hidden\"` (never rendered, never focusable); `a`/`area` are\n * focusable only with an `href`. Deliberately does **not** consider `disabled`,\n * `hidden`, or `inert`: those are usually intentional states, and — crucially —\n * this library's roving contracts keep items inside an ancestor-`hidden`\n * container until opened (a closed `<ul role=\"menu\" hidden>`), so treating them\n * as non-focusable would false-positive on every correct menu.\n */\nfunction isNativelyFocusable(el: ElementNode): boolean {\n if (NATIVE_FOCUSABLE_TAGS.has(el.tag)) return true;\n if (el.tag === \"input\") {\n const type = (el.attrs.find((a) => a.name === \"type\")?.value ?? \"\").trim().toLowerCase();\n return type !== \"hidden\";\n }\n if (el.tag === \"a\" || el.tag === \"area\") return el.attrs.some((a) => a.name === \"href\");\n return false;\n}\n\n/** Parsed integer `tabindex`, or `null` when absent or not a valid integer. */\nfunction tabindexValue(el: ElementNode): number | null {\n const attr = el.attrs.find((a) => a.name === \"tabindex\");\n if (!attr) return null;\n const parsed = Number.parseInt(attr.value.trim(), 10);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\n/**\n * Static focusability floor for the keyboard-prerequisite pass, per the rule's\n * {@link KeyboardRequirement.reach}:\n *\n * - `\"tab\"`: the element must be in the Tab order — natively focusable /\n * `contenteditable` with no `tabindex`, or `tabindex >= 0`. A `tabindex=\"-1\"`\n * (or a present-but-invalid value) fails, catching the \"removed from Tab\n * order\" bug a presence-only check would miss.\n * - `\"focus\"`: the controller focuses it programmatically, so any valid\n * `tabindex` (including the roving `-1`), a natively focusable element, or\n * `contenteditable` suffices.\n *\n * Presence-only otherwise — the set-level roving invariant is runtime state.\n */\nfunction isFocusable(el: ElementNode, reach: \"tab\" | \"focus\"): boolean {\n const hasTabindex = el.attrs.some((a) => a.name === \"tabindex\");\n if (hasTabindex) {\n const value = tabindexValue(el);\n if (value === null) return false; // present but invalid → not reliably focusable\n return reach === \"tab\" ? value >= 0 : true;\n }\n return isNativelyFocusable(el) || isContentEditable(el);\n}\n\n/**\n * Whether `contenteditable` makes the element focusable. Bare `contenteditable`\n * / `=\"true\"` / `=\"plaintext-only\"` are editable (focusable); only the explicit\n * `=\"false\"` opts out, so it must not count as focusable.\n */\nfunction isContentEditable(el: ElementNode): boolean {\n const attr = el.attrs.find((a) => a.name === \"contenteditable\");\n return attr !== undefined && attr.value.trim().toLowerCase() !== \"false\";\n}\n\n/**\n * ARIA attributes whose value is an idref (list); the idref-resolution pass\n * checks each token against the ids declared in the same file.\n */\nconst IDREF_ATTRS = new Set([\n \"aria-activedescendant\",\n \"aria-controls\",\n \"aria-describedby\",\n \"aria-details\",\n \"aria-errormessage\",\n \"aria-flowto\",\n \"aria-labelledby\",\n \"aria-owns\",\n]);\n\n/**\n * Opts an element (and its subtree) out of diagnostics: an empty value\n * suppresses everything, a whitespace-separated {@link DiagnosticCode} list\n * suppresses exactly those codes. The escape hatch for the rare markup the\n * static rules cannot see well enough (a reference resolved in another\n * partial, an intentionally exotic composition) — each use is greppable and\n * reviewable. Single-dash namespace like {@link FRAGMENT_ATTR}, so it can\n * never collide with a controller's own attribute namespace.\n */\nconst IGNORE_ATTR = \"data-stimeo-ignore\";\n\n/** Climbs the ancestor chain (including `node`) for the nearest owning scope. */\nfunction findOwner(node: ElementNode, identifier: string): ElementNode | null {\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const dataController = current.attrs.find((a) => a.name === \"data-controller\");\n if (dataController && controllerIdentifiers(dataController.value).includes(identifier)) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\n/**\n * Declares a server-rendered **fragment**: markup a controller fetches and\n * appends at runtime inside its own scope (a Turbo Stream template, an\n * incrementally fetched page of list items). Its value is the runtime host —\n * whitespace-separated `stimeo--*` identifiers. Targets inside the declaration\n * are exempt from `orphan-target` for exactly those identifiers; every name is\n * still spell-checked against the manifest, including the declaration itself.\n * Deliberately single-dash (`data-stimeo-`, not `data-stimeo--`) so it can never\n * collide with a controller's own `data-stimeo--<id>-*` attribute namespace.\n */\nconst FRAGMENT_ATTR = \"data-stimeo-fragment\";\n\n/** Whether `node` (or an ancestor) declares itself a fragment of `identifier`. */\nfunction inDeclaredFragment(node: ElementNode, identifier: string): boolean {\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const declared = current.attrs.find((a) => a.name === FRAGMENT_ATTR);\n if (declared?.value.split(/\\s+/).includes(identifier)) return true;\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Length of the token an anchor points at: the attribute name, or the opening\n * `<tag` (the `<` plus the tag name) for element anchors.\n */\nfunction anchorLength(at: Anchor): number {\n return \"name\" in at ? at.name.length : at.tag.length + 1;\n}\n\n/** Appends a diagnostic positioned at the given source location. */\nfunction push(\n out: Diagnostic[],\n code: DiagnosticCode,\n severity: DiagnosticSeverity,\n message: string,\n at: Anchor,\n suggestion?: string,\n fix?: DiagnosticFix,\n): void {\n out.push({\n code,\n severity,\n message,\n line: at.line,\n column: at.column,\n length: anchorLength(at),\n suggestion,\n fix,\n });\n}\n\n/**\n * Machine fix replacing one occurrence of `token` inside the attribute's\n * value with `replacement`. Returns undefined when there is no replacement,\n * the attribute is boolean (no value offsets), or the token cannot be located\n * verbatim. Uses the first occurrence — a value repeating the same broken\n * token is pathological enough that fixing the first is still the right edit.\n */\nfunction tokenFix(\n attr: ParsedAttr,\n token: string,\n replacement: string | undefined,\n): DiagnosticFix | undefined {\n if (replacement === undefined || attr.valueStart === undefined || token.length === 0) {\n return undefined;\n }\n const index = attr.value.indexOf(token);\n if (index < 0) return undefined;\n const start = attr.valueStart + index;\n return {\n start,\n end: start + token.length,\n text: replacement,\n title: `Replace with \"${replacement}\"`,\n };\n}\n\n/** Machine fix replacing the attribute's entire value. */\nfunction valueFix(attr: ParsedAttr, replacement: string, title: string): DiagnosticFix | undefined {\n if (attr.valueStart === undefined || attr.valueEnd === undefined) return undefined;\n return { start: attr.valueStart, end: attr.valueEnd, text: replacement, title };\n}\n\n/** Formats a name list for human-readable messages. */\nfunction list(names: readonly string[]): string {\n return names.length > 0 ? names.map((n) => `\"${n}\"`).join(\", \") : \"(none)\";\n}\n\n/** Describes a set of \"any of\" attributes, e.g. `aria-labelledby or aria-label`. */\nfunction describeAttrs(attrs: readonly string[]): string {\n return attrs.length === 1 ? (attrs[0] as string) : attrs.join(\" or \");\n}\n\n/**\n * Stage-4 typo candidate: the nearest known name when it is close enough to\n * be a plausible misspelling, else undefined. The threshold scales with name\n * length but is capped, so unrelated names never produce a misleading match.\n * Feeds both the human suggestion ({@link didYouMean}) and the machine fix.\n */\nfunction nearestName(name: string, candidates: readonly string[]): string | undefined {\n if (name.length === 0) return undefined;\n let best: string | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const distance = levenshtein(name, candidate);\n if (distance < bestDistance) {\n bestDistance = distance;\n best = candidate;\n }\n }\n const threshold = Math.min(3, Math.floor(name.length / 2) + 1);\n return best !== undefined && bestDistance <= threshold ? best : undefined;\n}\n\n/** Formats a {@link nearestName} candidate as the human-readable suggestion. */\nfunction asDidYouMean(best: string | undefined): string | undefined {\n return best === undefined ? undefined : `Did you mean \"${best}\"?`;\n}\n\n/**\n * Stage-4 typo suggestion: `Did you mean \"x\"?`, or undefined when nothing is\n * close. Exported for the MCP server's `stimeo_controller` unknown-id hint.\n */\nexport function didYouMean(name: string, candidates: readonly string[]): string | undefined {\n return asDidYouMean(nearestName(name, candidates));\n}\n\n/** Classic dynamic-programming Levenshtein edit distance. */\nfunction levenshtein(a: string, b: string): number {\n const rows = a.length;\n const cols = b.length;\n if (rows === 0) return cols;\n if (cols === 0) return rows;\n let prev = Array.from({ length: cols + 1 }, (_, j) => j);\n for (let i = 1; i <= rows; i++) {\n const curr = [i];\n for (let j = 1; j <= cols; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(\n (curr[j - 1] as number) + 1,\n (prev[j] as number) + 1,\n (prev[j - 1] as number) + cost,\n );\n }\n prev = curr;\n }\n return prev[cols] as number;\n}\n","import { checkSource } from \"./check\";\nimport type { Manifest } from \"./types\";\n\n/**\n * Bundled example index for the MCP server (`stimeo_example` tool and\n * `stimeo://examples/*` resources).\n *\n * The examples are the official catalog's demo sidecars — the exact markup\n * shown verbatim in each demo's code tab and copy-pasted by users, so they\n * are the closest thing the project has to \"verified reference markup\".\n * `scripts/postbuild.ts` walks them at build time (`scripts/demo_sources.ts`\n * resolves the supply: the playground catalog in the dev monorepo,\n * `examples/` in the public mirror) and serializes the result of\n * {@link buildExamplesIndex} into `dist/inspector/examples.json`, next to\n * `manifest.json`.\n *\n * {@link buildExamplesIndex} is pure so the mapping and the verification gate\n * are unit-tested directly; the filesystem walk stays in the build scripts.\n */\n\n/** Format version of `examples.json` (bumped on breaking shape changes). */\nexport const EXAMPLES_SCHEMA_VERSION = 1;\n\n/** One bundled example: the demo markup shown verbatim in the catalog. */\nexport interface ExampleEntry {\n /**\n * Repo-relative provenance: `playground/.../demos/menu/_demo.html.erb` in\n * the dev monorepo, `examples/menu/_demo.html.erb` in the public mirror.\n */\n readonly file: string;\n /** The HTML/ERB source. */\n readonly source: string;\n}\n\n/** The bundled `examples.json`: verified demo markup keyed by controller id. */\nexport interface ExamplesIndex {\n readonly schemaVersion: number;\n /** Keyed by controller identifier, e.g. `stimeo--menu`. Keys are sorted. */\n readonly examples: Readonly<Record<string, ExampleEntry>>;\n}\n\n/** One demo sidecar as discovered on disk by the build script. */\nexport interface DemoSource {\n /** Demo directory basename (snake_case), e.g. `inline_combobox`. */\n readonly dir: string;\n /** Repo-relative path of the `_demo.html.erb` file. */\n readonly file: string;\n /** The file's contents. */\n readonly source: string;\n}\n\n/**\n * Maps a demo directory basename to its controller identifier. Demo dirs use\n * snake_case (`date_range_picker`); controller identifiers are the `stimeo--`\n * prefix plus the kebab-case name (`stimeo--date-range-picker`).\n * {@link buildExamplesIndex} enforces a 1:1 mapping between the demos tree and\n * the manifest.\n */\nexport function demoDirToControllerId(dir: string): string {\n return `stimeo--${dir.replaceAll(\"_\", \"-\")}`;\n}\n\n/**\n * Controllers temporarily exempted from the demo/manifest bijection. The\n * reverse check fails when an exempted controller gains a demo, so every entry\n * must be removed as soon as its exemption is no longer needed.\n */\nexport const PENDING_DEMO_CONTROLLERS: ReadonlySet<string> = new Set([]);\n\n/**\n * Builds the bundled example index from the discovered demo sidecars,\n * enforcing two invariants so \"verified example\" stays true:\n *\n * 1. **Bijection with the manifest.** Every demo dir must map to a known\n * controller and every controller must have a demo — a mismatch on either\n * side means the catalog and the library drifted, and the build must fail\n * loudly rather than silently ship a hole. The only exception is the\n * explicit `pendingDemos` allowlist ({@link PENDING_DEMO_CONTROLLERS}):\n * a documented \"demo not built yet\" deferral, kept honest by the reverse\n * check (an allowlisted controller acquiring a demo fails the build until\n * the stale entry is removed).\n * 2. **Check-clean.** Every example must pass {@link checkSource} with no\n * error-severity diagnostics against the same manifest it ships with.\n *\n * @throws Error listing every violation when an invariant is broken.\n */\nexport function buildExamplesIndex(\n demos: readonly DemoSource[],\n manifest: Manifest,\n pendingDemos: ReadonlySet<string> = PENDING_DEMO_CONTROLLERS,\n): ExamplesIndex {\n const problems: string[] = [];\n const byId = new Map<string, DemoSource>();\n for (const demo of demos) {\n const id = demoDirToControllerId(demo.dir);\n if (!Object.hasOwn(manifest.controllers, id)) {\n problems.push(`demo \"${demo.dir}\" maps to unknown controller \"${id}\"`);\n continue;\n }\n if (byId.has(id)) {\n problems.push(`controller \"${id}\" has more than one demo source`);\n continue;\n }\n byId.set(id, demo);\n }\n for (const id of Object.keys(manifest.controllers)) {\n if (byId.has(id) || pendingDemos.has(id)) continue;\n problems.push(`controller \"${id}\" has no demo example`);\n }\n for (const id of pendingDemos) {\n if (byId.has(id)) {\n problems.push(\n `controller \"${id}\" is allowlisted as pending but now has a demo — ` +\n \"remove it from PENDING_DEMO_CONTROLLERS\",\n );\n }\n }\n for (const [id, demo] of byId) {\n const errors = checkSource(demo.source, manifest).filter((d) => d.severity === \"error\");\n for (const d of errors) {\n problems.push(`example for \"${id}\" fails check: ${d.line}:${d.column} ${d.message}`);\n }\n }\n if (problems.length > 0) {\n throw new Error(`examples index build failed:\\n - ${problems.join(\"\\n - \")}`);\n }\n // Null-prototype dictionary, mirroring runCatalogTool: ids derive from\n // directory names, and a hostile \"__proto__\" would otherwise rewrite the\n // dictionary's prototype instead of storing the entry.\n const examples: Record<string, ExampleEntry> = Object.create(null);\n for (const id of [...byId.keys()].sort()) {\n const demo = byId.get(id);\n if (!demo) continue;\n examples[id] = { file: demo.file, source: demo.source };\n }\n return { schemaVersion: EXAMPLES_SCHEMA_VERSION, examples };\n}\n","import { extname } from \"node:path\";\n\n/**\n * Single source of truth for which files the Inspector checks. Shared by the\n * CLI's directory walk and the VS Code extension's document filter so a file\n * never gets diagnostics in one surface and a silent pass in the other.\n */\n\n/** Final extensions (lowercased) the Inspector understands. `.html.erb` ends with `.erb`. */\nconst CHECKABLE_FILE_EXTENSIONS = new Set([\".erb\", \".html\", \".htm\"]);\n\n/**\n * Whether the path names a checkable HTML/ERB file. Matches on the *final*\n * extension only (`extname`), case-insensitively — case-only variants like\n * `legacy.HTM` are the same file on the case-insensitive filesystems most\n * Rails apps are edited on (macOS/Windows), so they must not slip past CI\n * while the editor flags them.\n */\nexport function isCheckableFile(path: string): boolean {\n return CHECKABLE_FILE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n","import { readFileSync } from \"node:fs\";\nimport type { Manifest } from \"./types\";\n\n/**\n * Loading and shape-validation of `manifest.json` files, shared by every\n * consumer that reads a manifest from disk: the CLI (the copy bundled next to\n * `cli_bin.js`), the VS Code extension (a workspace's installed copy or its\n * bundled snapshot), and any future server (MCP) doing the same. Keeping the\n * guard in one place means a corrupt or cross-version manifest degrades the\n * same way everywhere instead of crashing one surface and passing another.\n */\n\n/** Array-typed fields the schema-v5 engine iterates on every controller entry. */\nconst CONTROLLER_ARRAY_FIELDS = [\n \"targets\",\n \"values\",\n \"actions\",\n \"events\",\n \"requiredTargets\",\n \"a11y\",\n \"keyboard\",\n \"managedAria\",\n \"compositions\",\n] as const;\n\n/**\n * Structural guard for a parsed manifest. A reader bundles the engine of one\n * schema version but may load a manifest written by another (e.g. an app\n * installing a package whose manifest predates `keyboard`/`managedAria`), and\n * the engine iterates those arrays unconditionally — an unvalidated manifest\n * would crash every check instead of failing cleanly. Shape-based rather than\n * a strict `schemaVersion` equality so additive future versions keep working.\n */\nexport function isCompatibleManifest(value: unknown): value is Manifest {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (typeof record.schemaVersion !== \"number\" || typeof record.packageVersion !== \"string\") {\n return false;\n }\n const controllers = record.controllers;\n if (typeof controllers !== \"object\" || controllers === null || Array.isArray(controllers)) {\n return false;\n }\n for (const entry of Object.values(controllers as Record<string, unknown>)) {\n if (typeof entry !== \"object\" || entry === null) return false;\n for (const field of CONTROLLER_ARRAY_FIELDS) {\n if (!Array.isArray((entry as Record<string, unknown>)[field])) return false;\n }\n }\n return true;\n}\n\n/**\n * Reads and parses one manifest file; throws on missing/corrupt files and on\n * manifests whose shape the bundled engine cannot consume.\n */\nexport function readManifestFile(path: string): Manifest {\n const parsed: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n if (!isCompatibleManifest(parsed)) {\n throw new Error(`Incompatible or malformed manifest: ${path}`);\n }\n return parsed;\n}\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\nimport { checkSource } from \"./check\";\nimport type { ExamplesIndex } from \"./examples\";\nimport { EXAMPLES_SCHEMA_VERSION } from \"./examples\";\nimport { isCheckableFile } from \"./files\";\nimport { readManifestFile } from \"./manifest_io\";\nimport type { CheckReport, ControllerManifest, Diagnostic, FileReport, Manifest } from \"./types\";\n\n/**\n * `stimeo check <path...>` / `stimeo catalog` — static checker and catalog\n * for `stimeo--*` markup.\n *\n * This is the executable entry point bundled as the `stimeo` npm bin. It is a\n * thin shell around {@link checkSource} and the bundled manifest: discover\n * files, run the engine, format the report, and set the exit code. All checking\n * logic lives in the engine so the CLI and the project's own checks use exactly the same\n * code path. Both commands accept `--json` to emit machine-readable output for\n * editor tooling and CI.\n */\n\n/** Resolves one of the JSON artifacts postbuild writes next to this file in `dist/inspector/`. */\nfunction bundledPath(name: string): string {\n return join(dirname(fileURLToPath(import.meta.url)), name);\n}\n\n/**\n * Loads the manifest bundled next to this file (`dist/inspector/manifest.json`),\n * shape-validated so a corrupt build artifact fails loudly here rather than as\n * an engine crash mid-check. Exported for the MCP server (`stimeo mcp`), which\n * loads the same bundled manifest at startup.\n */\nexport function loadManifest(): Manifest {\n return readManifestFile(bundledPath(\"manifest.json\"));\n}\n\n/**\n * Loads the example index bundled next to this file\n * (`dist/inspector/examples.json`), rejecting a format-version mismatch: the\n * index is only ever read by the build it shipped with, so a mismatch means a\n * corrupted or mixed installation and must fail loudly, not misbehave.\n */\nexport function loadExamplesIndex(): ExamplesIndex {\n const index = JSON.parse(readFileSync(bundledPath(\"examples.json\"), \"utf8\")) as ExamplesIndex;\n if (index.schemaVersion !== EXAMPLES_SCHEMA_VERSION) {\n throw new Error(\n `examples.json schema version ${index.schemaVersion} does not match this build ` +\n `(expected ${EXAMPLES_SCHEMA_VERSION}); reinstall or rebuild the package.`,\n );\n }\n return index;\n}\n\n/** Recursively collects checkable files under the given path. */\nfunction collectFiles(target: string, out: string[]): void {\n const stat = statSync(target);\n if (stat.isDirectory()) {\n for (const entry of readdirSync(target)) {\n collectFiles(join(target, entry), out);\n }\n return;\n }\n if (isCheckableFile(target)) out.push(target);\n}\n\n/** Builds a report for a single file. */\nfunction checkFile(file: string, manifest: Manifest): FileReport {\n const source = readFileSync(file, \"utf8\");\n return { file, diagnostics: checkSource(source, manifest) };\n}\n\n/**\n * Formats one diagnostic, e.g. ` 13:5 error message [code]`. A stage-4\n * suggestion, when present, is appended on its own indented `→` line.\n */\nfunction formatDiagnostic(d: Diagnostic): string {\n const where = `${d.line}:${d.column}`.padEnd(7);\n const head = ` ${where} ${d.severity.padEnd(7)} ${d.message} [${d.code}]`;\n return d.suggestion ? `${head}\\n → ${d.suggestion}` : head;\n}\n\n/**\n * Escapes workflow-command *message* data (`%`, CR, LF) per the GitHub Actions\n * toolkit's escaping rules.\n */\nfunction escapeGithubData(value: string): string {\n return value.replaceAll(\"%\", \"%25\").replaceAll(\"\\r\", \"%0D\").replaceAll(\"\\n\", \"%0A\");\n}\n\n/** Escapes a workflow-command *property* value (message rules plus `:`, `,`). */\nfunction escapeGithubProperty(value: string): string {\n return escapeGithubData(value).replaceAll(\":\", \"%3A\").replaceAll(\",\", \"%2C\");\n}\n\n/**\n * Formats one diagnostic as a GitHub Actions workflow command\n * (`::error file=…,line=…,col=…,title=…::message`). Emitting these from any CI\n * step makes the runner render inline annotations on the PR diff — no\n * marketplace action, upload step, or SARIF pipeline required.\n */\nexport function formatGithubAnnotation(file: string, d: Diagnostic): string {\n const properties = [\n `file=${escapeGithubProperty(file)}`,\n `line=${d.line}`,\n `col=${d.column}`,\n `title=${escapeGithubProperty(`Stimeo Inspector [${d.code}]`)}`,\n ].join(\",\");\n const message = d.suggestion ? `${d.message} → ${d.suggestion}` : d.message;\n return `::${d.severity} ${properties}::${escapeGithubData(message)}`;\n}\n\n/**\n * Aggregates per-file reports into the structured {@link CheckReport}, keeping\n * only files that produced diagnostics and tallying severities. Pure (no I/O),\n * so the JSON output contract is unit-tested directly.\n */\nexport function buildCheckReport(\n reports: readonly FileReport[],\n checkedFiles: number,\n): CheckReport {\n let errorCount = 0;\n let warningCount = 0;\n const files: FileReport[] = [];\n for (const report of reports) {\n if (report.diagnostics.length === 0) continue;\n files.push(report);\n for (const d of report.diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else warningCount++;\n }\n }\n return { ok: errorCount === 0, checkedFiles, errorCount, warningCount, files };\n}\n\n/**\n * Controller entries sorted by identifier — the canonical iteration order for\n * catalog-style output. Shared by the CLI summary below and the MCP\n * `stimeo_catalog` tool so both render the manifest in the same order.\n */\nexport function sortedControllerEntries(\n manifest: Manifest,\n): ReadonlyArray<readonly [string, ControllerManifest]> {\n return Object.keys(manifest.controllers)\n .sort()\n .flatMap((id) => {\n const controller = manifest.controllers[id];\n return controller ? [[id, controller] as const] : [];\n });\n}\n\n/**\n * Renders the manifest as a human-readable catalog: one block per controller\n * listing its non-empty target/value/action/event names. `--json` emits the\n * raw manifest instead, for machine consumption.\n */\nexport function catalogSummary(manifest: Manifest): string[] {\n const entries = sortedControllerEntries(manifest);\n const lines = [\n `Stimeo UI catalog — ${entries.length} controller(s) (schema v${manifest.schemaVersion}, package ${manifest.packageVersion})`,\n \"\",\n ];\n for (const [id, c] of entries) {\n lines.push(id);\n if (c.targets.length > 0) lines.push(` targets: ${c.targets.join(\", \")}`);\n if (c.values.length > 0) lines.push(` values: ${c.values.join(\", \")}`);\n if (c.actions.length > 0) lines.push(` actions: ${c.actions.join(\", \")}`);\n if (c.events.length > 0) lines.push(` events: ${c.events.join(\", \")}`);\n }\n return lines;\n}\n\nconst USAGE = `stimeo — static checker and catalog for Stimeo UI markup\n\nUsage:\n stimeo check [--json|--github] <path...>\n Check HTML/ERB files (or directories) for\n unknown or misused stimeo--* controllers,\n targets, values and action methods.\n stimeo catalog [--json] Print the official controller catalog\n (identifiers, targets, values, actions,\n events).\n stimeo mcp Run a Model Context Protocol server over\n stdio, exposing the checker, catalog, and\n verified example markup as read-only tools\n (stimeo_check, stimeo_catalog,\n stimeo_controller, stimeo_example),\n resources, and workflow prompts for AI\n coding agents.\n\n--json makes either command emit machine-readable JSON (for tooling / MCP):\ncheck prints a CheckReport, catalog prints the raw manifest.\n--github prints check results as GitHub Actions workflow commands\n(::error / ::warning), which CI renders as inline PR annotations.\nExit code is 1 when any error is found (warnings never fail the run).`;\n\n/**\n * Runs the CLI.\n *\n * @param argv - Arguments after the node executable and script (`process.argv.slice(2)`).\n * @param write - Output sink (defaults to stdout); injectable for tests.\n * @param load - Manifest loader (defaults to the bundled manifest); injectable for tests.\n * @returns Process exit code (0 = clean, 1 = errors found, 2 = usage error).\n */\nexport function runCli(\n argv: readonly string[],\n write: (line: string) => void = console.log,\n load: () => Manifest = loadManifest,\n): number {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n write(USAGE);\n return command === undefined ? 2 : 0;\n }\n\n const json = rest.includes(\"--json\");\n const github = rest.includes(\"--github\");\n if (json && github) {\n write(`--json and --github are mutually exclusive.\\n\\n${USAGE}`);\n return 2;\n }\n\n if (command === \"catalog\") {\n const manifest = load();\n if (json) {\n write(JSON.stringify(manifest, null, 2));\n } else {\n for (const line of catalogSummary(manifest)) write(line);\n }\n return 0;\n }\n\n if (command !== \"check\") {\n write(`Unknown command \"${command}\".\\n\\n${USAGE}`);\n return 2;\n }\n\n const paths = rest.filter((arg) => !arg.startsWith(\"-\"));\n if (paths.length === 0) {\n write(`No paths given.\\n\\n${USAGE}`);\n return 2;\n }\n\n const files: string[] = [];\n for (const path of paths) {\n try {\n collectFiles(path, files);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n const reason =\n code === \"ENOENT\"\n ? \"no such file or directory\"\n : code === \"EACCES\"\n ? \"permission denied\"\n : ((err as Error).message ?? \"cannot access path\");\n write(`Cannot read path \"${path}\": ${reason}.\\n\\n${USAGE}`);\n return 2;\n }\n }\n\n const manifest = load();\n const cwd = process.cwd();\n const reports: FileReport[] = [];\n for (const file of files.sort()) {\n reports.push({\n file: relative(cwd, file) || file,\n diagnostics: checkFile(file, manifest).diagnostics,\n });\n }\n const summary = buildCheckReport(reports, files.length);\n\n if (json) {\n write(JSON.stringify(summary, null, 2));\n return summary.errorCount > 0 ? 1 : 0;\n }\n\n if (github) {\n for (const report of summary.files) {\n for (const d of report.diagnostics) write(formatGithubAnnotation(report.file, d));\n }\n } else {\n for (const report of summary.files) {\n write(report.file);\n for (const d of report.diagnostics) write(formatDiagnostic(d));\n write(\"\");\n }\n }\n\n const total = summary.errorCount + summary.warningCount;\n if (total === 0) {\n write(`✓ Checked ${summary.checkedFiles} file(s); no problems found.`);\n return 0;\n }\n write(\n `✖ ${total} problem(s) (${summary.errorCount} error(s), ${summary.warningCount} warning(s)).`,\n );\n return summary.errorCount > 0 ? 1 : 0;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/inspector/erb.ts","../../src/inspector/extract.ts","../../src/inspector/html_parser.ts","../../src/inspector/types.ts","../../src/inspector/check.ts","../../src/inspector/examples.ts","../../src/inspector/files.ts","../../src/inspector/manifest_io.ts","../../src/inspector/cli.ts"],"names":["j","readFileSync","manifest"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Neutralizes ERB so the HTML parser only ever sees static markup.\n *\n * Every ERB tag — `<% %>`, `<%= %>`, `<%# %>`, plus the whitespace-trimming\n * variants `<%- -%>` — is replaced with spaces. Newlines inside the tag are\n * preserved so that 1-based line/column positions used in diagnostics line up\n * with the original source.\n *\n * Because ERB is blanked rather than interpreted, dynamically-generated markup\n * is naturally excluded from checking: a dynamic identifier such as\n * `data-controller=\"<%= id %>\"` collapses to an empty attribute value and a\n * dynamic attribute name such as `data-<%= x %>-target` no longer matches the\n * `stimeo--*` patterns. This is the intended \"dynamic attributes are out of\n * scope\" behavior.\n *\n * @param source - Raw HTML/ERB source.\n * @returns The source with all ERB tags replaced by position-preserving spaces.\n */\nexport function neutralizeErb(source: string): string {\n return source.replace(/<%[\\s\\S]*?%>/g, (match) => match.replace(/[^\\n]/g, \" \"));\n}\n","/**\n * Pure helpers for recognizing `stimeo--*` attributes within parsed markup.\n *\n * These functions know nothing about files or the manifest — they only decode\n * Stimulus's attribute conventions, scoped strictly to the `stimeo--`\n * namespace so a consumer's own controllers are never inspected.\n */\n\nconst NAMESPACE_PREFIX = \"stimeo--\";\n\n/**\n * Converts a Stimulus value name to its attribute token, mirroring Stimulus's\n * own dasherize (e.g. `rootMargin` → `root-margin`).\n */\nexport function dasherize(value: string): string {\n return value.replace(/([A-Z])/g, (_match, char: string) => `-${char.toLowerCase()}`);\n}\n\n/** Extracts the `stimeo--*` identifiers listed in a `data-controller` value.\n * Duplicates are collapsed (Stimulus connects a repeated identifier once), which\n * keeps downstream scope-based diagnostics from being reported multiple times. */\nexport function controllerIdentifiers(dataControllerValue: string): string[] {\n const seen = new Set<string>();\n for (const token of dataControllerValue.split(/\\s+/)) {\n if (token.startsWith(NAMESPACE_PREFIX)) seen.add(token);\n }\n return [...seen];\n}\n\n/**\n * If `attrName` is an Stimeo target attribute (`data-{identifier}-target`),\n * returns the controller identifier; otherwise `null`.\n */\nexport function parseTargetAttr(attrName: string): string | null {\n const match = /^data-(stimeo--[a-z0-9][a-z0-9-]*)-target$/.exec(attrName);\n return match?.[1] ?? null;\n}\n\n/** Result of decoding a `data-{identifier}-{value}-value` attribute. */\nexport interface ParsedValueAttr {\n /** Resolved identifier, or `null` when it matches no known controller. */\n readonly identifier: string | null;\n /** The dasherized value token (e.g. `root-margin`), best-effort when unresolved. */\n readonly valueToken: string;\n}\n\n/**\n * Decodes an Stimeo value attribute (`data-{identifier}-{value}-value`).\n *\n * Identifiers may themselves contain hyphens (e.g. `stimeo--command-palette`),\n * so the boundary between identifier and value name is ambiguous from the\n * attribute name alone. We disambiguate against the set of known identifiers,\n * preferring the longest match.\n *\n * @param attrName - The lowercased attribute name.\n * @param knownIdentifiers - All identifiers present in the manifest.\n * @returns The decoded attribute, or `null` if it is not an Stimeo value attr.\n */\nexport function parseValueAttr(\n attrName: string,\n knownIdentifiers: readonly string[],\n): ParsedValueAttr | null {\n const match = /^data-(stimeo--[a-z0-9-]+)-value$/.exec(attrName);\n if (!match) return null;\n const inner = match[1] ?? \"\"; // identifier + \"-\" + valueToken\n\n let best: { identifier: string; valueToken: string } | null = null;\n for (const id of knownIdentifiers) {\n if (inner.startsWith(`${id}-`)) {\n const valueToken = inner.slice(id.length + 1);\n if (valueToken.length > 0 && (!best || id.length > best.identifier.length)) {\n best = { identifier: id, valueToken };\n }\n }\n }\n if (best) return best;\n\n // Unknown identifier: best-effort split at the first segment after the prefix.\n const rest = inner.slice(NAMESPACE_PREFIX.length);\n const dash = rest.indexOf(\"-\");\n const identifierGuess = dash === -1 ? inner : `${NAMESPACE_PREFIX}${rest.slice(0, dash)}`;\n const valueGuess = dash === -1 ? \"\" : rest.slice(dash + 1);\n return { identifier: null, valueToken: valueGuess || identifierGuess };\n}\n\n/** An Stimeo `data-action` descriptor decoded into its controller and method. */\nexport interface ActionDescriptor {\n /** The `stimeo--*` controller identifier (e.g. `stimeo--menu`). */\n readonly identifier: string;\n /** The action method name after `#` (e.g. `toggle`), or `\"\"` if absent. */\n readonly method: string;\n}\n\n/**\n * Decodes the Stimeo `data-action` descriptors in an attribute value, e.g.\n * `click->stimeo--menu#toggle keydown->stimeo--menu#onItemKeydown` yields one\n * entry per descriptor. Non-`stimeo--` controllers are skipped (their action\n * surface is out of scope). The method name is read up to the first action\n * option (`:prevent`, `:stop`, …), mirroring Stimulus's descriptor grammar.\n */\nexport function actionDescriptors(dataActionValue: string): ActionDescriptor[] {\n const descriptors: ActionDescriptor[] = [];\n for (const descriptor of dataActionValue.split(/\\s+/)) {\n const hash = descriptor.indexOf(\"#\");\n if (hash === -1) continue;\n let lhs = descriptor.slice(0, hash);\n const arrow = lhs.indexOf(\"->\");\n if (arrow !== -1) lhs = lhs.slice(arrow + 2);\n if (!lhs.startsWith(NAMESPACE_PREFIX)) continue;\n const method = /^[a-zA-Z_$][\\w$]*/.exec(descriptor.slice(hash + 1))?.[0] ?? \"\";\n descriptors.push({ identifier: lhs, method });\n }\n return descriptors;\n}\n\n/**\n * Extracts the `stimeo--*` controller identifiers referenced in a\n * `data-action` value, e.g. `click->stimeo--menu#toggle` yields\n * `[\"stimeo--menu\"]`. Convenience wrapper over {@link actionDescriptors}.\n */\nexport function actionIdentifiers(dataActionValue: string): string[] {\n return actionDescriptors(dataActionValue).map((d) => d.identifier);\n}\n\n/** Whether an attribute name belongs to the Stimeo namespace. */\nexport function isStimeoDataAttr(attrName: string): boolean {\n return attrName.startsWith(`data-${NAMESPACE_PREFIX}`);\n}\n","/**\n * A minimal, dependency-free HTML tokenizer/tree builder.\n *\n * The Inspector deliberately ships **zero runtime dependencies** beyond the\n * Stimulus peer, so rather than pull in a DOM library we build just enough of a\n * tree to answer the only questions the checker asks:\n * \"which `stimeo--*` attributes exist, where, and inside which controller\n * scope?\". The parser is intentionally lenient — real-world ERB output has\n * unclosed tags and stray markup — and never throws.\n *\n * It is **not** a spec-compliant HTML parser and should not be used for\n * anything beyond static attribute inspection.\n */\n\n/** A parsed attribute, with the source position of its name. */\nexport interface ParsedAttr {\n /** Lowercased attribute name (HTML attribute names are case-insensitive). */\n readonly name: string;\n /** Attribute value (without surrounding quotes); empty for boolean attrs. */\n readonly value: string;\n /** 1-based line of the attribute name. */\n readonly line: number;\n /** 1-based column of the attribute name. */\n readonly column: number;\n /**\n * Absolute source offset where the value text begins (inside the quotes);\n * absent for boolean attributes. ERB neutralization preserves offsets, so a\n * consumer can map the range back onto the *raw* source — this is how the\n * checker tells an authored value from a dynamically-generated one.\n */\n readonly valueStart?: number;\n /** Absolute source offset just past the value text; see {@link valueStart}. */\n readonly valueEnd?: number;\n}\n\n/** An element node in the lenient tree. */\nexport interface ElementNode {\n /** Lowercased tag name; the synthetic root uses `#root`. */\n readonly tag: string;\n readonly attrs: readonly ParsedAttr[];\n readonly children: ElementNode[];\n parent: ElementNode | null;\n /** 1-based line of the tag's `<`. */\n readonly line: number;\n /** 1-based column of the tag's `<`. */\n readonly column: number;\n}\n\n/** Elements that never have children and so are never pushed onto the stack. */\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\n/** Elements whose content is raw text (no nested elements to parse). */\nconst RAW_TEXT_ELEMENTS = new Set([\"script\", \"style\", \"textarea\", \"title\"]);\n\nconst WHITESPACE = new Set([\" \", \"\\t\", \"\\n\", \"\\r\", \"\\f\"]);\n\n/** Maps absolute string offsets to 1-based line/column positions. */\nclass PositionIndex {\n readonly #lineStarts: number[] = [0];\n\n constructor(source: string) {\n for (let i = 0; i < source.length; i++) {\n if (source[i] === \"\\n\") this.#lineStarts.push(i + 1);\n }\n }\n\n at(offset: number): { line: number; column: number } {\n // Binary search for the last line start that is <= offset.\n let lo = 0;\n let hi = this.#lineStarts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((this.#lineStarts[mid] ?? 0) <= offset) lo = mid;\n else hi = mid - 1;\n }\n return { line: lo + 1, column: offset - (this.#lineStarts[lo] ?? 0) + 1 };\n }\n}\n\n/**\n * Parses HTML (already ERB-neutralized) into a lenient element tree.\n *\n * @param source - HTML source to parse.\n * @returns The synthetic `#root` node whose children are the top-level elements.\n */\nexport function parseHtml(source: string): ElementNode {\n const pos = new PositionIndex(source);\n const len = source.length;\n /** Bounds-safe character access (out of range yields an empty string). */\n const ch = (k: number): string => (k >= 0 && k < len ? (source[k] as string) : \"\");\n\n const root: ElementNode = {\n tag: \"#root\",\n attrs: [],\n children: [],\n parent: null,\n line: 1,\n column: 1,\n };\n const stack: ElementNode[] = [root];\n let i = 0;\n\n const top = (): ElementNode => stack[stack.length - 1] as ElementNode;\n\n while (i < len) {\n if (ch(i) !== \"<\") {\n i++;\n continue;\n }\n\n const next = ch(i + 1);\n\n // Comment: <!-- ... -->\n if (source.startsWith(\"<!--\", i)) {\n const end = source.indexOf(\"-->\", i + 4);\n i = end === -1 ? len : end + 3;\n continue;\n }\n // Markup declaration (<!DOCTYPE ...>) or processing instruction (<? ... ?>).\n if (next === \"!\" || next === \"?\") {\n const end = source.indexOf(\">\", i);\n i = end === -1 ? len : end + 1;\n continue;\n }\n // End tag: </name>\n if (next === \"/\") {\n let j = i + 2;\n let name = \"\";\n while (j < len && ch(j) !== \">\" && !WHITESPACE.has(ch(j))) {\n name += ch(j);\n j++;\n }\n const end = source.indexOf(\">\", j);\n i = end === -1 ? len : end + 1;\n closeTag(stack, name.toLowerCase());\n continue;\n }\n // Not a tag start (e.g. a stray \"<\"); treat as text.\n if (!/[a-zA-Z]/.test(next)) {\n i++;\n continue;\n }\n\n // Start tag.\n const tagStart = i;\n let j = i + 1;\n let tagName = \"\";\n while (j < len && !WHITESPACE.has(ch(j)) && ch(j) !== \">\" && ch(j) !== \"/\") {\n tagName += ch(j);\n j++;\n }\n const lowerTag = tagName.toLowerCase();\n const attrs: ParsedAttr[] = [];\n\n // Parse attributes until the tag closes.\n let selfClosing = false;\n while (j < len) {\n while (j < len && WHITESPACE.has(ch(j))) j++;\n if (j >= len) break;\n if (ch(j) === \">\") {\n j++;\n break;\n }\n if (ch(j) === \"/\") {\n selfClosing = true;\n j++;\n continue;\n }\n\n // Attribute name.\n const nameStart = j;\n let attrName = \"\";\n while (j < len && !WHITESPACE.has(ch(j)) && ch(j) !== \"=\" && ch(j) !== \">\" && ch(j) !== \"/\") {\n attrName += ch(j);\n j++;\n }\n\n let attrValue = \"\";\n let valueStart: number | undefined;\n let valueEnd: number | undefined;\n // Optional value.\n let k = j;\n while (k < len && WHITESPACE.has(ch(k))) k++;\n if (ch(k) === \"=\") {\n k++;\n while (k < len && WHITESPACE.has(ch(k))) k++;\n const quote = ch(k);\n if (quote === '\"' || quote === \"'\") {\n k++;\n const valStart = k;\n while (k < len && ch(k) !== quote) k++;\n attrValue = source.slice(valStart, k);\n valueStart = valStart;\n valueEnd = k;\n k++; // skip closing quote\n } else {\n const valStart = k;\n while (k < len && !WHITESPACE.has(ch(k)) && ch(k) !== \">\") k++;\n attrValue = source.slice(valStart, k);\n valueStart = valStart;\n valueEnd = k;\n }\n j = k;\n }\n\n if (attrName.length > 0) {\n const p = pos.at(nameStart);\n attrs.push({\n name: attrName.toLowerCase(),\n value: attrValue,\n line: p.line,\n column: p.column,\n valueStart,\n valueEnd,\n });\n }\n }\n\n const startPos = pos.at(tagStart);\n const node: ElementNode = {\n tag: lowerTag,\n attrs,\n children: [],\n parent: top(),\n line: startPos.line,\n column: startPos.column,\n };\n top().children.push(node);\n\n i = j;\n\n if (selfClosing || VOID_ELEMENTS.has(lowerTag)) {\n continue;\n }\n\n if (RAW_TEXT_ELEMENTS.has(lowerTag)) {\n // Skip raw-text content so `<` inside scripts/styles is not parsed as markup.\n const closeNeedle = `</${lowerTag}`;\n const idx = source.toLowerCase().indexOf(closeNeedle, i);\n if (idx === -1) {\n i = len;\n } else {\n const gt = source.indexOf(\">\", idx);\n i = gt === -1 ? len : gt + 1;\n }\n continue;\n }\n\n stack.push(node);\n }\n\n return root;\n}\n\n/** Pops the stack down to (and including) the nearest matching open tag. */\nfunction closeTag(stack: ElementNode[], name: string): void {\n for (let depth = stack.length - 1; depth >= 1; depth--) {\n if (stack[depth]?.tag === name) {\n stack.length = depth;\n return;\n }\n }\n // No matching open tag — ignore the stray end tag.\n}\n\n/** Depth-first walk over every element node (excluding the synthetic root). */\nexport function walk(root: ElementNode, visit: (node: ElementNode) => void): void {\n for (const child of root.children) {\n visit(child);\n walk(child, visit);\n }\n}\n","/**\n * Shared types for the Stimeo Inspector CLI (`stimeo check`).\n *\n * The Inspector statically checks HTML/ERB against a *manifest* describing the\n * official `stimeo--` controllers. The same engine powers both the library's\n * own contract checks (e.g. `stimeo check app/views`) and the user-facing CLI;\n * it is therefore intentionally input-path agnostic.\n */\n\n/**\n * Per-controller manifest entry.\n *\n * `targets` and `values` are reflected from the controller class\n * (`static targets` / `static values`). `actions` and `events` are reflected\n * from co-located `static actions` / `static events` declarations — Stimulus\n * keeps no registry of action methods, and TypeScript `private` survives on the\n * prototype, so the public action/event surface cannot be told apart from\n * internal helpers by reflection alone; it must be declared explicitly in the\n * implementation. `requiredTargets` is a hand-written structure rule (Stimulus\n * reflection cannot express \"required\").\n */\nexport interface ControllerManifest {\n /** Target names declared via `static targets`. */\n readonly targets: readonly string[];\n /** Value names (camelCase) declared via `static values`. */\n readonly values: readonly string[];\n /**\n * Public action method names declared via `static actions`, wired by\n * consumers as `data-action=\"…-><identifier>#<action>\"`.\n */\n readonly actions: readonly string[];\n /**\n * Logical event names declared via `static events`, dispatched as\n * `<identifier>:<event>` (Stimulus `this.dispatch(\"<event>\")`).\n */\n readonly events: readonly string[];\n /** Targets that must be present at least once inside the controller scope. */\n readonly requiredTargets: readonly string[];\n /**\n * Target requirements that only apply once an optional target appears. See\n * {@link ConditionalTargetRule}.\n */\n readonly conditionalTargets: readonly ConditionalTargetRule[];\n /**\n * Accessibility requirements the *consumer's markup* must satisfy (stage 3):\n * ARIA attributes the controller does **not** set at runtime and therefore\n * relies on the author to provide (e.g. a dialog's `role`/`aria-modal`/name).\n * Attributes the controller manages itself (e.g. tabs' `aria-selected`) are\n * deliberately excluded — requiring them would be noise.\n */\n readonly a11y: readonly A11yRequirement[];\n /**\n * Keyboard prerequisites (stage 3): targets whose documented contract makes\n * the *author* responsible for focusability — the controller\n * moves focus (or relies on the Tab order) but never writes `tabindex` for\n * them. Each listed target must be natively focusable or carry `tabindex`.\n * Targets whose controller initializes a roving tabindex on connect (tabs,\n * toolbar, radio group, …) are deliberately excluded.\n */\n readonly keyboard: readonly KeyboardRequirement[];\n /**\n * Author-futile attributes (stage 3): ARIA the controller recomputes\n * wholesale at runtime, where an authored value can neither\n * survive nor serve as pre-connect initial state (e.g. a combobox input's\n * `aria-activedescendant`). Authoring one is reported as a *warning*.\n * Attributes whose authored value is a legitimate initial (`aria-expanded`,\n * `aria-checked`, `aria-valuenow`, …) are deliberately excluded.\n */\n readonly managedAria: readonly ManagedAriaRule[];\n /**\n * Conditional cross-controller composition rules (stage 3): value-alignment\n * contracts between this controller and a co-located companion (e.g.\n * sortable's sort axis vs roving's `orientation`). A dropped or misaligned\n * value silently breaks keyboard interaction, and no single-controller rule\n * can see it.\n */\n readonly compositions: readonly CompositionRule[];\n /**\n * Required companion controllers (stage 3): elements the contract says must\n * *also* declare another controller (e.g. an overflow menu's More\n * wrapper, whose menu behavior is delegated wholesale). Distinct from\n * {@link compositions}, which fire only once the companion is already there:\n * these fire on its **absence**, the case a rule keyed on presence can never\n * see.\n */\n readonly companions: readonly CompanionRequirement[];\n /**\n * Reverse-direction target rules (stage 3): markup that carries a pattern's\n * ARIA but was never declared as a target. Every other rule reads\n * target → required attribute; these read attribute → required target, the\n * direction in which an undeclared element is invisible to the controller\n * (and therefore to every forward rule).\n */\n readonly targetDeclarations: readonly TargetDeclarationRule[];\n /**\n * Set-level count constraints (stage 3): how many elements may or must exist\n * inside a scope or a container target. Every other family judges one element\n * at a time, which cannot express contracts of the form \"exactly one\" / \"at\n * most one\" however load-bearing they are.\n */\n readonly cardinality: readonly CardinalityRule[];\n /**\n * Attributes that must **not** be present in a given configuration\n * (stage 3). The inverse of {@link a11y}, and distinct from\n * {@link managedAria}: those attributes are futile because the *controller*\n * owns them, whereas these stay the author's to write — they are simply\n * contradicted by the markup around them (a menu declaring itself busy while\n * its items are right there).\n */\n readonly forbiddenAria: readonly ForbiddenAriaRule[];\n}\n\n/**\n * A condition on the controller's **own** Stimulus value, read from the scope\n * element. Shared by every rule family that needs one.\n *\n * The value is compared by its **effective** reading — the authored attribute,\n * or {@link default} when the attribute is absent — so a rule can be scoped to\n * a non-default configuration without flagging the default one. That is the\n * whole point: a horizontal toolbar must *not* carry\n * `aria-orientation=\"vertical\"`, so the requirement only exists in the vertical\n * configuration and an unconditional rule would reject correct markup.\n *\n * {@link default} duplicates the controller's `static values` default; a\n * manifest test guards it against drift.\n */\nexport interface ValueCondition {\n /** Value name (camelCase, as declared in `static values`). */\n readonly value: string;\n /** Effective values that arm the rule. */\n readonly equals: readonly string[];\n /** The value's declared default, used when the attribute is absent. */\n readonly default: string;\n}\n\n/**\n * A condition on how many targets an element **holds**, evaluated against the\n * very element the rule applies to — not the controller scope, the way\n * {@link ValueCondition} is. Both may appear on one rule; both must hold.\n *\n * It exists for contracts whose ARIA depends on the element's own contents\n * rather than on any configuration value. A `role=\"menu\"` requires owned\n * `menuitem`s, so a menu the consumer fills asynchronously has to declare the\n * temporary absence with `aria-busy` — a requirement that must arm on\n * emptiness alone, since the controller cannot tell \"still loading\" from\n * \"nothing to show\" and therefore never infers it.\n *\n * Bounds are inclusive and independently optional; a condition with neither is\n * meaningless and rejected by the manifest tests.\n */\nexport interface ContentCondition {\n /** Target name counted **inside** the element the rule applies to. */\n readonly target: string;\n /** Arms the rule when the count is at least this. */\n readonly min?: number;\n /** Arms the rule when the count is at most this. */\n readonly max?: number;\n}\n\n/**\n * A condition on the element's **own tag**, evaluated per element the way\n * {@link ContentCondition} is.\n *\n * It exists for roles whose accessible name ARIA marks *required* but which a\n * **native** element can name with no author ARIA at all: a\n * `<table role=\"grid\">` names from its `<caption>`, a\n * `<fieldset role=\"radiogroup\">` from its `<legend>`, an\n * `<input role=\"combobox\">` from a `<label for>`. Requiring `aria-label` on\n * those would reject correct markup, while dropping the rule outright would\n * leave the `div`-based spelling — the one with no native naming path at all —\n * unchecked. This disarms exactly the spellings that have one.\n *\n * The exemption is keyed on the **tag**, not on finding the name: a\n * `<label for>` legitimately lives in another partial, so looking for it would\n * report a missing name that is present one file over. Erring toward\n * under-detection is the same call the cardinality rules make for\n * ERB-generated values.\n */\nexport interface ElementCondition {\n /** Lowercase tag names whose native naming path disarms the requirement. */\n readonly exceptTags: readonly string[];\n}\n\n/**\n * A condition on the **whole source file**: how many elements in it carry a\n * given role. Every other condition reads one element or one scope; this one\n * reads the file.\n *\n * It exists for ARIA's *conditionally* levelled names, which come in both\n * directions: a `toolbar`'s name is \"Recommended\" and becomes \"Required if\n * multiple toolbars on a page\" ({@link A11yRequirement.escalateWhen}), while a\n * focusable `separator`'s name is discretionary and only becomes \"Recommended\n * if more than one focusable separator\" ({@link A11yRequirement.whenDocument}).\n * One raises the level of a standing requirement; the other brings a\n * requirement into existence.\n *\n * A file is not a page, so this deliberately **under**-approximates: elements\n * split across partials are counted apart and stay at the lower level. That is\n * the safe direction — it never invents a requirement the author does not have.\n */\nexport interface DocumentCondition {\n /** Role counted across the file. */\n readonly role: string;\n /** Holds when at least this many elements in the file carry {@link role}. */\n readonly atLeast: number;\n /**\n * Counts only Tab-reachable elements; omit to count every carrier of the\n * role. ARIA qualifies some of these conditions by focusability and some not:\n * a `separator`'s name matters once there is more than one **focusable**\n * separator, because that is when a user can land on both and needs to tell\n * them apart — a decorative `hr` carrying the role does not create that\n * problem. A `toolbar`'s condition has no such qualifier, so it counts all.\n */\n readonly focusable?: boolean;\n}\n\n/**\n * A single accessibility requirement on a controller's markup (Inspector\n * stage 3). At least one of {@link attrs} must be present on the\n * {@link target} element; when {@link values} is given, the present\n * attribute's value must be one of them. {@link or} widens the requirement\n * with alternative attribute/value groups — the requirement is satisfied when\n * *any* group is (e.g. `role=\"status\"` **or** `aria-live`).\n */\nexport interface A11yRequirement {\n /**\n * Target name the requirement applies to; the empty string `\"\"` means the\n * controller's own scope element (the `data-controller` node).\n */\n readonly target: string;\n /**\n * Candidate attribute names — at least one must be present. A list expresses\n * \"any of\" (e.g. `aria-labelledby` *or* `aria-label` for an accessible name).\n */\n readonly attrs: readonly string[];\n /** Allowed values for the matched attribute; omit to accept any value. */\n readonly values?: readonly string[];\n /**\n * Alternative attribute groups, each with its **own** allowed-value set —\n * something `attrs` alone cannot express (its `values` apply to every listed\n * attribute). A present attribute with a wrong value is still reported even\n * when another group is satisfied: an invalid authored value is an error in\n * its own right (e.g. `aria-live=\"off\"` silencing a satisfied `role=\"status\"`).\n */\n readonly or?: readonly A11yAlternative[];\n /**\n * Restricts the requirement to one configuration of the controller's own\n * value; omit for unconditional requirements. It exists for ARIA that is\n * mandatory in one configuration and *wrong* in another.\n */\n readonly when?: ValueCondition;\n /**\n * Restricts the requirement to elements holding a given number of a target;\n * omit for requirements that do not depend on the contents. Evaluated per\n * element, so sibling targets are judged independently.\n */\n readonly whenContains?: ContentCondition;\n /**\n * Disarms the requirement on elements whose tag already carries a native\n * naming path; omit for requirements that hold for every spelling of the\n * role.\n */\n readonly whenElement?: ElementCondition;\n /**\n * Arms the requirement only in files satisfying a file-level condition; omit\n * for requirements that apply to every file.\n *\n * Some ARIA names are optional alone and only start to matter in company: a\n * lone focusable `separator` needs no name, while a second one on the same\n * page leaves the two indistinguishable without one. Arming on the count\n * keeps the single-splitter page — by far the common one — silent, instead of\n * demanding a name that would only ever be read out as noise.\n */\n readonly whenDocument?: DocumentCondition;\n /**\n * Severity of an unmet requirement; omit for `\"error\"`.\n *\n * ARIA separates names it *requires* from names it merely *recommends*\n * (`toolbar`, `menubar`, `tablist`, `menu`). A missing recommended name is\n * real contract guidance but not a definite defect — the pattern still works\n * without it — so it reports as a warning, the bar `managed-aria` and\n * `forbidden-aria` already sit at. Reporting both levels as errors would make\n * the check say \"broken\" where ARIA says \"could be clearer\".\n */\n readonly severity?: DiagnosticSeverity;\n /**\n * Raises {@link severity} to `\"error\"` while the file-level condition holds;\n * omit for requirements whose level never moves. ARIA's conditional\n * requirements have exactly this shape — a toolbar's name is recommended on\n * its own and required once the file holds a second one, because that is the\n * point where the name stops being decoration and becomes the only way a user\n * can tell the two apart.\n */\n readonly escalateWhen?: DocumentCondition;\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/** One alternative attribute group of an {@link A11yRequirement} (`or`). */\nexport interface A11yAlternative {\n /** Candidate attribute names — at least one must be present. */\n readonly attrs: readonly string[];\n /** Allowed values for the matched attribute; omit to accept any value. */\n readonly values?: readonly string[];\n}\n\n/**\n * A keyboard prerequisite (stage 3): every present element of {@link target}\n * must be reachable by keyboard. What \"reachable\" means depends on how the\n * controller drives focus, expressed by {@link reach}:\n *\n * - `\"tab\"` (Tab stop): the element is a steady tab stop the user reaches with\n * Tab, so it must be natively tab-focusable (`button`, `input` except\n * `type=\"hidden\"`, `select`, `textarea`, `summary`, `a[href]`, `area[href]`,\n * or `contenteditable`) **or** carry `tabindex=\"0\"` (any non-negative value).\n * A `tabindex=\"-1\"` removes it from the Tab order and therefore **fails** —\n * this is the case a mere \"has tabindex\" presence check would miss.\n * - `\"focus\"` (roving / programmatic): the controller moves focus with\n * `element.focus()`, so the element only has to be focusable *at all* —\n * natively focusable **or** carrying any valid `tabindex` (including the\n * roving `-1`).\n *\n * Only the per-element floor is checked; the roving set-level invariant\n * (\"exactly one item is `tabindex=\"0\"`\") is runtime state owned by the\n * controller and deliberately out of scope.\n */\nexport interface KeyboardRequirement {\n /** Target name the requirement applies to (never the scope element). */\n readonly target: string;\n /**\n * How the user reaches the target. Defaults to `\"tab\"` (the common case —\n * most operation points are steady Tab stops); set `\"focus\"` only for\n * targets the controller roves via programmatic focus.\n */\n readonly reach?: \"tab\" | \"focus\";\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * An author-futile attribute rule (stage 3): authoring any of {@link attrs} on\n * the {@link target} element draws a `managed-aria` **warning** — the\n * controller recomputes the attribute wholesale, so the authored value is dead\n * weight that misleads readers of the markup.\n */\nexport interface ManagedAriaRule {\n /**\n * Target name the rule applies to; the empty string `\"\"` means the\n * controller's own scope element.\n */\n readonly target: string;\n /** Attribute names the controller owns outright. */\n readonly attrs: readonly string[];\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * A conditional cross-controller composition rule (stage 3): when a companion\n * controller is co-located on one of the host's elements, one of the\n * companion's values must align with a value of the host. The rule fires only\n * when {@link coController} is actually declared there — composition itself\n * stays optional (whether to compose is the author's call; the rule only\n * guards *how*).\n *\n * Both sides are compared by their **effective** value — the authored\n * attribute, or the declared default when the attribute is absent — because\n * the misalignments these rules exist for are default asymmetries (e.g.\n * sortable defaults its `orientation` to `vertical` while roving defaults to\n * `horizontal`, so a bare composition is silently broken). The defaults are\n * duplicated here from the controllers' `static values`; a manifest test\n * guards them against drift.\n */\nexport interface CompositionRule {\n /**\n * Host target whose element hosts the companion; the empty string `\"\"`\n * means the controller's own scope element.\n */\n readonly target: string;\n /**\n * Check the scope element when {@link target} is absent — for optional\n * container targets whose documented fallback is the scope element itself\n * (e.g. sortable's `list`).\n */\n readonly fallbackToScope?: boolean;\n /** Companion controller identifier expected in the element's `data-controller`. */\n readonly coController: string;\n /**\n * Condition on the host's own value (read from the scope element); omit for\n * unconditional rules. The rule applies only when the host's effective\n * value is one of `equals`.\n */\n readonly when?: ValueCondition;\n /** Requirement on the companion's value (read from the companion's element). */\n readonly require: {\n /** Companion value name (camelCase, as declared in `static values`). */\n readonly value: string;\n /**\n * Allowed effective values, **ordered**: the first entry is the canonical\n * alignment and feeds the machine fix when an authored value is wrong.\n */\n readonly oneOf: readonly string[];\n /** The companion value's declared default, used when the attribute is absent. */\n readonly default: string;\n };\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * A required companion controller (stage 3): the {@link target} element must\n * itself declare {@link controller} in its `data-controller`.\n *\n * This is the **absence** counterpart of {@link CompositionRule}. A composition\n * rule guards *how* two controllers are wired once both are present, and stays\n * silent when the companion was never added — correct for optional\n * compositions, useless for the mandatory ones. Where the host delegates a\n * whole interaction (a More wrapper whose menu semantics and keyboard handling\n * belong entirely to the menu controller), dropping the companion leaves markup\n * that renders, passes every forward rule, and simply never opens.\n */\nexport interface CompanionRequirement {\n /**\n * Target name whose element must declare the companion; the empty string\n * `\"\"` means the controller's own scope element.\n */\n readonly target: string;\n /** Companion controller identifier required in the element's `data-controller`. */\n readonly controller: string;\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * A reverse-direction target rule (stage 3): inside the controller's scope,\n * every element carrying {@link attr} (with one of {@link values}, when given)\n * must be declared as the {@link target} target.\n *\n * Forward rules ask \"does this target carry the ARIA it needs?\" and therefore\n * only ever see markup the controller already knows about. The failure this\n * rule exists for is the opposite one: markup that *looks* like part of the\n * pattern to a screen reader — it has the role — but was never wired as a\n * target, so the controller's roving, visible-item search, typeahead, and\n * selection sync all skip it. Nothing in the forward direction can detect that,\n * because the element is absent from every target set the forward rules read.\n *\n * Ownership is resolved by the **nearest** enclosing controller of the same\n * identifier, so nested instances judge only their own elements.\n */\nexport interface TargetDeclarationRule {\n /** Attribute that marks an element as part of the pattern (e.g. `role`). */\n readonly attr: string;\n /** Attribute values that mark it; omit to match any non-empty value. */\n readonly values?: readonly string[];\n /** Target name the matched element must be declared as. */\n readonly target: string;\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * A set-level count constraint (stage 3): how many {@link target} elements may\n * live inside {@link within}, optionally narrowed to those carrying\n * {@link attr}.\n *\n * Every other rule family judges elements one at a time, which cannot express\n * the two contracts that matter most in a set: \"this wrapper resolves to\n * exactly one control\" and \"no more than one element is selected\". Both fail\n * silently — a hover wrapper holding two triggers always opens the first, and a\n * second authored selection is quietly normalized away at connect, discarding\n * the author's intent with no diagnostic anywhere.\n *\n * Bounds are inclusive and independently optional; a rule with neither is\n * meaningless and rejected by the manifest tests.\n */\nexport interface CardinalityRule {\n /**\n * Container target whose element bounds the count — each container element is\n * counted separately. The empty string `\"\"` counts across the whole\n * controller scope.\n */\n readonly within: string;\n /** Target name whose elements are counted. */\n readonly target: string;\n /** Count only elements carrying this attribute; omit to count them all. */\n readonly attr?: string;\n /** Restricts {@link attr} to these values; omit to accept any value. */\n readonly values?: readonly string[];\n /** Smallest permitted count (inclusive); omit for no floor. */\n readonly min?: number;\n /** Largest permitted count (inclusive); omit for no ceiling. */\n readonly max?: number;\n /**\n * Restricts the constraint to one configuration of the controller's own\n * value; omit for unconditional constraints. Multiplicity is frequently a\n * *configured* property (a grid whose `selection` value decides whether two\n * selected rows are a bug or the point), so a fixed bound would be wrong in\n * one of the configurations.\n */\n readonly when?: ValueCondition;\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * An attribute that must **not** be present in a given configuration\n * (stage 3): authoring any of {@link attrs} on the {@link target} element —\n * with one of {@link values}, when given — contradicts the markup around it.\n *\n * Three families speak about an attribute the author might write, and the\n * difference is *why* it should go:\n *\n * - {@link A11yRequirement} — it is missing and the pattern needs it.\n * - {@link ManagedAriaRule} — the **controller** recomputes it, so any authored\n * value is dead weight in every state.\n * - This rule — the author legitimately owns the attribute, and it is even\n * required in the *other* configuration; here it simply states something the\n * surrounding markup contradicts.\n *\n * Reported as a **warning**, not an error, and deliberately so: a static reader\n * sees one file at one instant, and cannot separate a stale declaration from a\n * genuine in-progress one (a menu whose items stream in a chunk at a time is\n * correctly busy *with* items present). The markup may be lying; the page still\n * works either way.\n */\nexport interface ForbiddenAriaRule {\n /**\n * Target name the rule applies to; the empty string `\"\"` means the\n * controller's own scope element.\n */\n readonly target: string;\n /** Attribute names that must not be present. */\n readonly attrs: readonly string[];\n /** Restricts the rule to these values; omit to forbid the attribute outright. */\n readonly values?: readonly string[];\n /**\n * Restricts the rule to elements holding a given number of a target. Without\n * a condition the rule would forbid the attribute unconditionally, which is\n * {@link ManagedAriaRule}'s job — so in practice every rule here carries one.\n */\n readonly whenContains?: ContentCondition;\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/**\n * The bundled manifest. `schemaVersion` tracks the manifest *format*;\n * `packageVersion` tracks the `stimeo-ui` release it was generated from so a\n * consumer can confirm the check matches their installed version.\n */\nexport interface Manifest {\n readonly schemaVersion: number;\n readonly packageVersion: string;\n /** Keyed by controller identifier, e.g. `stimeo--menu`. */\n readonly controllers: Readonly<Record<string, ControllerManifest>>;\n}\n\n/**\n * A target requirement that only exists once another *optional* target is\n * present.\n *\n * `requiredTargets` is unconditional, which cannot express the shape two\n * controllers actually have: a feature that is entirely opt-in, but **incomplete\n * without its whole set**. A breadcrumb without any `collapsible` is a valid plain\n * trail; add one and the disclosure (`ellipsis` + `trigger`) becomes mandatory,\n * because without it the collapsed items have no control that can reveal them. A\n * file-dropzone without an `itemTemplate` never renders a list; add one without a\n * `list` and the selected files render nowhere.\n *\n * Both fail the same way: the required targets are *present enough* to pass every\n * other check, the page loads, `stimeo check` is green — and the feature silently\n * does nothing. Making the trigger target unconditionally required is not an\n * option: it would reject the plain spelling, which is the common one.\n */\nexport interface ConditionalTargetRule {\n /** The optional target whose presence turns the feature on. */\n readonly whenPresent: string;\n /** Targets that become required once {@link whenPresent} appears. */\n readonly require: readonly string[];\n /** Human-readable fix suggestion shown by the CLI (stage 4). */\n readonly suggestion: string;\n}\n\n/** Hand-written structure rules, merged into the reflected manifest. */\nexport type StructureRules = Readonly<\n Record<\n string,\n {\n readonly requiredTargets?: readonly string[];\n readonly conditionalTargets?: readonly ConditionalTargetRule[];\n }\n >\n>;\n\n/** Hand-written accessibility rules (stage 3), merged into the manifest. */\nexport type A11yRules = Readonly<Record<string, readonly A11yRequirement[]>>;\n\n/** Hand-written keyboard prerequisites (stage 3), merged into the manifest. */\nexport type KeyboardRules = Readonly<Record<string, readonly KeyboardRequirement[]>>;\n\n/** Hand-written author-futile attribute rules, merged into the manifest. */\nexport type ManagedAriaRules = Readonly<Record<string, readonly ManagedAriaRule[]>>;\n\n/** Hand-written composition rules (stage 3), merged into the manifest. */\nexport type CompositionRules = Readonly<Record<string, readonly CompositionRule[]>>;\n\n/** Hand-written required-companion rules, merged into the manifest. */\nexport type CompanionRules = Readonly<Record<string, readonly CompanionRequirement[]>>;\n\n/** Hand-written reverse-direction target rules, merged into the manifest. */\nexport type TargetDeclarationRules = Readonly<Record<string, readonly TargetDeclarationRule[]>>;\n\n/** Hand-written cardinality rules, merged into the manifest. */\nexport type CardinalityRules = Readonly<Record<string, readonly CardinalityRule[]>>;\n\n/** Hand-written forbidden-attribute rules, merged into the manifest. */\nexport type ForbiddenAriaRules = Readonly<Record<string, readonly ForbiddenAriaRule[]>>;\n\n/** Severity of a diagnostic. Only `error` affects the process exit code. */\nexport type DiagnosticSeverity = \"error\" | \"warning\";\n\n/**\n * Stable identifiers for the kinds of problems the Inspector reports. Useful\n * for testing, machine-readable output, and `data-stimeo-ignore` suppression\n * lists (which is why the set also exists as a runtime array).\n */\nexport const DIAGNOSTIC_CODES = [\n \"unknown-controller\",\n \"unknown-target\",\n \"unknown-value\",\n \"unknown-action-controller\",\n \"unknown-action-method\",\n \"orphan-target\",\n \"missing-required-target\",\n \"missing-conditional-target\",\n \"missing-aria\",\n \"invalid-aria-value\",\n \"keyboard-inaccessible\",\n \"unresolved-idref\",\n \"managed-aria\",\n \"composition-mismatch\",\n \"missing-companion\",\n \"undeclared-target\",\n \"cardinality-violation\",\n \"forbidden-aria\",\n \"unknown-ignore-code\",\n] as const;\n\n/** See {@link DIAGNOSTIC_CODES}. */\nexport type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];\n\n/**\n * A machine-applicable fix for a diagnostic: replace the source text in\n * `[start, end)` with `text`. Only emitted when the engine can compute the\n * exact range with confidence — a typo'd token inside an attribute value, or\n * a single-valued ARIA correction. Editors surface it as a quick fix; the\n * human-readable `suggestion` stays the fallback for everything else.\n */\nexport interface DiagnosticFix {\n /** Absolute source offset where the replacement starts. */\n readonly start: number;\n /** Absolute source offset just past the replaced text. */\n readonly end: number;\n /** Replacement text. */\n readonly text: string;\n /** Short imperative label for editor UI, e.g. `Replace with \"stimeo--menu\"`. */\n readonly title: string;\n}\n\n/** A single problem found in a source file. */\nexport interface Diagnostic {\n readonly code: DiagnosticCode;\n readonly severity: DiagnosticSeverity;\n readonly message: string;\n /** 1-based line where the problem was detected. */\n readonly line: number;\n /** 1-based column where the problem was detected. */\n readonly column: number;\n /**\n * Length in source characters of the anchored token starting at `column` —\n * the attribute name for attribute-anchored diagnostics, or the opening\n * `<tag` for element-anchored ones. Lets editors underline the exact token\n * instead of guessing a word boundary. Optional so hand-built reports without\n * it stay valid; consumers should fall back to `1`.\n */\n readonly length?: number;\n /**\n * Optional fix suggestion (stage 4): the corrected attribute to add, or the\n * nearest known name for a likely typo. Rendered on its own line by the CLI.\n */\n readonly suggestion?: string;\n /** Machine-applicable replacement (stage 4), when one can be computed safely. */\n readonly fix?: DiagnosticFix;\n}\n\n/** Diagnostics grouped by the file they came from. */\nexport interface FileReport {\n readonly file: string;\n readonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * Machine-readable result of `stimeo check --json`: the structured counterpart\n * of the human report, for editor tooling and CI. `files` lists only sources\n * that produced diagnostics; `ok` is true when no error-severity diagnostic was\n * found (mirrors the exit code).\n */\nexport interface CheckReport {\n /** True when no error-severity diagnostics were found. */\n readonly ok: boolean;\n /** Total number of HTML/ERB files scanned. */\n readonly checkedFiles: number;\n /** Count of error-severity diagnostics across all files. */\n readonly errorCount: number;\n /** Count of warning-severity diagnostics across all files. */\n readonly warningCount: number;\n /** Per-file reports, limited to files that produced at least one diagnostic. */\n readonly files: readonly FileReport[];\n}\n","import { neutralizeErb } from \"./erb\";\nimport {\n actionDescriptors,\n controllerIdentifiers,\n dasherize,\n isStimeoDataAttr,\n parseTargetAttr,\n parseValueAttr,\n} from \"./extract\";\nimport { type ElementNode, type ParsedAttr, parseHtml, walk } from \"./html_parser\";\nimport {\n type A11yAlternative,\n type A11yRequirement,\n type ContentCondition,\n DIAGNOSTIC_CODES,\n type Diagnostic,\n type DiagnosticCode,\n type DiagnosticFix,\n type DiagnosticSeverity,\n type DocumentCondition,\n type ElementCondition,\n type Manifest,\n type ValueCondition,\n} from \"./types\";\n\n/**\n * The core Inspector engine: checks a single HTML/ERB source string against the\n * manifest and returns diagnostics. It is **input-path agnostic** — the same\n * function backs both the project's own contract checks and the user-facing CLI.\n *\n * The check runs in staged passes:\n * - **Stage 1 (names/spelling):** every `stimeo--*` controller, target, value,\n * and `data-action` controller **and method** must exist in the manifest.\n * - **Stage 2 (structure):** required targets must be present within their\n * controller scope, and targets must have an owning controller.\n * - **Stage 3 (accessibility):** ARIA the controller relies on but does not set\n * itself (e.g. a dialog's `role`/`aria-modal`/name) must be present on the\n * relevant target, with the expected value (alternative groups via `or`), and\n * optionally only in one configuration of the controller's own value.\n * Sibling passes extend it: **keyboard prerequisites** (declared targets must\n * be focusable), **managed-aria** (author-futile attributes the controller\n * owns draw warnings), **composition** (value alignment with a co-located\n * companion), **required companions** (a delegated-to controller must be\n * present at all), **target declarations** (markup carrying a pattern's role\n * must be a declared target — the one rule family that reads\n * attribute → target rather than the reverse), **cardinality** (set-level\n * count bounds per scope or container), and **idref resolution** (ARIA\n * reference attributes on scope/target elements must point at an id declared\n * in the same file — a *warning*, since a reference may legitimately cross a\n * partial boundary the checker cannot see).\n * - **Stage 4 (fix suggestions):** diagnostics carry a `suggestion` — the\n * nearest known name for a likely typo, or the exact ARIA to add.\n *\n * Any element may opt out via {@link IGNORE_ATTR} (`data-stimeo-ignore`): an\n * empty value suppresses every diagnostic anchored at the element or its\n * descendants; a whitespace-separated {@link DiagnosticCode} list narrows the\n * suppression to those codes. Unknown codes in the list are themselves\n * reported (`unknown-ignore-code`, never suppressible).\n *\n * @remarks\n * Scope is resolved within a single source string. A controller and its targets\n * split across separate Rails partials cannot be correlated, so stage-2 checks\n * assume self-contained markup (Stimeo's recommended demo/partial structure).\n * Server-rendered **fragments** — markup a controller fetches and appends at\n * runtime (Turbo Streams, incrementally loaded list pages) — are the\n * legitimate exception:\n * declare the runtime host with {@link FRAGMENT_ATTR} on the fragment root and\n * `orphan-target` is suppressed for that identifier (names are still checked).\n * ERB is neutralized first, so dynamically-generated attributes are skipped.\n *\n * @param source - Raw HTML/ERB source.\n * @param manifest - The bundled controller manifest to check against.\n * @returns Diagnostics sorted by line then column.\n */\nexport function checkSource(source: string, manifest: Manifest): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const tree = parseHtml(neutralizeErb(source));\n const known = manifest.controllers;\n const knownIdentifiers = Object.keys(known);\n\n /** `[start, end)` offsets of every ERB tag in the raw source. */\n const erbRanges = [...source.matchAll(/<%[\\s\\S]*?%>/g)].map(\n (m) => [m.index ?? 0, (m.index ?? 0) + m[0].length] as const,\n );\n\n /**\n * Whether the attribute's value text was (even partially) ERB-generated.\n * Neutralization preserves offsets, so the parser's value range maps 1:1\n * onto the raw source.\n */\n const isDynamicValue = (attr: ParsedAttr): boolean => {\n const { valueStart, valueEnd } = attr;\n if (valueStart === undefined || valueEnd === undefined) return false;\n return erbRanges.some(([start, end]) => start < valueEnd && end > valueStart);\n };\n\n /**\n * Whether a rule's self-value condition holds for this scope, reading the\n * host's **effective** value (the authored attribute, or the rule's declared\n * default when absent). An unconditional rule always holds.\n *\n * Returns `null` when the host value is ERB-generated: the condition is then\n * undecidable, and the caller skips the rule rather than guessing at which\n * configuration the page will render in.\n */\n const conditionHolds = (\n scope: ElementNode,\n identifier: string,\n when: ValueCondition | undefined,\n ): boolean | null => {\n if (!when) return true;\n const hostAttr = scope.attrs.find(\n (a) => a.name === `data-${identifier}-${dasherize(when.value)}-value`,\n );\n if (hostAttr && isDynamicValue(hostAttr)) return null;\n return when.equals.includes(hostAttr ? hostAttr.value.trim() : when.default);\n };\n\n /** True when `node` or an ancestor opts out of `code` via the ignore attr. */\n const suppressed = (node: ElementNode, code: DiagnosticCode): boolean => {\n if (code === \"unknown-ignore-code\") return false; // meta-diagnostic: never suppressible\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const ignore = current.attrs.find((a) => a.name === IGNORE_ATTR);\n if (ignore) {\n const codes = ignore.value.trim();\n if (codes.length === 0 || codes.split(/\\s+/).includes(code)) return true;\n }\n current = current.parent;\n }\n return false;\n };\n\n /** Suppression-aware diagnostic sink; `owner` anchors the ignore lookup. */\n const report: Reporter = (owner, code, severity, message, at, suggestion, fix): void => {\n if (!suppressed(owner, code)) push(diagnostics, code, severity, message, at, suggestion, fix);\n };\n\n /** Controller scope registrations: a node declaring `data-controller`. */\n const scopes: Array<{ node: ElementNode; identifier: string }> = [];\n /** Target names found within each scope, keyed by scope node then identifier. */\n const presence = new Map<ElementNode, Map<string, Set<string>>>();\n /** Target *elements* per scope/identifier/target name, for stage-3 ARIA checks. */\n const targetNodes = new Map<ElementNode, Map<string, Map<string, ElementNode[]>>>();\n\n const recordPresence = (owner: ElementNode, identifier: string, target: string): void => {\n let byId = presence.get(owner);\n if (!byId) {\n byId = new Map();\n presence.set(owner, byId);\n }\n let set = byId.get(identifier);\n if (!set) {\n set = new Set();\n byId.set(identifier, set);\n }\n set.add(target);\n };\n\n const recordTargetNode = (\n owner: ElementNode,\n identifier: string,\n target: string,\n el: ElementNode,\n ): void => {\n let byId = targetNodes.get(owner);\n if (!byId) {\n byId = new Map();\n targetNodes.set(owner, byId);\n }\n let byName = byId.get(identifier);\n if (!byName) {\n byName = new Map();\n byId.set(identifier, byName);\n }\n const found = byName.get(target);\n if (found) found.push(el);\n else byName.set(target, [el]);\n };\n\n /**\n * Whether a rule's content condition holds for one element: how many of a\n * target the element itself holds. Unlike {@link conditionHolds} — which asks\n * about the scope's configuration — this is per element, so sibling targets\n * are judged independently. An unconditional rule always holds.\n *\n * Targets are counted from their declarations, so an ERB-generated target\n * *name* leaves an element uncounted. That biases the count downward, the\n * same direction the rest of the engine takes: the stage-2 required-target\n * check already reports such markup, so the miscount is not silent.\n */\n const contentHolds = (\n scope: ElementNode,\n identifier: string,\n element: ElementNode,\n condition: ContentCondition | undefined,\n ): boolean => {\n if (!condition) return true;\n const nodes = targetNodes.get(scope)?.get(identifier)?.get(condition.target) ?? [];\n let held = 0;\n for (const node of nodes) if (isWithin(node, element)) held += 1;\n if (condition.min !== undefined && held < condition.min) return false;\n if (condition.max !== undefined && held > condition.max) return false;\n return true;\n };\n\n /**\n * Whether the element's own tag leaves a requirement armed. A tag that names\n * the role natively — `<table>`/`<caption>`, `<fieldset>`/`<legend>`,\n * `<input>`/`<label for>` — disarms it, because the author has a correct\n * spelling that carries no ARIA at all and flagging it would be a false\n * positive. Unconditional requirements always hold.\n */\n const elementHolds = (element: ElementNode, condition: ElementCondition | undefined): boolean =>\n !condition?.exceptTags.includes(element.tag);\n\n /**\n * How many elements in this file carry each role, tallied during the walk\n * below. It backs {@link DocumentCondition}, whose question — \"is there more\n * than one of these?\" — no per-element or per-scope view can answer.\n *\n * ERB-generated role values are left out: `role=\"<%= … %>\"` could render as\n * anything, and counting it would escalate a requirement on a guess. Missing\n * one therefore under-counts, which can only *fail* to escalate — never\n * escalate wrongly.\n */\n const roleTally = new Map<string, number>();\n\n /**\n * The same tally restricted to Tab-reachable elements, for the conditions\n * ARIA qualifies by focusability. Kept as a second map rather than a filter\n * at query time because the walk is the only place the elements are in hand.\n */\n const focusableRoleTally = new Map<string, number>();\n\n /** Whether a file-level condition holds; absent conditions never escalate. */\n const documentHolds = (condition: DocumentCondition | undefined): boolean => {\n if (condition === undefined) return false;\n const tally = condition.focusable ? focusableRoleTally : roleTally;\n return (tally.get(condition.role) ?? 0) >= condition.atLeast;\n };\n\n /**\n * Attribute names any target-declaration rule matches on (e.g. `role`).\n * Collected up front so the reverse-direction pass can work from a single\n * shortlist gathered during this walk, instead of re-walking the tree once\n * per scope and rule.\n */\n const declarationAttrs = new Set<string>();\n for (const controller of Object.values(known)) {\n for (const rule of controller.targetDeclarations) declarationAttrs.add(rule.attr);\n }\n /** Elements carrying at least one {@link declarationAttrs} attribute. */\n const declarationCandidates: ElementNode[] = [];\n\n walk(tree, (node) => {\n if (declarationAttrs.size > 0 && node.attrs.some((a) => declarationAttrs.has(a.name))) {\n declarationCandidates.push(node);\n }\n const roleAttr = node.attrs.find((a) => a.name === \"role\");\n if (roleAttr && !isDynamicValue(roleAttr)) {\n const role = roleAttr.value.trim();\n roleTally.set(role, (roleTally.get(role) ?? 0) + 1);\n if (isFocusable(node, \"tab\")) {\n focusableRoleTally.set(role, (focusableRoleTally.get(role) ?? 0) + 1);\n }\n }\n for (const attr of node.attrs) {\n // --- suppression declaration: data-stimeo-ignore ---------------------\n if (attr.name === IGNORE_ATTR) {\n // Spell-check the code list so a typo'd suppression cannot silently\n // fail open. Reported directly: this meta-diagnostic is unsuppressible.\n for (const token of attr.value.split(/\\s+/).filter((t) => t.length > 0)) {\n if (!(DIAGNOSTIC_CODES as readonly string[]).includes(token)) {\n const best = nearestName(token, DIAGNOSTIC_CODES);\n push(\n diagnostics,\n \"unknown-ignore-code\",\n \"warning\",\n `Unknown diagnostic code \"${token}\" in ${IGNORE_ATTR}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, token, best),\n );\n }\n }\n continue;\n }\n\n // --- fragment declaration: data-stimeo-fragment ----------------------\n if (attr.name === FRAGMENT_ATTR) {\n const identifiers = attr.value.split(/\\s+/).filter((token) => token.length > 0);\n if (identifiers.length === 0) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `\"${FRAGMENT_ATTR}\" must name the fragment's runtime host controller(s).`,\n attr,\n );\n }\n for (const identifier of identifiers) {\n if (!(identifier in known)) {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Fragment declaration references unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n }\n }\n continue;\n }\n\n // --- data-controller -------------------------------------------------\n if (attr.name === \"data-controller\") {\n for (const identifier of controllerIdentifiers(attr.value)) {\n if (identifier in known) {\n scopes.push({ node, identifier });\n } else {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n }\n }\n continue;\n }\n\n // --- target attribute: data-{identifier}-target ----------------------\n const targetIdentifier = parseTargetAttr(attr.name);\n if (targetIdentifier) {\n const controller = known[targetIdentifier];\n if (!controller) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Target attribute \"${attr.name}\" references unknown Stimeo controller \"${targetIdentifier}\".`,\n attr,\n didYouMean(targetIdentifier, knownIdentifiers),\n );\n continue;\n }\n // Neutralization blanks the ERB tag in place, so a partly generated\n // name reads as its literal remnant (`<%= p %>item` → \"item\"). Taking\n // that reading would both silence the spelling check and register a\n // target the runtime never resolves — the same fabrication the\n // cardinality count avoids. Undecidable, exactly like a fully generated\n // name, whose blanked value already falls through the guards below.\n const targetName = isDynamicValue(attr) ? \"\" : attr.value.trim();\n if (targetName.length > 0 && !controller.targets.includes(targetName)) {\n const best = nearestName(targetName, controller.targets);\n report(\n node,\n \"unknown-target\",\n \"error\",\n `Unknown target \"${targetName}\" for \"${targetIdentifier}\". Known targets: ${list(controller.targets)}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, targetName, best),\n );\n }\n const owner = findOwner(node, targetIdentifier);\n if (owner) {\n if (targetName.length > 0) {\n recordPresence(owner, targetIdentifier, targetName);\n recordTargetNode(owner, targetIdentifier, targetName, node);\n }\n } else if (!inDeclaredFragment(node, targetIdentifier)) {\n report(\n node,\n \"orphan-target\",\n \"error\",\n `Target \"${attr.name}\" has no enclosing controller \"${targetIdentifier}\".`,\n attr,\n );\n }\n continue;\n }\n\n // --- value attribute: data-{identifier}-{value}-value ----------------\n if (isStimeoDataAttr(attr.name) && attr.name.endsWith(\"-value\")) {\n const parsed = parseValueAttr(attr.name, knownIdentifiers);\n if (parsed) {\n if (parsed.identifier === null) {\n report(\n node,\n \"unknown-controller\",\n \"error\",\n `Value attribute \"${attr.name}\" references unknown Stimeo controller.`,\n attr,\n );\n } else {\n const controller = known[parsed.identifier];\n const valid =\n controller?.values.some((v) => dasherize(v) === parsed.valueToken) ?? false;\n if (!valid) {\n report(\n node,\n \"unknown-value\",\n \"error\",\n `Unknown value \"${parsed.valueToken}\" for \"${parsed.identifier}\". Known values: ${list((controller?.values ?? []).map(dasherize))}.`,\n attr,\n didYouMean(parsed.valueToken, (controller?.values ?? []).map(dasherize)),\n );\n }\n }\n continue;\n }\n }\n\n // --- data-action descriptors: controller + method --------------------\n if (attr.name === \"data-action\") {\n for (const { identifier, method } of actionDescriptors(attr.value)) {\n const controller = known[identifier];\n if (!controller) {\n const best = nearestName(identifier, knownIdentifiers);\n report(\n node,\n \"unknown-action-controller\",\n \"error\",\n `Action references unknown Stimeo controller \"${identifier}\".`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, identifier, best),\n );\n } else if (method.length > 0 && !controller.actions.includes(method)) {\n const best = nearestName(method, controller.actions);\n report(\n node,\n \"unknown-action-method\",\n \"error\",\n `Unknown action \"${method}\" for \"${identifier}\". Known actions: ${list(controller.actions)}.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, method, best),\n );\n }\n }\n }\n }\n });\n\n // --- Stage 2: required targets per scope ---------------------------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n const present = presence.get(node)?.get(identifier) ?? new Set<string>();\n for (const required of controller.requiredTargets) {\n if (!present.has(required)) {\n report(\n node,\n \"missing-required-target\",\n \"error\",\n `\"${identifier}\" is missing required target \"${required}\".`,\n node,\n );\n }\n }\n }\n\n // --- Stage 2: conditional targets per scope ------------------------------\n // A feature that is opt-in but incomplete without its whole set. Judged from the\n // *presence* set rather than the element set: the question is only whether the\n // author declared the target anywhere in this scope.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n const present = presence.get(node)?.get(identifier) ?? new Set<string>();\n for (const rule of controller.conditionalTargets) {\n if (!present.has(rule.whenPresent)) continue;\n const missing = rule.require.filter((target) => !present.has(target));\n if (missing.length === 0) continue;\n report(\n node,\n \"missing-conditional-target\",\n \"error\",\n `\"${identifier}\" has a \"${rule.whenPresent}\" target, which also requires ${list(missing)}.`,\n node,\n rule.suggestion,\n );\n }\n }\n\n // --- Stage 3: accessibility (ARIA) per scope -----------------------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const req of controller.a11y) {\n // A conditional requirement only exists in the configuration it names —\n // outside it the attribute is not merely optional but wrong, so an\n // undecidable or unmet condition must skip the requirement entirely.\n if (conditionHolds(node, identifier, req.when) !== true) continue;\n // The root scope (\"\") is the controller element; otherwise the target's\n // own element(s). Targets that are absent are stage 2's concern, not ours\n // — we only judge accessibility of markup that is actually present.\n const elements =\n req.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(req.target) ?? []);\n // A file-level precondition arms the requirement at all; without it the\n // markup is complete as written, so nothing below should run.\n if (req.whenDocument && !documentHolds(req.whenDocument)) continue;\n // Escalation is a property of the file, not of any one element, so it is\n // resolved once per requirement rather than per element.\n const severity: DiagnosticSeverity = documentHolds(req.escalateWhen)\n ? \"error\"\n : (req.severity ?? \"error\");\n for (const el of elements) {\n // Contents are judged per element: two sibling menus of one menubar can\n // legitimately disagree about whether the requirement applies to them.\n if (!contentHolds(node, identifier, el, req.whenContains)) continue;\n // So is the tag: one file can spell the same role both natively and\n // with a div, and only the div needs the author to supply a name.\n if (!elementHolds(el, req.whenElement)) continue;\n checkA11y(report, el, identifier, req, severity);\n }\n }\n }\n\n // --- Stage 3: keyboard prerequisites per scope ---------------------------\n // Declared targets whose contract makes the author responsible for\n // focusability must be natively focusable or carry tabindex/contenteditable.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const req of controller.keyboard) {\n const reach = req.reach ?? \"tab\";\n const elements = targetNodes.get(node)?.get(identifier)?.get(req.target) ?? [];\n for (const el of elements) {\n if (!isFocusable(el, reach)) {\n const problem =\n reach === \"tab\"\n ? 'not in the Tab order (needs a native control or tabindex=\"0\")'\n : \"not focusable (needs a native control or tabindex)\";\n report(\n el,\n \"keyboard-inaccessible\",\n \"error\",\n `The \"${req.target}\" target of \"${identifier}\" is ${problem}.`,\n el,\n req.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: author-futile (controller-managed) attributes --------------\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.managedAria) {\n const elements =\n rule.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? []);\n const where = rule.target === \"\" ? \"scope element\" : `\"${rule.target}\" target`;\n for (const el of elements) {\n for (const name of rule.attrs) {\n const attr = el.attrs.find((a) => a.name === name);\n if (!attr) continue;\n report(\n el,\n \"managed-aria\",\n \"warning\",\n `${name} on the ${where} of \"${identifier}\" is managed by the controller at runtime.`,\n attr,\n rule.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: attributes forbidden by the surrounding markup -------------\n // The pass above reports attributes the *controller* owns; this one reports\n // attributes the author owns that contradict what is around them — required\n // in one configuration of the element's contents and wrong in the other.\n // Warning severity, because one file at one instant cannot tell a stale\n // declaration from a genuinely in-progress one.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.forbiddenAria) {\n const elements =\n rule.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? []);\n const where = rule.target === \"\" ? \"scope element\" : `\"${rule.target}\" target`;\n for (const el of elements) {\n if (!contentHolds(node, identifier, el, rule.whenContains)) continue;\n for (const name of rule.attrs) {\n const attr = el.attrs.find((a) => a.name === name);\n if (!attr) continue;\n // An ERB-generated value could render to anything, so a rule that\n // names specific values cannot decide it. A rule forbidding the\n // attribute outright still can: presence is static.\n if (rule.values && (isDynamicValue(attr) || !rule.values.includes(attr.value.trim()))) {\n continue;\n }\n report(\n el,\n \"forbidden-aria\",\n \"warning\",\n `${name} on the ${where} of \"${identifier}\" contradicts the markup around it.`,\n attr,\n rule.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: cross-controller composition values ------------------------\n // Value-alignment contracts between a host controller and a co-located\n // companion (e.g. sortable's sort axis vs roving's orientation). Both sides\n // are judged by their *effective* value — the authored attribute, or the\n // rule's declared default when absent — because these contracts exist\n // precisely where the companion's default does not match the host's. An\n // ERB-generated value on either side makes the rule undecidable, so it is\n // skipped rather than guessed at.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.compositions) {\n const targeted = targetNodes.get(node)?.get(identifier)?.get(rule.target);\n // An absent optional container target falls back to the scope element\n // when the rule says the runtime does the same (e.g. sortable's `list`).\n const elements =\n rule.target === \"\" ? [node] : (targeted ?? (rule.fallbackToScope ? [node] : []));\n const where = rule.target === \"\" || !targeted ? \"scope element\" : `\"${rule.target}\" target`;\n const when = rule.when;\n if (conditionHolds(node, identifier, when) !== true) continue;\n const hostContext = when ? ` (${when.value} ${list(when.equals)})` : \"\";\n for (const el of elements) {\n const declared = el.attrs.find((a) => a.name === \"data-controller\");\n if (!declared || !controllerIdentifiers(declared.value).includes(rule.coController)) {\n continue;\n }\n const coAttrName = `data-${rule.coController}-${dasherize(rule.require.value)}-value`;\n const coAttr = el.attrs.find((a) => a.name === coAttrName);\n if (coAttr && isDynamicValue(coAttr)) continue;\n const effective = coAttr ? coAttr.value.trim() : rule.require.default;\n if (rule.require.oneOf.includes(effective)) continue;\n const [canonical] = rule.require.oneOf;\n if (!coAttr) {\n report(\n el,\n \"composition-mismatch\",\n \"error\",\n `\"${identifier}\"${hostContext} requires the co-located \"${rule.coController}\" on its ${where} to set ${coAttrName} to ${list(rule.require.oneOf)} (its default is \"${rule.require.default}\").`,\n el,\n rule.suggestion,\n );\n } else {\n report(\n el,\n \"composition-mismatch\",\n \"error\",\n `${coAttrName}=\"${coAttr.value}\" on the ${where} of \"${identifier}\"${hostContext} must be ${list(rule.require.oneOf)}.`,\n coAttr,\n rule.suggestion,\n canonical !== undefined\n ? valueFix(coAttr, canonical, `Set ${coAttrName} to \"${canonical}\"`)\n : undefined,\n );\n }\n }\n }\n }\n\n // --- Stage 3: required companion controllers -----------------------------\n // The mirror image of the composition pass: that one guards *how* a\n // co-located companion is configured and stays silent when it was never\n // added, which is right for optional compositions and blind to the mandatory\n // ones. Here the companion carries behavior the host never implements, so its\n // absence is the failure — reported on the element that should have declared\n // it. An ERB-generated `data-controller` is undecidable and skipped.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.companions) {\n const elements =\n rule.target === \"\"\n ? [node]\n : (targetNodes.get(node)?.get(identifier)?.get(rule.target) ?? []);\n const where = rule.target === \"\" ? \"scope element\" : `\"${rule.target}\" target`;\n for (const el of elements) {\n const declared = el.attrs.find((a) => a.name === \"data-controller\");\n if (declared && isDynamicValue(declared)) continue;\n if (declared && controllerIdentifiers(declared.value).includes(rule.controller)) continue;\n report(\n el,\n \"missing-companion\",\n \"error\",\n `The ${where} of \"${identifier}\" must also declare \"${rule.controller}\" in data-controller.`,\n declared ?? el,\n rule.suggestion,\n // Appending to an existing list is unambiguous; creating the\n // attribute from nothing is an insertion the anchor cannot express.\n declared\n ? valueFix(\n declared,\n `${declared.value.trim()} ${rule.controller}`.trim(),\n `Add \"${rule.controller}\" to data-controller`,\n )\n : undefined,\n );\n }\n }\n }\n\n // --- Stage 3: reverse-direction target declarations ----------------------\n // Elements that wear the pattern's role but were never declared as a target.\n // Every forward rule reads the controller's target set, so this is the one\n // failure they structurally cannot see: to them the element does not exist,\n // while assistive technology announces it as part of the widget. Ownership\n // goes to the *nearest* enclosing controller of the same identifier, so\n // nested instances judge only their own subtree.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n if (controller.targetDeclarations.length === 0) continue;\n const targetAttrName = `data-${identifier}-target`;\n for (const rule of controller.targetDeclarations) {\n for (const el of declarationCandidates) {\n const marker = el.attrs.find((a) => a.name === rule.attr);\n if (!marker || isDynamicValue(marker)) continue;\n const value = marker.value.trim();\n if (value.length === 0) continue;\n if (rule.values && !rule.values.includes(value)) continue;\n if (findOwner(el, identifier) !== node) continue;\n const declaredAs = el.attrs.find((a) => a.name === targetAttrName);\n if (declaredAs && !isDynamicValue(declaredAs) && declaredAs.value.trim() === rule.target) {\n continue;\n }\n if (declaredAs && isDynamicValue(declaredAs)) continue;\n report(\n el,\n \"undeclared-target\",\n \"error\",\n `${rule.attr}=\"${value}\" inside \"${identifier}\" is not declared as its \"${rule.target}\" target, so the controller never manages it.`,\n marker,\n rule.suggestion,\n );\n }\n }\n }\n\n // --- Stage 3: set-level cardinality --------------------------------------\n // Counts, not per-element judgements: \"exactly one trigger in this wrapper\",\n // \"at most one selected option\". Both failures are silent at runtime — the\n // first extra element is either ignored forever or normalized away on connect\n // — so the authored source is the only place the mistake is still visible.\n // Counting follows the runtime's own ownership rule: the Stimulus target set.\n for (const { node, identifier } of scopes) {\n const controller = known[identifier];\n if (!controller) continue;\n for (const rule of controller.cardinality) {\n if (conditionHolds(node, identifier, rule.when) !== true) continue;\n const byName = targetNodes.get(node)?.get(identifier);\n const counted = byName?.get(rule.target) ?? [];\n const containers = rule.within === \"\" ? [node] : (byName?.get(rule.within) ?? []);\n const what = describeCounted(rule.target, rule.attr, rule.values);\n const where = rule.within === \"\" ? \"controller scope\" : `\"${rule.within}\" target`;\n for (const container of containers) {\n // Counted by their *literal* markup. A rule that pins specific values\n // skips any ERB-touched one: neutralization blanks the tag in place, so\n // reading what is left would take `<%= prefix %>true` for a literal\n // \"true\" and invent a match the rendering may never produce. Dropping\n // it under-counts instead, which can only hide a violation, never\n // fabricate one. A rule that merely requires the attribute counts it\n // either way, and correctly so: presence is static even when the value\n // is not. Either way the literal elements stand on their own, so a\n // definite over-count among them is still reported rather than waved\n // off as undecidable — `aria-selected=\"<%= … %>\"` is ordinary Rails,\n // and letting one sibling switch the whole rule off would leave it\n // firing on almost no real markup.\n const matched: Array<{ el: ElementNode; at: Anchor }> = [];\n for (const el of counted) {\n if (!isWithin(el, container)) continue;\n if (rule.attr === undefined) {\n matched.push({ el, at: el });\n continue;\n }\n const attr = el.attrs.find((a) => a.name === rule.attr);\n if (!attr) continue;\n if (rule.values && (isDynamicValue(attr) || !rule.values.includes(attr.value.trim()))) {\n continue;\n }\n matched.push({ el, at: attr });\n }\n if (rule.max !== undefined && matched.length > rule.max) {\n // Anchored on the elements *past* the limit: the ones the runtime\n // drops. The first `max` are the selection the page will actually\n // show, so pointing at them would name the wrong markup.\n for (const { el, at } of matched.slice(rule.max)) {\n report(\n el,\n \"cardinality-violation\",\n \"error\",\n `\"${identifier}\" allows at most ${rule.max} ${what} per ${where}, but found ${matched.length}.`,\n at,\n rule.suggestion,\n );\n }\n }\n if (rule.min !== undefined && matched.length < rule.min) {\n // Nothing to point at when the count is short, so the container is\n // the anchor — it is also the element the author has to fix.\n report(\n container,\n \"cardinality-violation\",\n \"error\",\n `\"${identifier}\" requires at least ${rule.min} ${what} per ${where}, but found ${matched.length}.`,\n container,\n rule.suggestion,\n );\n }\n }\n }\n }\n\n // --- Stage 3: ARIA idref resolution --------------------------------------\n // Scope/target elements are where the rules above push authors to write\n // reference attributes; a token that resolves to no id in the same file is\n // (at best) split across partials and (at worst) a typo that silently\n // empties an accessible name. Warning severity: only this file is visible.\n const ids = new Set<string>();\n walk(tree, (node) => {\n const id = node.attrs.find((a) => a.name === \"id\");\n if (!id || isDynamicValue(id)) return;\n const value = id.value.trim();\n if (value.length > 0 && !/\\s/.test(value)) ids.add(value);\n });\n\n const anchored = new Set<ElementNode>(scopes.map((scope) => scope.node));\n for (const byIdentifier of targetNodes.values()) {\n for (const byName of byIdentifier.values()) {\n for (const els of byName.values()) {\n for (const el of els) anchored.add(el);\n }\n }\n }\n for (const el of anchored) {\n for (const attr of el.attrs) {\n if (!IDREF_ATTRS.has(attr.name) || isDynamicValue(attr)) continue;\n for (const token of attr.value.split(/\\s+/).filter((t) => t.length > 0)) {\n if (!ids.has(token)) {\n const best = nearestName(token, [...ids]);\n report(\n el,\n \"unresolved-idref\",\n \"warning\",\n `${attr.name} references id \"${token}\", but no element in this file declares it.`,\n attr,\n asDidYouMean(best),\n tokenFix(attr, token, best),\n );\n }\n }\n }\n }\n\n diagnostics.sort((a, b) => a.line - b.line || a.column - b.column);\n return diagnostics;\n}\n\n/**\n * Where a diagnostic is anchored in the source: an attribute (position of the\n * attribute name) or an element (position of the tag's `<`). Knowing which of\n * the two it is lets {@link push} derive the anchored token's length.\n */\ntype Anchor = ParsedAttr | ElementNode;\n\n/** Suppression-aware diagnostic sink bound to a source's ignore declarations. */\ntype Reporter = (\n owner: ElementNode,\n code: DiagnosticCode,\n severity: DiagnosticSeverity,\n message: string,\n at: Anchor,\n suggestion?: string,\n fix?: DiagnosticFix,\n) => void;\n\n/**\n * Checks one accessibility requirement against a present element. The base\n * `attrs`/`values` pair and each `or` alternative are alternatives (OR): the\n * requirement is met when at least one candidate attribute is present.\n *\n * Value checking is resolved **per attribute name** by unioning the allowed\n * values across every group that lists that name — so a value valid in *any*\n * of its groups is accepted (a group without `values` accepts anything). This\n * matters when the same attribute appears in more than one group: a value\n * that is valid in one group must not be flagged just because another group\n * lists a different set. Distinct attributes still stand alone, so an authored\n * `aria-live=\"off\"` is flagged even next to a valid `role=\"status\"`.\n *\n * `severity` applies to the **missing** case only. A present attribute holding\n * a value the rule rejects stays an `error` whatever level the requirement\n * carries: the author demonstrably meant to satisfy the rule and got it wrong,\n * which is a definite defect, not the \"could be clearer\" the recommended level\n * describes. This is the same reasoning that reports an invalid value even when\n * another `or` group is already satisfied.\n */\nfunction checkA11y(\n report: Reporter,\n el: ElementNode,\n identifier: string,\n req: A11yRequirement,\n severity: DiagnosticSeverity,\n): void {\n const groups: readonly A11yAlternative[] = [\n { attrs: req.attrs, values: req.values },\n ...(req.or ?? []),\n ];\n const where = req.target === \"\" ? \"scope element\" : `\"${req.target}\" target`;\n\n // Per attribute name: the union of allowed values across the groups that\n // list it (`anyValue` when some group leaves the value unconstrained).\n const allowedByAttr = new Map<string, { anyValue: boolean; values: Set<string> }>();\n for (const group of groups) {\n for (const name of group.attrs) {\n let entry = allowedByAttr.get(name);\n if (!entry) {\n entry = { anyValue: false, values: new Set() };\n allowedByAttr.set(name, entry);\n }\n if (!group.values) entry.anyValue = true;\n else for (const value of group.values) entry.values.add(value);\n }\n }\n\n const invalid: Array<{ attr: ParsedAttr; values: readonly string[] }> = [];\n let anyPresent = false;\n for (const [name, allowed] of allowedByAttr) {\n const attr = el.attrs.find((a) => a.name === name);\n if (!attr) continue;\n anyPresent = true;\n if (!allowed.anyValue && !allowed.values.has(attr.value.trim())) {\n invalid.push({ attr, values: [...allowed.values] });\n }\n }\n\n if (!anyPresent) {\n // The verb tracks the level: saying \"requires\" for ARIA's *recommended*\n // names would misreport the contract in the one line most readers act on.\n const verb = severity === \"warning\" ? \"recommends\" : \"requires\";\n report(\n el,\n \"missing-aria\",\n severity,\n `\"${identifier}\" ${verb} ${describeAttrs([...allowedByAttr.keys()])} on its ${where}.`,\n el,\n req.suggestion,\n );\n return;\n }\n for (const { attr, values } of invalid) {\n // The attribute exists but holds a wrong value, so the rule's \"Add …\"\n // suggestion would mislead — point at the value fix instead. When exactly\n // one value is allowed the correction is unambiguous, so emit it as a\n // machine fix too; multi-valued rules stay a human decision.\n const [only] = values;\n report(\n el,\n \"invalid-aria-value\",\n \"error\",\n `${attr.name}=\"${attr.value}\" is not valid on the ${where} of \"${identifier}\". Expected ${list(values)}.`,\n attr,\n `Set ${attr.name} to ${list(values)}.`,\n values.length === 1 && only !== undefined\n ? valueFix(attr, only, `Set ${attr.name} to \"${only}\"`)\n : undefined,\n );\n }\n}\n\n/** Whether `node` is `container` itself or lives inside it. */\nfunction isWithin(node: ElementNode, container: ElementNode): boolean {\n let current: ElementNode | null = node;\n while (current) {\n if (current === container) return true;\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Names what a cardinality rule counts, e.g. `\"option\" targets with\n * aria-selected=\"true\"` — so the diagnostic says which subset the number\n * refers to rather than leaving the reader to infer it from the bound.\n */\nfunction describeCounted(\n target: string,\n attr: string | undefined,\n values: readonly string[] | undefined,\n): string {\n if (attr === undefined) return `\"${target}\" targets`;\n const constrained = values && values.length > 0 ? ` set to ${list(values)}` : \"\";\n return `\"${target}\" targets with ${attr}${constrained}`;\n}\n\n/** Tags focusable without an authored `tabindex` (input handled separately). */\nconst NATIVE_FOCUSABLE_TAGS = new Set([\"button\", \"select\", \"textarea\", \"summary\"]);\n\n/**\n * Whether the tag is natively focusable **as authored**. `input` is focusable\n * *unless* `type=\"hidden\"` (never rendered, never focusable); `a`/`area` are\n * focusable only with an `href`. Deliberately does **not** consider `disabled`,\n * `hidden`, or `inert`: those are usually intentional states, and — crucially —\n * this library's roving contracts keep items inside an ancestor-`hidden`\n * container until opened (a closed `<ul role=\"menu\" hidden>`), so treating them\n * as non-focusable would false-positive on every correct menu.\n */\nfunction isNativelyFocusable(el: ElementNode): boolean {\n if (NATIVE_FOCUSABLE_TAGS.has(el.tag)) return true;\n if (el.tag === \"input\") {\n const type = (el.attrs.find((a) => a.name === \"type\")?.value ?? \"\").trim().toLowerCase();\n return type !== \"hidden\";\n }\n if (el.tag === \"a\" || el.tag === \"area\") return el.attrs.some((a) => a.name === \"href\");\n return false;\n}\n\n/** Parsed integer `tabindex`, or `null` when absent or not a valid integer. */\nfunction tabindexValue(el: ElementNode): number | null {\n const attr = el.attrs.find((a) => a.name === \"tabindex\");\n if (!attr) return null;\n const parsed = Number.parseInt(attr.value.trim(), 10);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\n/**\n * Static focusability floor for the keyboard-prerequisite pass, per the rule's\n * {@link KeyboardRequirement.reach}:\n *\n * - `\"tab\"`: the element must be in the Tab order — natively focusable /\n * `contenteditable` with no `tabindex`, or `tabindex >= 0`. A `tabindex=\"-1\"`\n * (or a present-but-invalid value) fails, catching the \"removed from Tab\n * order\" bug a presence-only check would miss.\n * - `\"focus\"`: the controller focuses it programmatically, so any valid\n * `tabindex` (including the roving `-1`), a natively focusable element, or\n * `contenteditable` suffices.\n *\n * Presence-only otherwise — the set-level roving invariant is runtime state.\n */\nfunction isFocusable(el: ElementNode, reach: \"tab\" | \"focus\"): boolean {\n const hasTabindex = el.attrs.some((a) => a.name === \"tabindex\");\n if (hasTabindex) {\n const value = tabindexValue(el);\n if (value === null) return false; // present but invalid → not reliably focusable\n return reach === \"tab\" ? value >= 0 : true;\n }\n return isNativelyFocusable(el) || isContentEditable(el);\n}\n\n/**\n * Whether `contenteditable` makes the element focusable. Bare `contenteditable`\n * / `=\"true\"` / `=\"plaintext-only\"` are editable (focusable); only the explicit\n * `=\"false\"` opts out, so it must not count as focusable.\n */\nfunction isContentEditable(el: ElementNode): boolean {\n const attr = el.attrs.find((a) => a.name === \"contenteditable\");\n return attr !== undefined && attr.value.trim().toLowerCase() !== \"false\";\n}\n\n/**\n * ARIA attributes whose value is an idref (list); the idref-resolution pass\n * checks each token against the ids declared in the same file.\n */\nconst IDREF_ATTRS = new Set([\n \"aria-activedescendant\",\n \"aria-controls\",\n \"aria-describedby\",\n \"aria-details\",\n \"aria-errormessage\",\n \"aria-flowto\",\n \"aria-labelledby\",\n \"aria-owns\",\n]);\n\n/**\n * Opts an element (and its subtree) out of diagnostics: an empty value\n * suppresses everything, a whitespace-separated {@link DiagnosticCode} list\n * suppresses exactly those codes. The escape hatch for the rare markup the\n * static rules cannot see well enough (a reference resolved in another\n * partial, an intentionally exotic composition) — each use is greppable and\n * reviewable. Single-dash namespace like {@link FRAGMENT_ATTR}, so it can\n * never collide with a controller's own attribute namespace.\n */\nconst IGNORE_ATTR = \"data-stimeo-ignore\";\n\n/** Climbs the ancestor chain (including `node`) for the nearest owning scope. */\nfunction findOwner(node: ElementNode, identifier: string): ElementNode | null {\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const dataController = current.attrs.find((a) => a.name === \"data-controller\");\n if (dataController && controllerIdentifiers(dataController.value).includes(identifier)) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\n/**\n * Declares a server-rendered **fragment**: markup a controller fetches and\n * appends at runtime inside its own scope (a Turbo Stream template, an\n * incrementally fetched page of list items). Its value is the runtime host —\n * whitespace-separated `stimeo--*` identifiers. Targets inside the declaration\n * are exempt from `orphan-target` for exactly those identifiers; every name is\n * still spell-checked against the manifest, including the declaration itself.\n * Deliberately single-dash (`data-stimeo-`, not `data-stimeo--`) so it can never\n * collide with a controller's own `data-stimeo--<id>-*` attribute namespace.\n */\nconst FRAGMENT_ATTR = \"data-stimeo-fragment\";\n\n/** Whether `node` (or an ancestor) declares itself a fragment of `identifier`. */\nfunction inDeclaredFragment(node: ElementNode, identifier: string): boolean {\n let current: ElementNode | null = node;\n while (current && current.tag !== \"#root\") {\n const declared = current.attrs.find((a) => a.name === FRAGMENT_ATTR);\n if (declared?.value.split(/\\s+/).includes(identifier)) return true;\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Length of the token an anchor points at: the attribute name, or the opening\n * `<tag` (the `<` plus the tag name) for element anchors.\n */\nfunction anchorLength(at: Anchor): number {\n return \"name\" in at ? at.name.length : at.tag.length + 1;\n}\n\n/** Appends a diagnostic positioned at the given source location. */\nfunction push(\n out: Diagnostic[],\n code: DiagnosticCode,\n severity: DiagnosticSeverity,\n message: string,\n at: Anchor,\n suggestion?: string,\n fix?: DiagnosticFix,\n): void {\n out.push({\n code,\n severity,\n message,\n line: at.line,\n column: at.column,\n length: anchorLength(at),\n suggestion,\n fix,\n });\n}\n\n/**\n * Machine fix replacing one occurrence of `token` inside the attribute's\n * value with `replacement`. Returns undefined when there is no replacement,\n * the attribute is boolean (no value offsets), or the token cannot be located\n * verbatim. Uses the first occurrence — a value repeating the same broken\n * token is pathological enough that fixing the first is still the right edit.\n */\nfunction tokenFix(\n attr: ParsedAttr,\n token: string,\n replacement: string | undefined,\n): DiagnosticFix | undefined {\n if (replacement === undefined || attr.valueStart === undefined || token.length === 0) {\n return undefined;\n }\n const index = attr.value.indexOf(token);\n if (index < 0) return undefined;\n const start = attr.valueStart + index;\n return {\n start,\n end: start + token.length,\n text: replacement,\n title: `Replace with \"${replacement}\"`,\n };\n}\n\n/** Machine fix replacing the attribute's entire value. */\nfunction valueFix(attr: ParsedAttr, replacement: string, title: string): DiagnosticFix | undefined {\n if (attr.valueStart === undefined || attr.valueEnd === undefined) return undefined;\n return { start: attr.valueStart, end: attr.valueEnd, text: replacement, title };\n}\n\n/** Formats a name list for human-readable messages. */\nfunction list(names: readonly string[]): string {\n return names.length > 0 ? names.map((n) => `\"${n}\"`).join(\", \") : \"(none)\";\n}\n\n/** Describes a set of \"any of\" attributes, e.g. `aria-labelledby or aria-label`. */\nfunction describeAttrs(attrs: readonly string[]): string {\n return attrs.length === 1 ? (attrs[0] as string) : attrs.join(\" or \");\n}\n\n/**\n * Stage-4 typo candidate: the nearest known name when it is close enough to\n * be a plausible misspelling, else undefined. The threshold scales with name\n * length but is capped, so unrelated names never produce a misleading match.\n * Feeds both the human suggestion ({@link didYouMean}) and the machine fix.\n */\nfunction nearestName(name: string, candidates: readonly string[]): string | undefined {\n if (name.length === 0) return undefined;\n let best: string | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const distance = levenshtein(name, candidate);\n if (distance < bestDistance) {\n bestDistance = distance;\n best = candidate;\n }\n }\n const threshold = Math.min(3, Math.floor(name.length / 2) + 1);\n return best !== undefined && bestDistance <= threshold ? best : undefined;\n}\n\n/** Formats a {@link nearestName} candidate as the human-readable suggestion. */\nfunction asDidYouMean(best: string | undefined): string | undefined {\n return best === undefined ? undefined : `Did you mean \"${best}\"?`;\n}\n\n/**\n * Stage-4 typo suggestion: `Did you mean \"x\"?`, or undefined when nothing is\n * close. Exported for the MCP server's `stimeo_controller` unknown-id hint.\n */\nexport function didYouMean(name: string, candidates: readonly string[]): string | undefined {\n return asDidYouMean(nearestName(name, candidates));\n}\n\n/** Classic dynamic-programming Levenshtein edit distance. */\nfunction levenshtein(a: string, b: string): number {\n const rows = a.length;\n const cols = b.length;\n if (rows === 0) return cols;\n if (cols === 0) return rows;\n let prev = Array.from({ length: cols + 1 }, (_, j) => j);\n for (let i = 1; i <= rows; i++) {\n const curr = [i];\n for (let j = 1; j <= cols; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(\n (curr[j - 1] as number) + 1,\n (prev[j] as number) + 1,\n (prev[j - 1] as number) + cost,\n );\n }\n prev = curr;\n }\n return prev[cols] as number;\n}\n","import { checkSource } from \"./check\";\nimport type { Manifest } from \"./types\";\n\n/**\n * Bundled example index for the MCP server (`stimeo_example` tool and\n * `stimeo://examples/*` resources).\n *\n * The examples are the demo sidecars shipped with the library — the exact\n * markup users copy — so they are the closest thing the project has to\n * \"verified reference markup\". `scripts/postbuild.ts` walks them at build time\n * (`scripts/demo_sources.ts` locates the demo tree) and serializes the result\n * of {@link buildExamplesIndex} into `dist/inspector/examples.json`, next to\n * `manifest.json`.\n *\n * {@link buildExamplesIndex} is pure so the mapping and the verification gate\n * are unit-tested directly; the filesystem walk stays in the build scripts.\n */\n\n/** Format version of `examples.json` (bumped on breaking shape changes). */\nexport const EXAMPLES_SCHEMA_VERSION = 1;\n\n/** One bundled example: the demo markup shipped for a single controller. */\nexport interface ExampleEntry {\n /**\n * Repo-relative path the example was read from, e.g.\n * `examples/menu/_demo.html.erb`.\n */\n readonly file: string;\n /** The HTML/ERB source. */\n readonly source: string;\n}\n\n/** The bundled `examples.json`: verified demo markup keyed by controller id. */\nexport interface ExamplesIndex {\n readonly schemaVersion: number;\n /** Keyed by controller identifier, e.g. `stimeo--menu`. Keys are sorted. */\n readonly examples: Readonly<Record<string, ExampleEntry>>;\n}\n\n/** One demo sidecar as discovered on disk by the build script. */\nexport interface DemoSource {\n /** Demo directory basename (snake_case), e.g. `tree_view`. */\n readonly dir: string;\n /** Repo-relative path of the `_demo.html.erb` file. */\n readonly file: string;\n /** The file's contents. */\n readonly source: string;\n}\n\n/**\n * Maps a demo directory basename to its controller identifier. Demo dirs use\n * snake_case (`date_range_picker`); controller identifiers are the `stimeo--`\n * prefix plus the kebab-case name (`stimeo--date-range-picker`).\n * {@link buildExamplesIndex} enforces a 1:1 mapping between the demos tree and\n * the manifest.\n */\nexport function demoDirToControllerId(dir: string): string {\n return `stimeo--${dir.replaceAll(\"_\", \"-\")}`;\n}\n\n/**\n * Controllers temporarily exempted from the demo/manifest bijection. The\n * reverse check fails when an exempted controller gains a demo, so every entry\n * must be removed as soon as its exemption is no longer needed.\n */\nexport const PENDING_DEMO_CONTROLLERS: ReadonlySet<string> = new Set([]);\n\n/**\n * Builds the bundled example index from the discovered demo sidecars,\n * enforcing two invariants so \"verified example\" stays true:\n *\n * 1. **Bijection with the manifest.** Every demo dir must map to a known\n * controller and every controller must have a demo — a mismatch on either\n * side means the demos and the library drifted, and the build must fail\n * loudly rather than silently ship a hole. The only exception is the\n * explicit `pendingDemos` allowlist ({@link PENDING_DEMO_CONTROLLERS}):\n * a documented \"demo not built yet\" deferral, kept honest by the reverse\n * check (an allowlisted controller acquiring a demo fails the build until\n * the stale entry is removed).\n * 2. **Check-clean.** Every example must pass {@link checkSource} with no\n * error-severity diagnostics against the same manifest it ships with.\n *\n * @throws Error listing every violation when an invariant is broken.\n */\nexport function buildExamplesIndex(\n demos: readonly DemoSource[],\n manifest: Manifest,\n pendingDemos: ReadonlySet<string> = PENDING_DEMO_CONTROLLERS,\n): ExamplesIndex {\n const problems: string[] = [];\n const byId = new Map<string, DemoSource>();\n for (const demo of demos) {\n const id = demoDirToControllerId(demo.dir);\n if (!Object.hasOwn(manifest.controllers, id)) {\n problems.push(`demo \"${demo.dir}\" maps to unknown controller \"${id}\"`);\n continue;\n }\n if (byId.has(id)) {\n problems.push(`controller \"${id}\" has more than one demo source`);\n continue;\n }\n byId.set(id, demo);\n }\n for (const id of Object.keys(manifest.controllers)) {\n if (byId.has(id) || pendingDemos.has(id)) continue;\n problems.push(`controller \"${id}\" has no demo example`);\n }\n for (const id of pendingDemos) {\n if (byId.has(id)) {\n problems.push(\n `controller \"${id}\" is allowlisted as pending but now has a demo — ` +\n \"remove it from PENDING_DEMO_CONTROLLERS\",\n );\n }\n }\n for (const [id, demo] of byId) {\n const errors = checkSource(demo.source, manifest).filter((d) => d.severity === \"error\");\n for (const d of errors) {\n problems.push(`example for \"${id}\" fails check: ${d.line}:${d.column} ${d.message}`);\n }\n }\n if (problems.length > 0) {\n throw new Error(`examples index build failed:\\n - ${problems.join(\"\\n - \")}`);\n }\n // Null-prototype dictionary, mirroring runCatalogTool: ids derive from\n // directory names, and a hostile \"__proto__\" would otherwise rewrite the\n // dictionary's prototype instead of storing the entry.\n const examples: Record<string, ExampleEntry> = Object.create(null);\n for (const id of [...byId.keys()].sort()) {\n const demo = byId.get(id);\n if (!demo) continue;\n examples[id] = { file: demo.file, source: demo.source };\n }\n return { schemaVersion: EXAMPLES_SCHEMA_VERSION, examples };\n}\n","import { extname } from \"node:path\";\n\n/**\n * Single source of truth for which files the Inspector checks. Shared by the\n * CLI's directory walk and the VS Code extension's document filter so a file\n * never gets diagnostics in one surface and a silent pass in the other.\n */\n\n/** Final extensions (lowercased) the Inspector understands. `.html.erb` ends with `.erb`. */\nconst CHECKABLE_FILE_EXTENSIONS = new Set([\".erb\", \".html\", \".htm\"]);\n\n/**\n * Whether the path names a checkable HTML/ERB file. Matches on the *final*\n * extension only (`extname`), case-insensitively — case-only variants like\n * `legacy.HTM` are the same file on the case-insensitive filesystems most\n * Rails apps are edited on (macOS/Windows), so they must not slip past CI\n * while the editor flags them.\n */\nexport function isCheckableFile(path: string): boolean {\n return CHECKABLE_FILE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n","import { readFileSync } from \"node:fs\";\nimport type { Manifest } from \"./types\";\n\n/**\n * Loading and shape-validation of `manifest.json` files, shared by every\n * consumer that reads a manifest from disk: the CLI (the copy bundled next to\n * `cli_bin.js`), the VS Code extension (a workspace's installed copy or its\n * bundled snapshot), and the MCP server. Keeping the guard in one place means a\n * corrupt or cross-version manifest degrades the same way everywhere instead of\n * crashing one surface and passing another.\n */\n\n/**\n * Array-typed fields the engine iterates on every controller entry. Fields\n * nested *inside* an a11y requirement need no entry here — they ride along as\n * parsed JSON and are never iterated blindly.\n */\nconst CONTROLLER_ARRAY_FIELDS = [\n \"targets\",\n \"values\",\n \"actions\",\n \"events\",\n \"requiredTargets\",\n \"conditionalTargets\",\n \"a11y\",\n \"keyboard\",\n \"managedAria\",\n \"compositions\",\n \"companions\",\n \"targetDeclarations\",\n \"cardinality\",\n \"forbiddenAria\",\n] as const;\n\n/**\n * Structural guard for a parsed manifest. A reader bundles the engine of one\n * schema version but may load a manifest written by another — an installed copy\n * missing a field this engine iterates unconditionally — and an unvalidated\n * manifest would crash every check instead of failing cleanly. Shape-based\n * rather than a strict `schemaVersion` equality so additive versions keep\n * working.\n */\nexport function isCompatibleManifest(value: unknown): value is Manifest {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (typeof record.schemaVersion !== \"number\" || typeof record.packageVersion !== \"string\") {\n return false;\n }\n const controllers = record.controllers;\n if (typeof controllers !== \"object\" || controllers === null || Array.isArray(controllers)) {\n return false;\n }\n for (const entry of Object.values(controllers as Record<string, unknown>)) {\n if (typeof entry !== \"object\" || entry === null) return false;\n for (const field of CONTROLLER_ARRAY_FIELDS) {\n if (!Array.isArray((entry as Record<string, unknown>)[field])) return false;\n }\n }\n return true;\n}\n\n/**\n * Reads and parses one manifest file; throws on missing/corrupt files and on\n * manifests whose shape the bundled engine cannot consume.\n */\nexport function readManifestFile(path: string): Manifest {\n const parsed: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n if (!isCompatibleManifest(parsed)) {\n throw new Error(`Incompatible or malformed manifest: ${path}`);\n }\n return parsed;\n}\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\nimport { checkSource } from \"./check\";\nimport type { ExamplesIndex } from \"./examples\";\nimport { EXAMPLES_SCHEMA_VERSION } from \"./examples\";\nimport { isCheckableFile } from \"./files\";\nimport { readManifestFile } from \"./manifest_io\";\nimport type { CheckReport, ControllerManifest, Diagnostic, FileReport, Manifest } from \"./types\";\n\n/**\n * `stimeo check <path...>` / `stimeo catalog` — static checker and catalog\n * for `stimeo--*` markup.\n *\n * This is the executable entry point bundled as the `stimeo` npm bin. It is a\n * thin shell around {@link checkSource} and the bundled manifest: discover\n * files, run the engine, format the report, and set the exit code. All checking\n * logic lives in the engine so the CLI and the project's own checks use exactly the same\n * code path. Both commands accept `--json` to emit machine-readable output for\n * editor tooling and CI.\n */\n\n/** Resolves one of the JSON artifacts postbuild writes next to this file in `dist/inspector/`. */\nfunction bundledPath(name: string): string {\n return join(dirname(fileURLToPath(import.meta.url)), name);\n}\n\n/**\n * Loads the manifest bundled next to this file (`dist/inspector/manifest.json`),\n * shape-validated so a corrupt build artifact fails loudly here rather than as\n * an engine crash mid-check. Exported for the MCP server (`stimeo mcp`), which\n * loads the same bundled manifest at startup.\n */\nexport function loadManifest(): Manifest {\n return readManifestFile(bundledPath(\"manifest.json\"));\n}\n\n/**\n * Loads the example index bundled next to this file\n * (`dist/inspector/examples.json`), rejecting a format-version mismatch: the\n * index is only ever read by the build it shipped with, so a mismatch means a\n * corrupted or mixed installation and must fail loudly, not misbehave.\n */\nexport function loadExamplesIndex(): ExamplesIndex {\n const index = JSON.parse(readFileSync(bundledPath(\"examples.json\"), \"utf8\")) as ExamplesIndex;\n if (index.schemaVersion !== EXAMPLES_SCHEMA_VERSION) {\n throw new Error(\n `examples.json schema version ${index.schemaVersion} does not match this build ` +\n `(expected ${EXAMPLES_SCHEMA_VERSION}); reinstall or rebuild the package.`,\n );\n }\n return index;\n}\n\n/** Recursively collects checkable files under the given path. */\nfunction collectFiles(target: string, out: string[]): void {\n const stat = statSync(target);\n if (stat.isDirectory()) {\n for (const entry of readdirSync(target)) {\n collectFiles(join(target, entry), out);\n }\n return;\n }\n if (isCheckableFile(target)) out.push(target);\n}\n\n/** Builds a report for a single file. */\nfunction checkFile(file: string, manifest: Manifest): FileReport {\n const source = readFileSync(file, \"utf8\");\n return { file, diagnostics: checkSource(source, manifest) };\n}\n\n/**\n * Formats one diagnostic, e.g. ` 13:5 error message [code]`. A stage-4\n * suggestion, when present, is appended on its own indented `→` line.\n */\nfunction formatDiagnostic(d: Diagnostic): string {\n const where = `${d.line}:${d.column}`.padEnd(7);\n const head = ` ${where} ${d.severity.padEnd(7)} ${d.message} [${d.code}]`;\n return d.suggestion ? `${head}\\n → ${d.suggestion}` : head;\n}\n\n/**\n * Escapes workflow-command *message* data (`%`, CR, LF) per the GitHub Actions\n * toolkit's escaping rules.\n */\nfunction escapeGithubData(value: string): string {\n return value.replaceAll(\"%\", \"%25\").replaceAll(\"\\r\", \"%0D\").replaceAll(\"\\n\", \"%0A\");\n}\n\n/** Escapes a workflow-command *property* value (message rules plus `:`, `,`). */\nfunction escapeGithubProperty(value: string): string {\n return escapeGithubData(value).replaceAll(\":\", \"%3A\").replaceAll(\",\", \"%2C\");\n}\n\n/**\n * Formats one diagnostic as a GitHub Actions workflow command\n * (`::error file=…,line=…,col=…,title=…::message`). Emitting these from any CI\n * step makes the runner render inline annotations on the PR diff — no\n * marketplace action, upload step, or SARIF pipeline required.\n */\nexport function formatGithubAnnotation(file: string, d: Diagnostic): string {\n const properties = [\n `file=${escapeGithubProperty(file)}`,\n `line=${d.line}`,\n `col=${d.column}`,\n `title=${escapeGithubProperty(`Stimeo Inspector [${d.code}]`)}`,\n ].join(\",\");\n const message = d.suggestion ? `${d.message} → ${d.suggestion}` : d.message;\n return `::${d.severity} ${properties}::${escapeGithubData(message)}`;\n}\n\n/**\n * Aggregates per-file reports into the structured {@link CheckReport}, keeping\n * only files that produced diagnostics and tallying severities. Pure (no I/O),\n * so the JSON output contract is unit-tested directly.\n */\nexport function buildCheckReport(\n reports: readonly FileReport[],\n checkedFiles: number,\n): CheckReport {\n let errorCount = 0;\n let warningCount = 0;\n const files: FileReport[] = [];\n for (const report of reports) {\n if (report.diagnostics.length === 0) continue;\n files.push(report);\n for (const d of report.diagnostics) {\n if (d.severity === \"error\") errorCount++;\n else warningCount++;\n }\n }\n return { ok: errorCount === 0, checkedFiles, errorCount, warningCount, files };\n}\n\n/**\n * Controller entries sorted by identifier — the canonical iteration order for\n * catalog-style output. Shared by the CLI summary below and the MCP\n * `stimeo_catalog` tool so both render the manifest in the same order.\n */\nexport function sortedControllerEntries(\n manifest: Manifest,\n): ReadonlyArray<readonly [string, ControllerManifest]> {\n return Object.keys(manifest.controllers)\n .sort()\n .flatMap((id) => {\n const controller = manifest.controllers[id];\n return controller ? [[id, controller] as const] : [];\n });\n}\n\n/**\n * Renders the manifest as a human-readable catalog: one block per controller\n * listing its non-empty target/value/action/event names. `--json` emits the\n * raw manifest instead, for machine consumption.\n */\nexport function catalogSummary(manifest: Manifest): string[] {\n const entries = sortedControllerEntries(manifest);\n const lines = [\n `Stimeo UI catalog — ${entries.length} controller(s) (schema v${manifest.schemaVersion}, package ${manifest.packageVersion})`,\n \"\",\n ];\n for (const [id, c] of entries) {\n lines.push(id);\n if (c.targets.length > 0) lines.push(` targets: ${c.targets.join(\", \")}`);\n if (c.values.length > 0) lines.push(` values: ${c.values.join(\", \")}`);\n if (c.actions.length > 0) lines.push(` actions: ${c.actions.join(\", \")}`);\n if (c.events.length > 0) lines.push(` events: ${c.events.join(\", \")}`);\n }\n return lines;\n}\n\nconst USAGE = `stimeo — static checker and catalog for Stimeo UI markup\n\nUsage:\n stimeo check [--json|--github] <path...>\n Check HTML/ERB files (or directories) for\n unknown or misused stimeo--* controllers,\n targets, values and action methods.\n stimeo catalog [--json] Print the official controller catalog\n (identifiers, targets, values, actions,\n events).\n stimeo mcp Run a Model Context Protocol server over\n stdio, exposing the checker, catalog, and\n verified example markup as read-only tools\n (stimeo_check, stimeo_catalog,\n stimeo_controller, stimeo_example),\n resources, and workflow prompts for AI\n coding agents.\n\n--json makes either command emit machine-readable JSON (for tooling / MCP):\ncheck prints a CheckReport, catalog prints the raw manifest.\n--github prints check results as GitHub Actions workflow commands\n(::error / ::warning), which CI renders as inline PR annotations.\nExit code is 1 when any error is found (warnings never fail the run).`;\n\n/**\n * Runs the CLI.\n *\n * @param argv - Arguments after the node executable and script (`process.argv.slice(2)`).\n * @param write - Output sink (defaults to stdout); injectable for tests.\n * @param load - Manifest loader (defaults to the bundled manifest); injectable for tests.\n * @returns Process exit code (0 = clean, 1 = errors found, 2 = usage error).\n */\nexport function runCli(\n argv: readonly string[],\n write: (line: string) => void = console.log,\n load: () => Manifest = loadManifest,\n): number {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n write(USAGE);\n return command === undefined ? 2 : 0;\n }\n\n const json = rest.includes(\"--json\");\n const github = rest.includes(\"--github\");\n if (json && github) {\n write(`--json and --github are mutually exclusive.\\n\\n${USAGE}`);\n return 2;\n }\n\n if (command === \"catalog\") {\n const manifest = load();\n if (json) {\n write(JSON.stringify(manifest, null, 2));\n } else {\n for (const line of catalogSummary(manifest)) write(line);\n }\n return 0;\n }\n\n if (command !== \"check\") {\n write(`Unknown command \"${command}\".\\n\\n${USAGE}`);\n return 2;\n }\n\n const paths = rest.filter((arg) => !arg.startsWith(\"-\"));\n if (paths.length === 0) {\n write(`No paths given.\\n\\n${USAGE}`);\n return 2;\n }\n\n const files: string[] = [];\n for (const path of paths) {\n try {\n collectFiles(path, files);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n const reason =\n code === \"ENOENT\"\n ? \"no such file or directory\"\n : code === \"EACCES\"\n ? \"permission denied\"\n : ((err as Error).message ?? \"cannot access path\");\n write(`Cannot read path \"${path}\": ${reason}.\\n\\n${USAGE}`);\n return 2;\n }\n }\n\n const manifest = load();\n const cwd = process.cwd();\n const reports: FileReport[] = [];\n for (const file of files.sort()) {\n reports.push({\n file: relative(cwd, file) || file,\n diagnostics: checkFile(file, manifest).diagnostics,\n });\n }\n const summary = buildCheckReport(reports, files.length);\n\n if (json) {\n write(JSON.stringify(summary, null, 2));\n return summary.errorCount > 0 ? 1 : 0;\n }\n\n if (github) {\n for (const report of summary.files) {\n for (const d of report.diagnostics) write(formatGithubAnnotation(report.file, d));\n }\n } else {\n for (const report of summary.files) {\n write(report.file);\n for (const d of report.diagnostics) write(formatDiagnostic(d));\n write(\"\");\n }\n }\n\n const total = summary.errorCount + summary.warningCount;\n if (total === 0) {\n write(`✓ Checked ${summary.checkedFiles} file(s); no problems found.`);\n return 0;\n }\n write(\n `✖ ${total} problem(s) (${summary.errorCount} error(s), ${summary.warningCount} warning(s)).`,\n );\n return summary.errorCount > 0 ? 1 : 0;\n}\n"]}
|