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

View File

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