module.exports = function(eleventyConfig) { const fs = require('fs'); const path = require('path'); const exifParser = require("exif-parser"); // add my css file from the root folder eleventyConfig.addPassthroughCopy("bundle.css"); eleventyConfig.addPassthroughCopy("img"); eleventyConfig.addPassthroughCopy({ "_data/images": "photos" }); // This line was to make sure my post.md weren't processed as Liquid, // permitting this post here eleventyConfig.setTemplateFormats(["md", "njk", "html"]); eleventyConfig.addGlobalData("site.author", "unakt"); // Double with the .eleventyignore file, but just in case eleventyConfig.ignores.add("/_drafts/**"); eleventyConfig.ignores.add("/README.md"); eleventyConfig.addLayoutAlias("post", "post.njk"); eleventyConfig.addCollection("postlist", function(collectionApi) { return collectionApi.getFilteredByGlob("./posts/*.md"); }); // Custom collection for mini images // It scans the ./src/_data/images/ folder for jpg files // and groups them by their parent folder name // Each image object contains its path, album name, and last modified date // ======================================================== eleventyConfig.addCollection("miniImages", function(collectionApi) { const files = []; const baseDir = "./_data/images/"; // Recursive function to find all images const getFiles = (dir) => { if (!fs.existsSync(dir)) return; // Safety check fs.readdirSync(dir).forEach(file => { const fullPath = path.join(dir, file); if (fs.statSync(fullPath).isDirectory()) { getFiles(fullPath); } else if (file.endsWith(".jpg") || file.endsWith(".jpeg") || file.endsWith(".png") || file.endsWith(".gif") || file.endsWith(".webp")) { // .jpg an others extensions might be case sensitive on some systems !! // READ EXIF DATA let exifDate = null; try { const buffer = fs.readFileSync(fullPath); const parser = exifParser.create(buffer); const result = parser.parse(); // Grab Exif Date of photo taken (if exists) if (result.tags.DateTimeOriginal) { exifDate = new Date(result.tags.DateTimeOriginal * 1000); } exifData = { model: result.tags.Model || "Unknown", lens: result.tags.LensModel || "Unknown", focalLength: result.tags.FocalLength ? `${result.tags.FocalLength}` : "N/A", fNumber: result.tags.FNumber ? `f/${result.tags.FNumber}` : "N/A", exposure: result.tags.ExposureTime ? `1/${Math.round(1/result.tags.ExposureTime)}s` : "N/A", iso: result.tags.ISO || "N/A" }; } catch (e) { console.error(`Skipping ${file}: No valid EXIF date found.`); } // END READ EXIF DATA // BEFORE ============= const relativePath = path.relative("./_data/images", fullPath).replace(/\\/g, "/"); //const pathParts = relativePath.split(path.sep).slice(0, -1); // Make Breadcrumb // ==================== // Only add real photos with EXIF date if (exifDate) { files.push({ fullPath: fullPath, // We need this for the calculation below //webPath: fullPath.replace("src/", "/"), date: exifDate, path: "/photos/" + relativePath, folderPath: path.relative(baseDir, path.dirname(fullPath)), exif: exifData, }); } } }); }; getFiles(baseDir); // Group them by album name const grouped = {}; // This here ? or just before return grouped ? files.sort((a, b) => a.date - b.date); files.forEach(f => { const relFolder = path.relative(baseDir, path.dirname(f.fullPath)); if (!grouped[relFolder]) { grouped[relFolder] = { images: [], subfolders: [], breadcrumbArray: relFolder === "" ? [] : relFolder.split(path.sep) //path: folderPath.split(path.sep) // Normalize to forward slashes }; } grouped[relFolder].images.push(f); }); // Second pass to link parents to children subfolders for (const parentPath in grouped) { for (const potentialChild in grouped) { const parentParts = parentPath === "" ? [] : parentPath.split(path.sep); const childParts = potentialChild.split(path.sep); // Is the child exactly one level deeper than the parent? if (potentialChild.startsWith(parentPath) && childParts.length === parentParts.length + 1 && parentPath !== potentialChild) { grouped[parentPath].subfolders.push(potentialChild); } } } return grouped; }); // ======================================================== eleventyConfig.addCollection("allPhotos", function(collectionApi) { //const grouped = collectionApi.getFilteredByTag("miniImages"); // This won't work since miniImages isn't a tag // Instead, use the logic we already built: const miniImages = collectionApi.getAll()[0].data.collections.miniImages; return Object.values(miniImages).flatMap(album => album.images); }); // Date filter to format dates as YYYY-MM-DD //eleventyConfig.addFilter("date", function(dateObj, format = "YYYY-MM-DD") { // const d = new Date(dateObj); // return d.toISOString().split('T')[0]; // Returns YYYY-MM-DD // }); //eleventyConfig.addFilter("date", function(dateObj) { // const d = new Date(dateObj); // // Check if the date is actually valid // if (isNaN(d.getTime())) { // console.warn("Skipping invalid date for a file. Value received:", dateObj); // return "Date Unknown"; // } // return d.toISOString().split('T')[0]; //}); return { // Ok idk this prevent markdown from being processed? markdownTemplateEngine: false, dir: { input: "./", output: "_site", layouts: "layouts", includes: "includes" } }; };