108 lines
2.6 KiB
JavaScript
108 lines
2.6 KiB
JavaScript
import fs from 'fs/promises'
|
|
import path from 'path'
|
|
import sharp from 'sharp'
|
|
|
|
const getDataPath = (filename) => {
|
|
const cwd = process.cwd()
|
|
if (cwd.endsWith('.output')) return path.join(cwd, '../server/data', filename)
|
|
return path.join(cwd, 'server/data', filename)
|
|
}
|
|
|
|
const GALERIE_DIR = getDataPath('galerie')
|
|
const GALERIE_METADATA = getDataPath('galerie-metadata.json')
|
|
|
|
async function readJsonArray(file) {
|
|
try {
|
|
const data = await fs.readFile(file, 'utf-8')
|
|
const parsed = JSON.parse(data)
|
|
return Array.isArray(parsed) ? parsed : []
|
|
} catch (e) {
|
|
if (e.code === 'ENOENT') return []
|
|
throw e
|
|
}
|
|
}
|
|
|
|
async function writeJson(file, obj) {
|
|
await fs.writeFile(file, JSON.stringify(obj, null, 2), 'utf-8')
|
|
}
|
|
|
|
async function ensureDirs() {
|
|
await fs.mkdir(path.join(GALERIE_DIR, 'originals'), { recursive: true })
|
|
await fs.mkdir(path.join(GALERIE_DIR, 'previews'), { recursive: true })
|
|
}
|
|
|
|
async function fileExists(p) {
|
|
try {
|
|
await fs.access(p)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function generatePreviewForEntry(entry, size) {
|
|
const original = path.join(GALERIE_DIR, 'originals', entry.filename)
|
|
if (!(await fileExists(original))) return { ok: false, reason: 'missing original' }
|
|
|
|
const previewFilename = entry.previewFilename && String(entry.previewFilename).trim() !== ''
|
|
? entry.previewFilename
|
|
: `preview_${entry.filename}`
|
|
|
|
const preview = path.join(GALERIE_DIR, 'previews', previewFilename)
|
|
|
|
await sharp(original)
|
|
.rotate()
|
|
.resize(size, size, {
|
|
fit: 'cover',
|
|
withoutEnlargement: true
|
|
})
|
|
.jpeg({ quality: 82, mozjpeg: true })
|
|
.toFile(preview)
|
|
|
|
return { ok: true, previewFilename }
|
|
}
|
|
|
|
async function main() {
|
|
const size = Number(process.env.GALERIE_PREVIEW_SIZE || 300)
|
|
await ensureDirs()
|
|
|
|
const entries = await readJsonArray(GALERIE_METADATA)
|
|
if (entries.length === 0) {
|
|
console.log('Keine Galerie-Metadaten gefunden.')
|
|
return
|
|
}
|
|
|
|
let changed = 0
|
|
let generated = 0
|
|
let skipped = 0
|
|
|
|
for (const entry of entries) {
|
|
if (!entry || !entry.filename) {
|
|
skipped++
|
|
continue
|
|
}
|
|
|
|
const res = await generatePreviewForEntry(entry, size)
|
|
if (!res.ok) {
|
|
skipped++
|
|
continue
|
|
}
|
|
|
|
generated++
|
|
|
|
if (entry.previewFilename !== res.previewFilename) {
|
|
entry.previewFilename = res.previewFilename
|
|
changed++
|
|
}
|
|
}
|
|
|
|
if (changed > 0) await writeJson(GALERIE_METADATA, entries)
|
|
|
|
console.log(`Previews erzeugt: ${generated}, übersprungen: ${skipped}, metadata-updates: ${changed}`)
|
|
}
|
|
|
|
main().catch(e => {
|
|
console.error(e)
|
|
process.exit(1)
|
|
})
|