@every-env/cli
Version:
Multi-agent orchestrator for AI-powered development workflows
64 lines • 2.46 kB
JavaScript
import { readFile } from 'fs/promises';
import { validatePath } from '../utils/security.js';
export class ContentPatternMatcher {
async match(pattern, files) {
const allMatches = [];
for (const file of files) {
// Validate file path is within working directory
const safePath = validatePath(file, process.cwd());
const content = await readFile(safePath, 'utf-8');
const matches = this.extractMatches(pattern, file, content);
allMatches.push(...matches);
}
return this.filterExcluded(allMatches, pattern.exclude);
}
extractMatches(pattern, file, content) {
const matches = [];
if (pattern.regex) {
const regex = new RegExp(pattern.regex, pattern.multiline ? 'gm' : 'g');
let match;
while ((match = regex.exec(content)) !== null) {
const captureGroup = pattern.captureGroup || 1;
const matchText = match[captureGroup] || match[0];
// Get line and column
const lines = content.substring(0, match.index).split('\n');
const line = lines.length;
const column = lines[lines.length - 1].length + 1;
matches.push({
file,
match: matchText,
captures: this.extractCaptures(match),
line,
column,
context: this.extractContext(content, match.index),
});
}
}
return matches;
}
extractCaptures(match) {
const captures = {};
for (let i = 1; i < match.length; i++) {
if (match[i] !== undefined) {
captures[`group${i}`] = match[i];
}
}
// Named groups support
if (match.groups) {
Object.assign(captures, match.groups);
}
return captures;
}
extractContext(content, index, contextSize = 50) {
const start = Math.max(0, index - contextSize);
const end = Math.min(content.length, index + contextSize);
return content.substring(start, end).trim();
}
filterExcluded(matches, exclude) {
if (!exclude || exclude.length === 0) {
return matches;
}
return matches.filter(match => !exclude.includes(match.match));
}
}
//# sourceMappingURL=content-pattern.js.map