publish(task 17): validate-post-subcommand

validatePostFile(path) liest post-datei, parst frontmatter, ruft
validatePost aus core/validation. liefert { ok, slug?, error? }.
offline-befehl ohne netz-zugriff. 3 tests grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jörg Lohrer 2026-04-18 05:40:29 +02:00
parent f31e586e85
commit 4d9af00a97
2 changed files with 53 additions and 0 deletions

View File

@ -0,0 +1,24 @@
import { parseFrontmatter } from '../core/frontmatter.ts'
import { validatePost } from '../core/validation.ts'
export interface ValidateResult {
ok: boolean
slug?: string
error?: string
}
export async function validatePostFile(path: string): Promise<ValidateResult> {
let text: string
try {
text = await Deno.readTextFile(path)
} catch (err) {
return { ok: false, error: `cannot read ${path}: ${err instanceof Error ? err.message : err}` }
}
try {
const { fm } = parseFrontmatter(text)
validatePost(fm)
return { ok: true, slug: fm.slug }
} catch (err) {
return { ok: false, error: err instanceof Error ? err.message : String(err) }
}
}

View File

@ -0,0 +1,29 @@
import { assertEquals } from '@std/assert'
import { validatePostFile } from '../src/subcommands/validate-post.ts'
Deno.test('validatePostFile: ok bei fixture-post', async () => {
const result = await validatePostFile('./tests/fixtures/sample-post.md')
assertEquals(result.ok, true)
assertEquals(result.slug, 'sample-slug')
})
Deno.test('validatePostFile: fehler bei fehlender datei', async () => {
const result = await validatePostFile('./does-not-exist.md')
assertEquals(result.ok, false)
assertEquals(result.error?.includes('read'), true)
})
Deno.test('validatePostFile: fehler bei ungültigem slug', async () => {
const tmp = await Deno.makeTempFile({ suffix: '.md' })
try {
await Deno.writeTextFile(
tmp,
'---\ntitle: "T"\nslug: "Bad Slug"\ndate: 2024-01-01\n---\n\nbody',
)
const result = await validatePostFile(tmp)
assertEquals(result.ok, false)
assertEquals(result.error?.includes('slug'), true)
} finally {
await Deno.remove(tmp)
}
})