UNPKG

@search-docs/server

Version:
110 lines 4.02 kB
import fg from 'fast-glob'; import * as fs from 'fs/promises'; import * as path from 'path'; import { minimatch } from 'minimatch'; // ignoreパッケージのファクトリ関数をdynamic importで使用 let ignoreFactory = null; /** * ファイル検索クラス * Globパターンと.gitignoreを使用してMarkdownファイルを検索 */ export class FileDiscovery { rootDir; config; ignoreFilter = null; constructor(options) { this.rootDir = path.resolve(options.rootDir); this.config = options.config; } /** * ファイルを検索 * @returns 見つかったファイルのパス一覧(プロジェクトルートからの相対パス) */ async findFiles() { // .gitignoreを読み込む if (this.config.ignoreGitignore) { await this.loadGitignore(); } // fast-globで検索 const files = await fg(this.config.include, { cwd: this.rootDir, ignore: this.config.exclude, absolute: false, // 相対パスを返す onlyFiles: true, dot: false, // ドットファイルを除外 }); // .gitignoreフィルタを適用 if (this.ignoreFilter) { return files.filter((file) => !this.ignoreFilter.ignores(file)); } return files; } /** * パスがパターンにマッチするか判定 * @param filePath ファイルパス(相対パス) * @returns マッチする場合true */ matchesPattern(filePath) { // includeパターンにマッチするか const matchesInclude = this.config.include.some((pattern) => { // minimatchはfast-globと異なり、**/patternがルートレベルにマッチしない // fast-globの挙動に合わせるため、**/で始まるパターンは // ルートレベルとネストレベルの両方をチェック if (pattern.startsWith('**/')) { const rootPattern = pattern.slice(3); // '**/'を除去 return minimatch(filePath, pattern) || minimatch(filePath, rootPattern); } return minimatch(filePath, pattern); }); if (!matchesInclude) { return false; } // excludeパターンにマッチしないか const matchesExclude = this.config.exclude.some((pattern) => { // exclude側も同様の処理 if (pattern.startsWith('**/')) { const rootPattern = pattern.slice(3); return minimatch(filePath, pattern) || minimatch(filePath, rootPattern); } return minimatch(filePath, pattern); }); return !matchesExclude; } /** * パスを除外すべきか判定 * @param filePath ファイルパス(相対パス) * @returns 除外する場合true */ shouldIgnore(filePath) { // .gitignoreフィルタ if (this.config.ignoreGitignore && this.ignoreFilter) { if (this.ignoreFilter.ignores(filePath)) { return true; } } // パターンマッチング return !this.matchesPattern(filePath); } /** * .gitignoreを読み込む */ async loadGitignore() { try { // ignoreパッケージを動的にロード if (!ignoreFactory) { const ignoreModule = await import('ignore'); ignoreFactory = ignoreModule.default; } const gitignorePath = path.join(this.rootDir, '.gitignore'); const content = await fs.readFile(gitignorePath, 'utf-8'); this.ignoreFilter = ignoreFactory().add(content); } catch (error) { // .gitignoreが存在しない場合は無視 if (error.code !== 'ENOENT') { throw error; } } } } //# sourceMappingURL=file-discovery.js.map