tests:filter/model - validate link cache

This commit is contained in:
2025-03-28 12:05:43 +01:00
parent 8620ee4817
commit 40f89d623e
3 changed files with 230 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
import { describe, it, expect } from 'vitest';
import { fixMarkdownLint } from '../markdown.js';
describe('fixMarkdownLint', () => {
it('should fix heading capitalization', async () => {
const input = `# hello world
## this is a test heading
### another heading here`;
const result = await fixMarkdownLint(input);
expect(result.fixed).toBe(`# Hello World
## This Is A Test Heading
### Another Heading Here`);
expect(result.errors.length).toBe(0);
});
it('should handle empty input', async () => {
const result = await fixMarkdownLint('');
expect(result.fixed).toBe('');
expect(result.errors.length).toBe(0);
});
it('should handle markdown with code blocks', async () => {
const input = `# test heading
\`\`\`typescript
const hello = "world";
\`\`\`
## another heading`;
const result = await fixMarkdownLint(input);
expect(result.fixed).toBe(`# Test Heading
\`\`\`typescript
const hello = "world";
\`\`\`
## Another Heading`);
expect(result.errors.length).toBe(0);
});
it('should handle markdown with lists', async () => {
const input = `# test heading
- item 1
- item 2
- subitem 1
- subitem 2
## another heading`;
const result = await fixMarkdownLint(input);
expect(result.fixed).toBe(`# Test Heading
- Item 1
- Item 2
- Subitem 1
- Subitem 2
## Another Heading`);
expect(result.errors.length).toBe(0);
});
});
+80
View File
@@ -0,0 +1,80 @@
import fs from 'fs/promises';
import path from 'path';
interface CacheEntry {
isValid: boolean;
timestamp: number;
}
interface CacheData {
[url: string]: CacheEntry;
}
const CACHE_FILE = path.join(process.cwd(), '.cache', 'link-cache.json');
const CACHE_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 1 week in milliseconds
class LinkCache {
private cache: CacheData = {};
private initialized = false;
private async ensureCacheDir() {
const dir = path.dirname(CACHE_FILE);
try {
await fs.access(dir);
} catch {
await fs.mkdir(dir, { recursive: true });
}
}
private async loadCache() {
if (this.initialized) return;
try {
const data = await fs.readFile(CACHE_FILE, 'utf-8');
this.cache = JSON.parse(data);
} catch (error) {
// If file doesn't exist or is invalid, start with empty cache
this.cache = {};
}
this.initialized = true;
}
private async saveCache() {
await this.ensureCacheDir();
await fs.writeFile(CACHE_FILE, JSON.stringify(this.cache, null, 2));
}
private isExpired(entry: CacheEntry): boolean {
return Date.now() - entry.timestamp > CACHE_EXPIRY;
}
async get(url: string): Promise<boolean | null> {
await this.loadCache();
const entry = this.cache[url];
if (!entry) return null;
if (this.isExpired(entry)) {
delete this.cache[url];
await this.saveCache();
return null;
}
return entry.isValid;
}
async set(url: string, isValid: boolean): Promise<void> {
await this.loadCache();
this.cache[url] = {
isValid,
timestamp: Date.now()
};
await this.saveCache();
}
async clear(): Promise<void> {
this.cache = {};
await this.saveCache();
}
}
export const linkCache = new LinkCache();