Files
oh-my-opencode/src/hooks/rules-injector/rule-distance.ts
T
YeonGyu-Kim 2d22a54b55 refactor(rules-injector): split finder.ts into rule discovery modules
Extract rule finding logic:
- project-root-finder.ts: project root detection
- rule-file-finder.ts: rule file discovery
- rule-file-scanner.ts: filesystem scanning for rules
- rule-distance.ts: rule-to-file distance calculation
2026-02-08 16:22:33 +09:00

54 lines
1.6 KiB
TypeScript

import { dirname, relative } from "node:path";
/**
* Calculate directory distance between a rule file and current file.
* Distance is based on common ancestor within project root.
*
* @param rulePath - Path to the rule file
* @param currentFile - Path to the current file being edited
* @param projectRoot - Project root for relative path calculation
* @returns Distance (0 = same directory, higher = further)
*/
export function calculateDistance(
rulePath: string,
currentFile: string,
projectRoot: string | null,
): number {
if (!projectRoot) {
return 9999;
}
try {
const ruleDir = dirname(rulePath);
const currentDir = dirname(currentFile);
const ruleRel = relative(projectRoot, ruleDir);
const currentRel = relative(projectRoot, currentDir);
// Handle paths outside project root
if (ruleRel.startsWith("..") || currentRel.startsWith("..")) {
return 9999;
}
// Split by both forward and back slashes for cross-platform compatibility
// path.relative() returns OS-native separators (backslashes on Windows)
const ruleParts = ruleRel ? ruleRel.split(/[/\\]/) : [];
const currentParts = currentRel ? currentRel.split(/[/\\]/) : [];
// Find common prefix length
let common = 0;
for (let i = 0; i < Math.min(ruleParts.length, currentParts.length); i++) {
if (ruleParts[i] === currentParts[i]) {
common++;
} else {
break;
}
}
// Distance is how many directories up from current file to common ancestor
return currentParts.length - common;
} catch {
return 9999;
}
}