diff --git a/publish/deno.jsonc b/publish/deno.jsonc index 49b797b..9308dc7 100644 --- a/publish/deno.jsonc +++ b/publish/deno.jsonc @@ -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" }, diff --git a/publish/src/core/image-collector.ts b/publish/src/core/image-collector.ts new file mode 100644 index 0000000..1c3871c --- /dev/null +++ b/publish/src/core/image-collector.ts @@ -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 = { + '.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 { + 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 +} diff --git a/publish/tests/image-collector_test.ts b/publish/tests/image-collector_test.ts new file mode 100644 index 0000000..1b86b4b --- /dev/null +++ b/publish/tests/image-collector_test.ts @@ -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 }) + } +})