const path = require("path"); const fs = require("fs"); const { execSync } = require("child_process"); const { DateTime } = require("luxon"); const getGitCreatedTime = (filePath) => { try { const result = execSync( `git log --diff-filter=A --follow --format=%aI -- "${filePath}" | tail -1`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] } ).trim(); if (result) { return DateTime.fromISO(result); } } catch (e) { // Git command failed, return null } return null; }; const getGitModifiedTime = (filePath) => { try { const result = execSync( `git log -1 --format=%aI -- "${filePath}"`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] } ).trim(); if (result) { return DateTime.fromISO(result); } } catch (e) { // Git command failed, return null } return null; }; const getTitleFromFilename = (filePath) => { const basename = path.basename(filePath, '.md'); return basename .split('-') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); } const getFileCreatedTime = (filePath) => { try { const stats = fs.statSync(filePath); const time = stats.birthtime ?? stats.mtime; return DateTime.fromJSDate(time); } catch (e) { return null; } } const getFileModifiedTime = (filePath) => { try { const stats = fs.statSync(filePath); return DateTime.fromJSDate(stats.mtime); } catch (e) { return null; } } const parseDate = (value) => { if (!value) return null; if (DateTime.isDateTime(value)) return value; if (value instanceof Date) return DateTime.fromJSDate(value); const parsed = DateTime.fromISO(value); return parsed.isValid ? parsed : null; } const getPostCreatedAt = (data) => { const frontmatterDate = parseDate(data.createdAt); if (frontmatterDate) { return frontmatterDate; } const gitDate = getGitCreatedTime(data.page.inputPath); if (gitDate) { return gitDate; } const fileDate = getFileCreatedTime(data.page.inputPath); if (fileDate) { return fileDate; } return DateTime.fromJSDate(data.page.date); } module.exports = { layout: "post.njk", tags: ["posts"], eleventyComputed: { released: (data) => { if(data.page.inputPath.startsWith('./posts/drafts/')) { return false } return true }, title: (data) => { if (data.title && data.title !== data.page.fileSlug) { return data.title; } return getTitleFromFilename(data.page.inputPath); }, createdAt: getPostCreatedAt, updatedAt: (data) => { return parseDate(data.updatedAt) ?? getGitModifiedTime(data.page.inputPath) ?? getFileModifiedTime(data.page.inputPath); }, permalink: (data) => { const title = data.title || getTitleFromFilename(data.page.inputPath); const slug = title.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]/g, ''); const createdDate = getPostCreatedAt(data); const isoDate = createdDate.toISODate(); return `/post/${slug}/${isoDate}/`; } } };