/** * Styling Policy — 프로젝트별로 "무엇이 정식이고 무엇이 금지인지"를 선언한다. * * 이식 전략: * - 실제 정책 값은 CJS 파일(예: `stylingPolicy.js`)로 작성해서 * analyzer(TS)와 ESLint 플러그인(JS) 양쪽에서 동일한 파일을 참조할 수 있게 한다. * - 이 파일은 **타입 정의만** 제공한다. */ type DetectSpec = { /** import source path에 매치되는 정규식 (예: /\.scss$/i) */ importPathPatterns?: RegExp[]; /** import source가 정확히 일치해야 하는 모듈명 (예: 'reactstrap') */ importModules?: string[]; /** className 토큰에 매치되는 정규식 */ classPatterns?: RegExp[]; /** `style={{...}}` 사용 탐지 */ inlineStyleJSX?: boolean; }; type AllowedMethodSpec = { /** 방식 식별자. preferred 참조 키 (예: 'scss', 'tailwind', 'css-modules') */ id: string; label: string; detect: DetectSpec; }; type ForbiddenPatternSpec = { /** 패턴 그룹 식별자 (예: 'bootstrap-utilities') */ id: string; label: string; /** 기본 심각도. ESLint 래칫에서 baseline-등록 파일은 warn으로 완화된다. */ severity: "warn" | "error"; /** className 토큰에 매치되는 정규식들. */ classPatterns: RegExp[]; /** 모듈 import 자체를 금지하려면 여기에 (예: ['react-bootstrap']) */ importModules?: string[]; }; type StylingPolicy = { /** 허용되는 스타일링 방식 */ allowed: AllowedMethodSpec[]; /** 정식으로 권장하는 방식의 id (allowed 중 하나) */ preferred: string; /** 금지/경고할 패턴들 */ forbidden: ForbiddenPatternSpec[]; }; interface UIHealthConfig { projectRoot: string; /** * 프로젝트 이름 — dashboard header / footer 안 표시. * * 미지정 시 `package.json` 안 `name` 자동 read. 둘 다 없는 시점 = "Unknown Project". */ projectName?: string; /** 프로젝트별 스타일링 정책 — 허용/금지/권장 스타일링 방식. */ stylingPolicy: StylingPolicy; scan: { codeRoots: string[]; styleRoots: string[]; ignore: string[]; codeExts: string[]; styleExts: string[]; }; /** * 글로벌(= "허용된") 스타일 정의의 출처 glob 패턴. * * v0.4 orphan class 분류용. 이 glob 에 매치되는 파일에서 정의된 모든 CSS * 클래스 셀렉터를 수집해 "글로벌 인덱스" 를 만든다. * * 컴포넌트가 사용한 className 중 하나 이상이 이 인덱스에 존재하면 * `allowedGlobal` (건강한 글로벌 재사용), 하나도 없으면 `orphanClass` * (어디에도 정의 안 된 부채) 로 분류. * * 각 프로젝트는 글로벌 스타일 파일이 있는 실제 경로를 지정 — * 예) 이 프로젝트는 `styles/css/scss/*.scss` 와 `styles/css/*.css` * (labeling.css 가 이 폴더에 있음). 이 패턴들 밖의 SCSS/CSS 파일은 * 모두 컴포넌트 전용으로 간주되어 인덱스에 포함 안 함. */ globalStyleSources: string[]; designSystem: { officialPaths: string[]; officialAliases: string[]; componentExts: string[]; }; hardcodedValues: { colorPatterns: RegExp[]; scssVariableUsagePatterns: RegExp[]; scssVariableDefFiles: string[]; }; migrationTargets: Record; migrationMinClassLength: number; /** * 마이그레이션 후보 검출 옵션 (0.7.2+). * * 옛 schema 와의 관계: * - `metrics.migrationCandidates: boolean` = 측정 자체를 켜고 끄는 toggle. * - `migrationCandidates: MigrationCandidatesOptions` = 측정 동작의 세부 옵션. * 같은 prefix 를 가지지만 다른 차원입니다. */ migrationCandidates?: MigrationCandidatesOptions; report: { outputDir: string; baselineFilenamePrefix: string; }; /** * Soft lint baseline 설정 (Phase 1: 가시화 전용, CI 블로킹 없음). * * 이 파일은 `npm run lint:summary`가 참조해서 현재 위반 수를 baseline과 * 비교·표시한다. CI 실패 처리는 하지 않는다. 파일이 없으면 summary는 * "baseline 없음" 메시지만 출력하고 종료 (신규 프로젝트 대비). * * 참고: 이 파일과 `lint-baseline.json`(dsmonitor/eslint 의 파일별 * 심각도 오버라이드 맵)은 **다른 파일**이다. 헷갈리지 말 것. */ softBaseline?: { /** baseline JSON 파일 경로 (config 파일 기준 상대경로) */ path: string; }; /** * 어떤 프레임워크의 코드를 분석할지. 어댑터 선택 키. * 현재 지원: "react". Vue/Svelte는 어댑터 추가 후 사용. */ framework: { id: string; }; /** * 각 지표를 켜고 끌지. 프로젝트 상황에 맞지 않는 지표는 false로. * 예) 순수 TS 프로젝트면 tsMigration: false. */ metrics: { tsMigration: boolean; dsCoverage: boolean; migrationCandidates: boolean; stylingDistribution: boolean; hardcodedColors: boolean; scssVariableCompliance: boolean; /** * Figma baseline 측정 on/off (Phase 0.5). * true 로 설정 시 `figma` 필드, `FIGMA_API_TOKEN` env 모두 필요. * 둘 중 하나라도 없으면 친절한 에러와 함께 중단. */ figmaAnalysis: boolean; }; /** * Figma baseline 측정 설정 (Phase 0.5 최소 버전 + Phase B 확장 예정). * * `metrics.figmaAnalysis` 가 true 일 때만 사용. 실제 파일 URL 은 민감 정보이므로 * `dsmonitor.config.local.ts` (.gitignore 대상) 에서 import 해서 주입. */ figma?: FigmaConfig; /** * Lighthouse 측정 설정 (옵션). * * Phase 0.5 (2026-04-27 분리 4단계) 에는 type 만 정의되어 있고 실제 활용은 * Phase B 의 AuthAdapter 인터페이스 작업과 함께 정식화 예정. */ lighthouse?: LighthouseConfig; /** * 리포트 해석용 임계값. 각 지표에 대해 "이 값이면 good/warn/bad" 를 결정. * direction: 'higher' — 값이 높을수록 좋음 (good: 값 ≥ good, warn: 값 ≥ warn) * direction: 'lower' — 값이 낮을수록 좋음 (good: 값 ≤ good, warn: 값 ≤ warn) */ thresholds: { dsCoverage: Threshold; tsMigration: Threshold; scssVariableCompliance: Threshold; /** 참고 지표. 현재 reporter는 informational로 표시하고 개선/강점 분류에서 제외한다. */ preferredCompliance: Threshold; hardcodedColors: Threshold; forbiddenClassOccurrences: Threshold; /** 주 지표 — forbidden 방식을 쓰는 파일 비율. 낮을수록 좋음. */ forbiddenFileRatio: Threshold; /** * 컴포넌트 매칭률 (B 그룹 단계 3, 2026-04-29). * Figma DS variantGroup 이름 ↔ 코드 className (글로벌 인덱스 + JSX/TSX 사용 합집합) 매칭. * 본 프로젝트는 Figma 이름 ↔ CSS class 동기화 정책이라 같은 kebab-case 로 정확 일치. */ componentMatch?: Threshold; }; /** * 측정 도구 자체의 개선 이력. 분석 로직이 바뀌어 과거 수치가 재해석될 필요가 * 있을 때 기록. 리포트 하단에 표시되어 "왜 이 숫자가 이만큼 바뀌었는지"를 * 독자가 추적할 수 있게 한다. */ measurementHistory?: MeasurementHistoryEntry[]; /** * 개선 작업의 단계 상태. baseline.md 상단에 배지로 렌더링된다. * 리포트는 자동 생성물이므로 단계 전환 시 config에서 바꿔야 유지된다. * * 일반적 운용: * - completedPhases: Phase 종료 시 수동으로 추가 * - currentPhase: 지금 진행 중인 Phase (1개) * - upcomingPhases: 로드맵 상 이후 Phase를 선언. 리포트에 "예정" 표기로 * 노출 가능. 수동 전환 시 upcoming → current → completed 순으로 이동. */ reportStatus?: { completedPhases?: Array<{ name: string; completedAt: string; note?: string; }>; currentPhase?: { name: string; note?: string; startedAt?: string; }; upcomingPhases?: Array<{ name: string; note?: string; }>; }; } /** * `UIHealthConfig.migrationCandidates` 의 세부 옵션 (0.7.2+). * * 본 옵션은 마이그레이션 후보 검출 흐름만 정정합니다. `totals.dsComponentFiles` * 같은 다른 지표는 영향을 받지 않습니다. */ interface MigrationCandidatesOptions { /** * `designSystem.officialPaths` 에 매치되는 파일을 마이그레이션 후보 검출에서 * 자동으로 제외할지 여부. * * @default true * * true 시점 (default): * - officialPaths glob (`src/laon-web-ui/**`, `src/components/ds/**` 등) 안 파일은 * 후보 점검에서 제외됩니다. * - DS 본체 안에서 native HTML 을 자연스럽게 사용하는 케이스 (예: Button.tsx 가 * 내부에서 `