publish(task 4): slug- und post-validation
validateSlug prüft regex ^[a-z0-9][a-z0-9-]*$ (lowercase, digits, hyphen; kein führender hyphen). validatePost checkt title, slug und date (muss Date-instanz mit gültigem timestamp sein). 7 tests grün. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
178016f0f4
commit
bc2679aeba
|
|
@ -0,0 +1,22 @@
|
|||
import type { Frontmatter } from './frontmatter.ts'
|
||||
|
||||
const SLUG_RE = /^[a-z0-9][a-z0-9-]*$/
|
||||
|
||||
export function validateSlug(slug: string): void {
|
||||
if (!SLUG_RE.test(slug)) {
|
||||
throw new Error(`invalid slug: "${slug}" (must match ${SLUG_RE})`)
|
||||
}
|
||||
}
|
||||
|
||||
export function validatePost(fm: Frontmatter): void {
|
||||
if (!fm.title || typeof fm.title !== 'string') {
|
||||
throw new Error('missing/invalid title')
|
||||
}
|
||||
if (!fm.slug || typeof fm.slug !== 'string') {
|
||||
throw new Error('missing/invalid slug')
|
||||
}
|
||||
validateSlug(fm.slug)
|
||||
if (!(fm.date instanceof Date) || isNaN(fm.date.getTime())) {
|
||||
throw new Error('missing/invalid date (expected YAML date)')
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { assertThrows } from '@std/assert'
|
||||
import { validatePost, validateSlug } from '../src/core/validation.ts'
|
||||
import type { Frontmatter } from '../src/core/frontmatter.ts'
|
||||
|
||||
Deno.test('validateSlug: akzeptiert lowercase/digits/hyphen', () => {
|
||||
validateSlug('abc-123')
|
||||
validateSlug('a')
|
||||
validateSlug('dezentrale-oep-oer')
|
||||
})
|
||||
|
||||
Deno.test('validateSlug: lehnt Großbuchstaben ab', () => {
|
||||
assertThrows(() => validateSlug('Abc'), Error, 'slug')
|
||||
})
|
||||
|
||||
Deno.test('validateSlug: lehnt Unterstriche/Leerzeichen ab', () => {
|
||||
assertThrows(() => validateSlug('a_b'), Error, 'slug')
|
||||
assertThrows(() => validateSlug('a b'), Error, 'slug')
|
||||
})
|
||||
|
||||
Deno.test('validateSlug: lehnt führenden Bindestrich ab', () => {
|
||||
assertThrows(() => validateSlug('-abc'), Error, 'slug')
|
||||
})
|
||||
|
||||
Deno.test('validatePost: ok bei vollständigem Frontmatter', () => {
|
||||
const fm: Frontmatter = {
|
||||
title: 'T',
|
||||
slug: 'ok-slug',
|
||||
date: new Date('2024-01-01'),
|
||||
}
|
||||
validatePost(fm)
|
||||
})
|
||||
|
||||
Deno.test('validatePost: fehlt title', () => {
|
||||
const fm = { slug: 'ok', date: new Date() } as unknown as Frontmatter
|
||||
assertThrows(() => validatePost(fm), Error, 'title')
|
||||
})
|
||||
|
||||
Deno.test('validatePost: date muss Date sein', () => {
|
||||
const fm = { title: 'T', slug: 'ok', date: 'not-a-date' } as unknown as Frontmatter
|
||||
assertThrows(() => validatePost(fm), Error, 'date')
|
||||
})
|
||||
Loading…
Reference in New Issue