feat: updated date parsing logic

This commit is contained in:
Leyla Becker 2026-02-10 15:56:01 -06:00
parent d354c2ca37
commit 68addeb938
5 changed files with 40 additions and 30 deletions

View file

@ -6,7 +6,7 @@ layout: base.njk
<header class="post-header"> <header class="post-header">
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
<time datetime="{{ createdAt | dateFormat }}">{{ createdAt | dateFormat }}</time> <time datetime="{{ createdAt | dateFormat }}">{{ createdAt | dateFormat }}</time>
{% if updatedAt %} {% if updatedAt and (updatedAt | isMoreThanHourAfter(createdAt)) %}
<p class="updated-at">Updated: <time datetime="{{ updatedAt | dateFormat }}">{{ updatedAt | dateFormat }}</time></p> <p class="updated-at">Updated: <time datetime="{{ updatedAt | dateFormat }}">{{ updatedAt | dateFormat }}</time></p>
{% endif %} {% endif %}
</header> </header>

View file

@ -4,6 +4,7 @@ const markdownItFootnote = require("markdown-it-footnote");
const markdownItMermaid = require('markdown-it-mermaid').default const markdownItMermaid = require('markdown-it-mermaid').default
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight"); const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const fs = require("fs"); const fs = require("fs");
const { DateTime } = require("luxon");
const tagPattern = /(?<=^|\s)#([a-zA-Z][a-zA-Z0-9_]*)(?![a-zA-Z0-9_-])/g; const tagPattern = /(?<=^|\s)#([a-zA-Z][a-zA-Z0-9_]*)(?![a-zA-Z0-9_-])/g;
@ -111,18 +112,30 @@ module.exports = (eleventyConfig) => {
eleventyConfig.setLibrary("md", md); eleventyConfig.setLibrary("md", md);
eleventyConfig.addFilter("dateFormat", (date) => { eleventyConfig.addFilter("dateFormat", (date) => {
const d = new Date(date); const dt = date instanceof Date
return d.toLocaleDateString('en-US', { ? DateTime.fromJSDate(date)
year: 'numeric', : DateTime.fromISO(date);
month: 'long', return dt.toFormat('MMMM d, yyyy');
day: 'numeric',
timeZone: 'UTC'
});
}); });
eleventyConfig.addFilter("isoDate", (date) => { eleventyConfig.addFilter("isoDate", (date) => {
const d = new Date(date); const dt = date instanceof Date
return d.toISOString().split('T')[0]; ? DateTime.fromJSDate(date)
: DateTime.fromISO(date);
return dt.toISODate();
});
eleventyConfig.addFilter("isMoreThanHourAfter", (date1, date2) => {
if (!date1 || !date2) return false;
const toDateTime = (d) => {
if (DateTime.isDateTime(d)) return d;
if (d instanceof Date) return DateTime.fromJSDate(d);
return DateTime.fromISO(d);
};
const dt1 = toDateTime(date1);
const dt2 = toDateTime(date2);
const diff = dt1.diff(dt2, 'hours').hours;
return Math.abs(diff) > 1;
}); });
eleventyConfig.addCollection("posts", (collectionApi) => { eleventyConfig.addCollection("posts", (collectionApi) => {

View file

@ -14,6 +14,7 @@
"dependencies": { "dependencies": {
"@11ty/eleventy": "^3.1.2", "@11ty/eleventy": "^3.1.2",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2", "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"luxon": "^3.7.2",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-container": "^4.0.0", "markdown-it-container": "^4.0.0",
"markdown-it-footnote": "^4.0.0", "markdown-it-footnote": "^4.0.0",

3
pnpm-lock.yaml generated
View file

@ -14,6 +14,9 @@ importers:
'@11ty/eleventy-plugin-syntaxhighlight': '@11ty/eleventy-plugin-syntaxhighlight':
specifier: ^5.0.2 specifier: ^5.0.2
version: 5.0.2 version: 5.0.2
luxon:
specifier: ^3.7.2
version: 3.7.2
markdown-it: markdown-it:
specifier: ^14.1.0 specifier: ^14.1.0
version: 14.1.0 version: 14.1.0

View file

@ -1,6 +1,7 @@
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const { execSync } = require("child_process"); const { execSync } = require("child_process");
const { DateTime } = require("luxon");
const getGitCreatedTime = (filePath) => { const getGitCreatedTime = (filePath) => {
try { try {
@ -9,7 +10,7 @@ const getGitCreatedTime = (filePath) => {
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] } { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
).trim(); ).trim();
if (result) { if (result) {
return new Date(result); return DateTime.fromISO(result);
} }
} catch (e) { } catch (e) {
// Git command failed, return null // Git command failed, return null
@ -24,7 +25,7 @@ const getGitModifiedTime = (filePath) => {
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] } { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
).trim(); ).trim();
if (result) { if (result) {
return new Date(result); return DateTime.fromISO(result);
} }
} catch (e) { } catch (e) {
// Git command failed, return null // Git command failed, return null
@ -43,7 +44,8 @@ const getTitleFromFilename = (filePath) => {
const getFileCreatedTime = (filePath) => { const getFileCreatedTime = (filePath) => {
try { try {
const stats = fs.statSync(filePath); const stats = fs.statSync(filePath);
return stats.birthtime || stats.mtime; const time = stats.birthtime ?? stats.mtime;
return DateTime.fromJSDate(time);
} catch (e) { } catch (e) {
return null; return null;
} }
@ -52,7 +54,7 @@ const getFileCreatedTime = (filePath) => {
const getFileModifiedTime = (filePath) => { const getFileModifiedTime = (filePath) => {
try { try {
const stats = fs.statSync(filePath); const stats = fs.statSync(filePath);
return stats.mtime; return DateTime.fromJSDate(stats.mtime);
} catch (e) { } catch (e) {
return null; return null;
} }
@ -60,9 +62,10 @@ const getFileModifiedTime = (filePath) => {
const parseDate = (value) => { const parseDate = (value) => {
if (!value) return null; if (!value) return null;
if (value instanceof Date) return value; if (DateTime.isDateTime(value)) return value;
const parsed = new Date(value); if (value instanceof Date) return DateTime.fromJSDate(value);
return isNaN(parsed.getTime()) ? null : parsed; const parsed = DateTime.fromISO(value);
return parsed.isValid ? parsed : null;
} }
const getPostCreatedAt = (data) => { const getPostCreatedAt = (data) => {
@ -79,7 +82,7 @@ const getPostCreatedAt = (data) => {
return fileDate; return fileDate;
} }
return data.page.date; return DateTime.fromJSDate(data.page.date);
} }
module.exports = { module.exports = {
@ -95,19 +98,9 @@ module.exports = {
}, },
createdAt: getPostCreatedAt, createdAt: getPostCreatedAt,
updatedAt: (data) => { updatedAt: (data) => {
const modifiedDate = parseDate(data.updatedAt) ?? return parseDate(data.updatedAt) ??
getGitModifiedTime(data.page.inputPath) ?? getGitModifiedTime(data.page.inputPath) ??
getFileModifiedTime(data.page.inputPath); getFileModifiedTime(data.page.inputPath);
const createdDate = getPostCreatedAt(data);
if (modifiedDate) {
// Only return updatedAt if it's AFTER created date (by more than a day)
const dayInMs = 24 * 60 * 60 * 1000;
if (modifiedDate > createdDate && (modifiedDate - createdDate) > dayInMs) {
return modifiedDate;
}
}
return createdDate;
}, },
permalink: (data) => { permalink: (data) => {
const title = data.title || getTitleFromFilename(data.page.inputPath); const title = data.title || getTitleFromFilename(data.page.inputPath);
@ -115,7 +108,7 @@ module.exports = {
const createdDate = getPostCreatedAt(data); const createdDate = getPostCreatedAt(data);
const isoDate = createdDate.toISOString().split('T')[0]; const isoDate = createdDate.toISODate();
return `/post/${slug}/${isoDate}/`; return `/post/${slug}/${isoDate}/`;
} }
} }