publish(task 11): image-collector (ignoriert hugo-derivate)
collectImages(postDir) scannt ordner nach png/jpg/jpeg/gif/webp/svg, ignoriert hugo-resize-derivate (*_hu_<hex>.*), liest bytes und gibt sortierte ImageFile[]-liste zurück. mimeFromExt() mapped extension auf mime-type. deno.jsonc test-task um --allow-write erweitert (Deno. makeTempDir+writeFile in tests). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
05ba4e4ef9
commit
8eebd29266
|
|
@ -3,7 +3,7 @@
|
|||
"publish": "deno run --env-file=../.env.local --allow-env --allow-read --allow-write=./logs --allow-net --allow-run=git src/cli.ts publish",
|
||||
"check": "deno run --env-file=../.env.local --allow-env --allow-read --allow-net src/cli.ts check",
|
||||
"validate-post": "deno run --allow-read src/cli.ts validate-post",
|
||||
"test": "deno test --allow-env --allow-read --allow-net --allow-run",
|
||||
"test": "deno test --allow-env --allow-read --allow-write --allow-net --allow-run",
|
||||
"fmt": "deno fmt",
|
||||
"lint": "deno lint"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
import { extname, join } from '@std/path'
|
||||
|
||||
const IMG_EXTS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'])
|
||||
|
||||
const MIME_MAP: Record<string, string> = {
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
'.svg': 'image/svg+xml',
|
||||
}
|
||||
|
||||
const HUGO_DERIVATIVE = /_hu_[0-9a-f]+\./
|
||||
|
||||
export function mimeFromExt(filename: string): string {
|
||||
return MIME_MAP[extname(filename).toLowerCase()] ?? 'application/octet-stream'
|
||||
}
|
||||
|
||||
export interface ImageFile {
|
||||
fileName: string
|
||||
absolutePath: string
|
||||
data: Uint8Array
|
||||
mimeType: string
|
||||
}
|
||||
|
||||
export async function collectImages(postDir: string): Promise<ImageFile[]> {
|
||||
const results: ImageFile[] = []
|
||||
for await (const entry of Deno.readDir(postDir)) {
|
||||
if (!entry.isFile) continue
|
||||
if (HUGO_DERIVATIVE.test(entry.name)) continue
|
||||
const ext = extname(entry.name).toLowerCase()
|
||||
if (!IMG_EXTS.has(ext)) continue
|
||||
const abs = join(postDir, entry.name)
|
||||
const data = await Deno.readFile(abs)
|
||||
results.push({
|
||||
fileName: entry.name,
|
||||
absolutePath: abs,
|
||||
data,
|
||||
mimeType: mimeFromExt(entry.name),
|
||||
})
|
||||
}
|
||||
results.sort((a, b) => a.fileName.localeCompare(b.fileName))
|
||||
return results
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import { assertEquals } from '@std/assert'
|
||||
import { collectImages, mimeFromExt } from '../src/core/image-collector.ts'
|
||||
|
||||
Deno.test('mimeFromExt: erkennt gängige formate', () => {
|
||||
assertEquals(mimeFromExt('a.png'), 'image/png')
|
||||
assertEquals(mimeFromExt('a.jpg'), 'image/jpeg')
|
||||
assertEquals(mimeFromExt('a.jpeg'), 'image/jpeg')
|
||||
assertEquals(mimeFromExt('a.gif'), 'image/gif')
|
||||
assertEquals(mimeFromExt('a.webp'), 'image/webp')
|
||||
assertEquals(mimeFromExt('a.svg'), 'image/svg+xml')
|
||||
})
|
||||
|
||||
Deno.test('collectImages: liest alle bild-dateien im ordner, ignoriert hugo-derivate', async () => {
|
||||
const tmp = await Deno.makeTempDir()
|
||||
try {
|
||||
await Deno.writeTextFile(`${tmp}/index.md`, '# hi')
|
||||
await Deno.writeFile(`${tmp}/a.png`, new Uint8Array([1]))
|
||||
await Deno.writeFile(`${tmp}/b.jpg`, new Uint8Array([2]))
|
||||
await Deno.writeFile(`${tmp}/a_hu_deadbeef.png`, new Uint8Array([3]))
|
||||
await Deno.writeTextFile(`${tmp}/notes.txt`, 'ignore me')
|
||||
const imgs = await collectImages(tmp)
|
||||
assertEquals(imgs.map((i) => i.fileName).sort(), ['a.png', 'b.jpg'])
|
||||
assertEquals(imgs.find((i) => i.fileName === 'a.png')?.mimeType, 'image/png')
|
||||
} finally {
|
||||
await Deno.remove(tmp, { recursive: true })
|
||||
}
|
||||
})
|
||||
Loading…
Reference in New Issue