Bläddra i källkod

Gallery final ✅

volt 3 månader sedan
förälder
incheckning
0bdfc044ac
14 ändrade filer med 182 tillägg och 46 borttagningar
  1. BIN
      _data/images/photos/IMG_0170.jpeg
  2. BIN
      _data/images/photos/IMG_4512.jpeg
  3. 1 1
      about.md
  4. 64 0
      bundle.css
  5. 54 17
      eleventy.config.js
  6. 9 5
      gallery.njk
  7. 47 0
      image_show.njk
  8. 2 2
      includes/topbar.html
  9. 1 1
      index.md
  10. 0 0
      layouts/home.njk
  11. 1 1
      layouts/note.njk
  12. 0 17
      layouts/page.njk
  13. 1 1
      notes.md
  14. 2 1
      package.json

BIN
_data/images/photos/IMG_0170.jpeg


BIN
_data/images/photos/IMG_4512.jpeg


+ 1 - 1
about.md

@@ -1,5 +1,5 @@
 ---
-layout: page.njk
+layout: main_layout.njk
 title: Hi you
 ---
 # Why is there even a website here?

+ 64 - 0
bundle.css

@@ -146,4 +146,68 @@ code {
 
 .page-footer {
     float: right;
+}
+
+/* Gallery Styles for a Premium Look */
+/* ================================= */
+.gallery-grid {
+  display: grid;
+  /* Adjust 200px to make your thumbnails larger or smaller */
+  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+  gap: 1.5rem;
+  padding: 1rem;
+}
+
+.gallery-item {
+  position: relative;
+  aspect-ratio: 1 / 1; /* Makes every item a perfect square */
+  overflow: hidden;
+  border-radius: 8px;
+  background: #222; /* Placeholder color while loading */
+  transition: transform 0.3s ease;
+}
+
+.gallery-item img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover; /* Crops the image to fill the square without stretching */
+  display: block;
+}
+
+/* Hover Effects to make it feel "Premium" */
+.gallery-item:hover {
+  transform: scale(1.02);
+  z-index: 10;
+}
+
+.meta-overlay {
+  position: absolute;
+  inset: 0;
+  background: rgba(0, 0, 0, 0.4);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  opacity: 0;
+  transition: opacity 0.3s ease;
+  color: white;
+  font-weight: bold;
+}
+
+.gallery-item:hover .meta-overlay {
+  opacity: 1;
+}
+
+.back-link {
+    margin-left: 25px;
+}
+.single_image ul li {
+    list-style-type: none;
+    font-size: 80%;
+}
+
+.uploaded-date {
+    font-size: 80%;
+    text-align: center;
+    color: #555555;
+    margin-top: 10px;
 }

+ 54 - 17
eleventy.config.js

@@ -2,6 +2,7 @@ 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");
@@ -34,30 +35,50 @@ eleventyConfig.addCollection("miniImages", function(collectionApi) {
 
     // Recursive function to find all jpgs
     const getFiles = (dir) => {
+      if (!fs.existsSync(dir)) return; // [EXIF] 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(".png") ||
+                  file.endsWith(".gif") ||
+                  file.endsWith(".webp")) {
+          // .jpg an others extensions might be case sensitive on some systems !!
           
+          // READ EXIF DATA
+          let exifData = {};
+          try {
+            const buffer = fs.readFileSync(fullPath);
+            const parser = exifParser.create(buffer);
+            const result = parser.parse();
+            
+            exifData = {
+              model: result.tags.Model || "Unknown Camera",
+              lens: result.tags.LensModel || "Unknown Lens",
+              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(`Could not parse EXIF for ${file}:`, e.message);
+          }
+          // 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
           // ====================
 
           files.push({
-            // AFTER ==============
             fullPath: fullPath, // We need this for the calculation below
             //webPath: fullPath.replace("src/", "/"), 
             date: fs.statSync(fullPath).mtime,
-            // BEFORE =============
             path: "/photos/" + relativePath,
-            //album: dir.split(path.sep).pop(), // Gets the folder name
-            //breadcrumbs: pathParts,
-            //date: fs.statSync(fullPath).mtime
-            // ====================
+            folderPath: path.relative(baseDir, path.dirname(fullPath)),
+            exif: exifData,
           });
         }
       });
@@ -69,12 +90,7 @@ eleventyConfig.addCollection("miniImages", function(collectionApi) {
     const grouped = {};
 
     files.forEach(f => {
-      // AFTER ==============
       const relFolder = path.relative(baseDir, path.dirname(f.fullPath));
-      // BEFORE =============
-      // Use the directory path as the unique ID (e.g., "wargaming/40k/orks")
-      //const folderPath = path.dirname(path.relative("./_data/images", f.path));
-      
 
       if (!grouped[relFolder]) {
         grouped[relFolder] = {
@@ -102,14 +118,35 @@ eleventyConfig.addCollection("miniImages", function(collectionApi) {
       }
     }
     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, 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?

+ 9 - 5
gallery.njk

@@ -36,15 +36,18 @@ permalink: "/gallery/{{ albumName | slugify }}/index.html"
 {# 2. List Images #}
 <div class="gallery-grid">
   {% for photo in currentData.images | sort(attribute='date') | reverse %}
-    <img src="{{ photo.path }}" alt="photo_{{ loop.index }}" loading="lazy">
-    <div class="meta">
-        <span>{{ photo.date | date('YYYY-MM-DD') }}</span>
-    </div>
+    <a href="/gallery/single/{{ photo.path | slugify }}/index.html" class="gallery-item">
+      <img src="{{ photo.path }}" alt="photo_{{ loop.index }}" loading="lazy">
+      <div class="meta-overlay">
+          <span>{{ photo.date | date('YYYY-MM-DD') }}</span>
+      </div>
+    </a>
   {% else %}
     <p>No photos found in this album.</p>
   {% endfor %}
 </div>
 
+<!--
 <p class="pagination">
     {% if page.url != pagination.href.last %}
         <a href="{{ pagination.href.next }}">⬅️ Prev Page</a>
@@ -52,4 +55,5 @@ permalink: "/gallery/{{ albumName | slugify }}/index.html"
     {% if page.url != pagination.href.first %}
         <a href="{{ pagination.href.previous }}">Next Page ➡️</a>
     {% endif %}
-</p>
+</p>
+-->

+ 47 - 0
image_show.njk

@@ -0,0 +1,47 @@
+---
+layout: main_layout.njk
+title: unakt - Image
+pagination:
+  data: collections.allPhotos
+  size: 1
+  alias: photo
+permalink: "/gallery/single/{{ photo.path | slugify }}/index.html"
+---
+
+{% set photo = pagination.items[0] %}
+
+<nav class="breadcrumbs">
+  <a href="/gallery/">Gallery</a>
+  {% set pathAcc = "" %}
+  {# Split the folderPath (e.g., "tabletop/orks") into segments #}
+  {% for part in photo.folderPath.split('/') %}
+    {% if part %}
+      {% set pathAcc = (pathAcc + "-" + part) if pathAcc else part %}
+      <span> / </span>
+      {# Link back to the album view we created earlier #}
+      <a href="/gallery/{{ pathAcc }}/">{{ part | capitalize }}</a>
+    {% endif %}
+  {% endfor %}
+  <span> / Image</span>
+</nav>
+
+<div class="single_image">
+  <!-- <a href="javascript:history.back()" class="back-link">⬅️ Back to Album</a> -->
+  {% if photo.exif.model %}
+  <ul>
+    <li><strong>Camera:</strong>
+    {{ photo.exif.model | default("Unknown") }} - 
+    <strong>Lens:</strong> 
+    {{ photo.exif.lens | default("N/A") }}
+    </li>
+    <li><strong>Settings:</strong> 
+      {{photo.exif.fNumber | default("N/A") }} - 
+      {{ photo.exif.exposure | default("N/A") }} - 
+      ISO {{ photo.exif.iso | default("N/A") }} -
+      {{ photo.exif.focalLength | default("N/A") }}mm
+    </li>
+  </ul>
+  {% endif %}
+  <img src="{{ photo.path }}" alt="photo" style="max-width: 100%; height: auto;">
+  <p class="uploaded-date">Uploaded on: {{ photo.date | date('YYYY-MM-DD') }}</p>
+</div>

+ 2 - 2
includes/topbar.html

@@ -4,9 +4,9 @@
     </a>
 
     <nav class="topnav">
-        <a href="/">Home</a>
+        <a href="/">Blog</a>
         <a href="/gallery">Photos</a>
         <a href="/about">About Me</a>
-        <a href="/notes">Notes</a>
+        <!-- <a href="/notes">Notes</a>-->
     </nav>
 </header>

+ 1 - 1
index.md

@@ -1,5 +1,5 @@
 ---
-layout: default.njk
+layout: home.njk
 title: unakt - hi
 ---
 Hi, I'm unakt - a living mess from France doing his best to sort things up.

+ 0 - 0
layouts/default.njk → layouts/home.njk


+ 1 - 1
layouts/note.njk

@@ -1,5 +1,5 @@
 ---
-layout: default.njk
+layout: main_layout.njk
 ---
 <article>
     {{ content | safe }}

+ 0 - 17
layouts/page.njk

@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    {% include 'head.html' %}
-</head>
-<body>
-    {% include 'topbar.html' %}
-
-    <article>
-    {{ content | safe }}
-    </article>
-
-<footer class="page-footer">
-        <small>- {{ site.author }}</small>
-    </footer>
-</body>
-</html>

+ 1 - 1
notes.md

@@ -1,5 +1,5 @@
 ---
-layout: page.njk
+layout: main_layout.njk
 title: unakt - notes
 ---
 

+ 2 - 1
package.json

@@ -14,6 +14,7 @@
   "license": "ISC",
   "type": "commonjs",
   "dependencies": {
-    "@11ty/eleventy": "^3.1.2"
+    "@11ty/eleventy": "^3.1.2",
+    "exif-parser": "^0.1.12"
   }
 }