Files

57 lines
2.2 KiB
JavaScript

import slugify from 'slugify';
/**
* Normalizes a filename: slugifies the NAME part (diacritics, spaces, case)
* while preserving the extension. Keeps uploaded media URLs clean and portable.
*
* "Zdjęcie jeden nad morzem.jpg" → "zdjecie-jeden-nad-morzem.jpg"
* "Faktura #12 (2024).PDF" → "faktura-12-2024.pdf"
* "already-clean.webp" → "already-clean.webp"
*
* Why not toSlug(): toSlug uses strict:true, which would strip the dot and
* merge name+extension. Here we split on the LAST dot, slug the stem, lowercase
* the extension, and rejoin.
*/ export function normalizeFilename(filename) {
const lastDot = filename.lastIndexOf('.');
// No extension (or leading-dot dotfile) → slug the whole thing.
if (lastDot <= 0) {
return slugify(filename, {
lower: true,
strict: true,
trim: true
});
}
const stem = filename.slice(0, lastDot);
const ext = filename.slice(lastDot + 1).toLowerCase();
const cleanStem = slugify(stem, {
lower: true,
strict: true,
trim: true
});
const cleanExt = slugify(ext, {
lower: true,
strict: true,
trim: true
});
// Stem could slug to empty (e.g. filename was all symbols) — fall back so we
// never produce a nameless file.
const safeStem = cleanStem || 'plik';
return cleanExt ? `${safeStem}.${cleanExt}` : safeStem;
}
/**
* beforeOperation hook for an upload collection (e.g. Media). Rewrites the
* incoming file's name to its normalized form before Payload stores it, so both
* the stored file and its DB filename are clean. Works with local disk and with
* cloud storage adapters (R2/S3) — it runs before the storage layer.
*
* Wire into your Media collection:
* import { normalizeFilenameHook } from '@intecion/ipal-kit'
* hooks: { beforeOperation: [normalizeFilenameHook] }
*/ export const normalizeFilenameHook = ({ req, operation })=>{
if (operation !== 'create' && operation !== 'update') return;
const file = req.file;
if (file?.name) {
file.name = normalizeFilename(file.name);
}
};
//# sourceMappingURL=normalizeFilename.js.map