import type { KnownDetector, KnownSeverity } from "./detectors.js"; /** Token value with Tailwind class mapping */ export interface TokenValue { value: string | number | string[]; tailwind?: string; cssVar?: string; px?: number; rem?: string; size?: string; lineHeight?: string; [key: string]: unknown; } /** tokens.json root structure */ export interface Tokens { version: string; color: { primary: Record; body: TokenValue; semantic: { light: Record; dark: Record; }; status: Record>; }; typography: { fontFamily: Record; fontSize: Record; fontWeight: Record; letterSpacing: Record; lineHeight: Record; }; spacing: Record; elevation: Record; radius: Record; motion: { duration: Record; easing: Record; }; zIndex: Record; wireframe?: Record; } /** Component variant(生成 metadata の形。class が正、tailwind は deprecated alias で同値) */ export interface ComponentVariant { name: string; /** 正のキー。生成 metadata では tailwind と必ず同値で併記される */ class: string; /** @deprecated class を使うこと。削除は次の major(それまでは必ず同値で出力される) */ tailwind: string; } /** Component size(class が正、tailwind は deprecated alias で同値) */ export interface ComponentSize { name: string; /** 正のキー。生成 metadata では tailwind と必ず同値で併記される */ class: string; /** @deprecated class を使うこと。削除は次の major(それまでは必ず同値で出力される) */ tailwind: string; } /** Component accessibility spec */ export interface ComponentAccessibility { role: string; required: string[]; /** 契約が宣言した場合のみ存在する(engine は既定値を補わない) */ focusRing?: string; } /** state ごとの生成仕様(P2-1)。tailwind は base/variant からの差分クラスのみ */ export interface StateSpec { description: string; /** 正のキー。生成 metadata では tailwind と必ず同値で併記される */ class: string; /** @deprecated class を使うこと。削除は次の major(それまでは必ず同値で出力される) */ tailwind: string; ariaChanges?: string; htmlNote?: string; } /** anatomy part(object 形式時の各パーツ。Phase1 移行形 — 簡易は string[] 据置) */ export interface AnatomyPart { description: string; element?: string; roles?: string; class?: string; /** @deprecated class を使うこと。削除は次の major */ tailwind?: string; } /** Single component metadata */ export interface ComponentMeta { id: string; name: string; category: string; description: string; docPath: string; /** Phase1 移行形: 簡易は string[]、複合は part 名→AnatomyPart の object */ anatomy?: string[] | Record; variants: ComponentVariant[]; sizes: ComponentSize[]; /** UI 状態の列挙(melta-app が codegen で読む。byte-identical 維持) */ states?: string[]; /** state ごとの生成仕様(opt-in)。keys(stateSpecs) ⊆ states を validate.ts が担保 */ stateSpecs?: Record; /** プラットフォーム分岐の意味論宣言(規範部、P3)。分岐の具象値は recipes 側 */ platformSemantics?: Record; /** APP(RN) 実装の状態宣言。implemented ⇔ recipes/app 存在を validate が担保。差分表の生成元 */ appStatus?: "implemented" | "planned" | "not-planned"; /** web からの写像形態(appStatus と直交)。省略時 native。adapted は appNote に変換先必須 */ appMapping?: "native" | "adapted"; /** appStatus / appMapping の補足(adapted の変換先 / not-planned の理由) */ appNote?: string; /** プラットフォーム別具象レシピ(P3)。app = RN styleRefs(recipes/app/ 由来)。web の tailwind は variants に既存 */ recipes?: { app?: Record; }; accessibility: ComponentAccessibility; prohibited: string[]; htmlSample: string | Record; } /** components.json root structure */ export interface ComponentsData { version: string; components: ComponentMeta[]; } /** * html-attr ルールの機械可読検出仕様(Q5)。 * cheerio 等の DOM パーサ未導入のため正規表現ベースで presence/absence/値を判定する。 * 文脈依存(role=dialog を要する modal の特定など)は表現できず、対象外。 */ export type HtmlAttrCheck = /** attr の値(空白区切りの単一トークン)が valueRegex にマッチしたら違反(例: tabindex の正値) */ { kind: "attr-value-forbidden"; attr: string; valueRegex: string; } /** attr の値(クォート内全体)が valueRegex を含めば違反(例: inline style 内の hardcoded color) */ | { kind: "attr-value-contains"; attr: string; valueRegex: string; } /** tag が requiredAttr を持たなければ違反(例: の scope 欠落) */ | { kind: "tag-missing-attr"; tag: string; requiredAttr: string; } /** tag[attr=attrValue] が存在したら違反(例: の native datepicker) */ | { kind: "element-present"; tag: string; attr: string; attrValue: string; } /** tag が存在するだけで違反(例: 生 CSS の