import type { DocumentType, DocumentMetadata, LintResult, ValidationContext } from '../core/types.js'; import { MarkdownParser } from '../core/parser.js'; import { FileReader } from '../infrastructure/FileReader.js'; /** * LintUseCaseの入力 */ export interface LintUseCaseInput { /** ファイルパス(必須) */ filePath: string; /** コンテンツ(指定されていればファイル読み込みをスキップ) */ content?: string; } /** * LintUseCaseの出力 */ export interface LintUseCaseOutput { /** リント結果の配列 */ results: LintResult[]; /** ドキュメントメタデータ */ metadata: DocumentMetadata; } /** * Lint実行ユースケース * ドキュメントタイプに応じたバリデーションを実行する */ export class LintUseCase { constructor( private readonly parser: MarkdownParser, private readonly fileReader: FileReader, private readonly documentType: DocumentType, ) {} /** * コンテンツまたはファイルパスからリントを実行 */ async execute(input: LintUseCaseInput): Promise { // コンテンツを取得(指定されていなければファイルから読み込み) const content = input.content ?? await this.fileReader.read(input.filePath); // ASTにパース const tree = this.parser.parse(content); // frontmatterを抽出 const frontmatter = this.parser.extractFrontmatter(content); // メタデータを構築 const metadata: DocumentMetadata = { filePath: input.filePath, title: typeof frontmatter.title === 'string' ? frontmatter.title : undefined, frontmatter, documentType: this.documentType.id, documentTypeName: this.documentType.name, }; // バリデーションコンテキストを構築 const context: ValidationContext = { tree, content, metadata, }; // 全バリデーターを実行して結果を収集 const results: LintResult[] = []; for (const validator of this.documentType.validators) { const validatorResults = validator.validate(context); results.push(...validatorResults); } return { results, metadata, }; } /** * ファイルパスからリントを実行 */ async executeFromFile(filePath: string): Promise { return this.execute({ filePath }); } }