feat(mod_format): Refactor formatting modules to new BaseFormatter and implement concrete analyze/apply logic
This commit is contained in:
@@ -1,8 +1,111 @@
|
||||
import { LegacyFormatter } from './legacy.formatter.js';
|
||||
import * as formatGitignore from '../format.gitignore.js';
|
||||
import { BaseFormatter } from '../classes.baseformatter.js';
|
||||
import type { IPlannedChange } from '../interfaces.format.js';
|
||||
import * as plugins from '../mod.plugins.js';
|
||||
import { logger } from '../../gitzone.logging.js';
|
||||
|
||||
export class GitignoreFormatter extends LegacyFormatter {
|
||||
constructor(context: any, project: any) {
|
||||
super(context, project, 'gitignore', formatGitignore);
|
||||
// Standard gitignore template content (without front-matter)
|
||||
const GITIGNORE_TEMPLATE = `.nogit/
|
||||
|
||||
# artifacts
|
||||
coverage/
|
||||
public/
|
||||
|
||||
# installs
|
||||
node_modules/
|
||||
|
||||
# caches
|
||||
.yarn/
|
||||
.cache/
|
||||
.rpt2_cache
|
||||
|
||||
# builds
|
||||
dist/
|
||||
dist_*/
|
||||
|
||||
# AI
|
||||
.claude/
|
||||
.serena/
|
||||
|
||||
#------# custom`;
|
||||
|
||||
export class GitignoreFormatter extends BaseFormatter {
|
||||
get name(): string {
|
||||
return 'gitignore';
|
||||
}
|
||||
|
||||
async analyze(): Promise<IPlannedChange[]> {
|
||||
const changes: IPlannedChange[] = [];
|
||||
const gitignorePath = '.gitignore';
|
||||
|
||||
// Check if file exists and extract custom content
|
||||
let customContent = '';
|
||||
const exists = await plugins.smartfs.file(gitignorePath).exists();
|
||||
|
||||
if (exists) {
|
||||
const existingContent = (await plugins.smartfs
|
||||
.file(gitignorePath)
|
||||
.encoding('utf8')
|
||||
.read()) as string;
|
||||
|
||||
// Extract custom section content
|
||||
const customMarkers = ['#------# custom', '# custom'];
|
||||
for (const marker of customMarkers) {
|
||||
const splitResult = existingContent.split(marker);
|
||||
if (splitResult.length > 1) {
|
||||
customContent = splitResult[1].trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute new content
|
||||
let newContent = GITIGNORE_TEMPLATE;
|
||||
if (customContent) {
|
||||
newContent = GITIGNORE_TEMPLATE + '\n' + customContent + '\n';
|
||||
} else {
|
||||
newContent = GITIGNORE_TEMPLATE + '\n';
|
||||
}
|
||||
|
||||
// Read current content to compare
|
||||
let currentContent = '';
|
||||
if (exists) {
|
||||
currentContent = (await plugins.smartfs
|
||||
.file(gitignorePath)
|
||||
.encoding('utf8')
|
||||
.read()) as string;
|
||||
}
|
||||
|
||||
// Determine change type
|
||||
if (!exists) {
|
||||
changes.push({
|
||||
type: 'create',
|
||||
path: gitignorePath,
|
||||
module: this.name,
|
||||
description: 'Create .gitignore',
|
||||
content: newContent,
|
||||
});
|
||||
} else if (newContent !== currentContent) {
|
||||
changes.push({
|
||||
type: 'modify',
|
||||
path: gitignorePath,
|
||||
module: this.name,
|
||||
description: 'Update .gitignore (preserving custom section)',
|
||||
content: newContent,
|
||||
});
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
async applyChange(change: IPlannedChange): Promise<void> {
|
||||
if (!change.content) return;
|
||||
|
||||
if (change.type === 'create') {
|
||||
await this.createFile(change.path, change.content);
|
||||
logger.log('info', 'Created .gitignore');
|
||||
} else if (change.type === 'modify') {
|
||||
await this.modifyFile(change.path, change.content);
|
||||
logger.log('info', 'Updated .gitignore (preserved custom section)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user