feat(publish): filterPostDirs traversiert sprach-ebene

This commit is contained in:
Jörg Lohrer 2026-04-21 09:06:43 +02:00
parent 695f5e8e69
commit d3215fa760
2 changed files with 22 additions and 20 deletions

View File

@ -7,22 +7,24 @@ function escapeRegex(s: string): string {
export function filterPostDirs(lines: string[], contentRoot: string): string[] {
const root = contentRoot.replace(/\/$/, '')
const prefix = root + '/'
const indexRe = new RegExp(`^${escapeRegex(prefix)}([^/]+)/index\\.md$`)
const assetRe = new RegExp(`^${escapeRegex(prefix)}([^/]+)/`)
const drafts = prefix + '_'
const indexRe = new RegExp(`^${escapeRegex(prefix)}([a-z]{2})/([^/]+)/index\\.md$`)
const assetRe = new RegExp(`^${escapeRegex(prefix)}([a-z]{2})/([^/]+)/`)
const dirs = new Set<string>()
for (const line of lines) {
const l = line.trim()
if (!l) continue
if (l.startsWith(drafts)) continue
const indexMatch = l.match(indexRe)
if (indexMatch) {
dirs.add(`${prefix}${indexMatch[1]}`)
const [, lang, slug] = indexMatch
if (slug.startsWith('_')) continue
dirs.add(`${prefix}${lang}/${slug}`)
continue
}
const assetMatch = l.match(assetRe)
if (assetMatch && !l.endsWith('.md')) {
dirs.add(`${prefix}${assetMatch[1]}`)
const [, lang, slug] = assetMatch
if (slug.startsWith('_')) continue
dirs.add(`${prefix}${lang}/${slug}`)
}
}
return [...dirs].sort()

View File

@ -7,35 +7,35 @@ import {
Deno.test('filterPostDirs: extrahiert post-ordner aus dateipfaden (content/posts)', () => {
const lines = [
'content/posts/a/index.md',
'content/posts/b/image.png',
'content/posts/c/other.md',
'content/posts/de/a/index.md',
'content/posts/de/b/image.png',
'content/posts/de/c/other.md',
'README.md',
'app/src/lib/x.ts',
]
assertEquals(
filterPostDirs(lines, 'content/posts').sort(),
['content/posts/a', 'content/posts/b'],
['content/posts/de/a', 'content/posts/de/b'],
)
})
Deno.test('filterPostDirs: respektiert alternativen root (blog/)', () => {
const lines = [
'blog/x/index.md',
'blog/y/pic.png',
'content/posts/z/index.md',
'blog/de/x/index.md',
'blog/en/y/pic.png',
'content/posts/de/z/index.md',
'README.md',
]
assertEquals(filterPostDirs(lines, 'blog').sort(), ['blog/x', 'blog/y'])
assertEquals(filterPostDirs(lines, 'blog').sort(), ['blog/de/x', 'blog/en/y'])
})
Deno.test('filterPostDirs: ignoriert _drafts und non-index.md', () => {
const lines = [
'content/posts/a/index.md',
'content/posts/a/extra.md',
'content/posts/_drafts/x/index.md',
'content/posts/de/a/index.md',
'content/posts/de/a/extra.md',
'content/posts/de/_drafts/x/index.md',
]
assertEquals(filterPostDirs(lines, 'content/posts'), ['content/posts/a'])
assertEquals(filterPostDirs(lines, 'content/posts'), ['content/posts/de/a'])
})
Deno.test('changedPostDirs: nutzt git diff --name-only A..B', async () => {
@ -43,7 +43,7 @@ Deno.test('changedPostDirs: nutzt git diff --name-only A..B', async () => {
assertEquals(args[0], 'diff')
assertEquals(args[1], '--name-only')
assertEquals(args[2], 'HEAD~1..HEAD')
return Promise.resolve('content/posts/x/index.md\nREADME.md\n')
return Promise.resolve('content/posts/de/x/index.md\nREADME.md\n')
}
const dirs = await changedPostDirs({
from: 'HEAD~1',
@ -51,7 +51,7 @@ Deno.test('changedPostDirs: nutzt git diff --name-only A..B', async () => {
contentRoot: 'content/posts',
runner,
})
assertEquals(dirs, ['content/posts/x'])
assertEquals(dirs, ['content/posts/de/x'])
})
Deno.test('filterPostDirs: extrahiert post-ordner mit sprach-ebene', () => {