Est.
Last Modification Date
How up-to-date is the jotting you are reading right now? In the upper right corner you can see that this page was originally created in May 2022 and when it was last updated.
I wanted to have this information on all of my pages to give readers a clue as to whether the content is still relevant to them.
The Script
Linux' ls -l
displays the date of the last local modification. But what about the original creation date? That doesn't change over time, so I could just make an entry for each file and take the last modification date from the file system.
On the other hand, all markdown files of this site are stored in a Git project on GitLab. Git should be able to tell me when the file was first created and last modified? At least Git knows the first and last commits of a (possibly moved or renamed) file.
git log --follow --date=format:%m/%d/%Y -- \
"$file" | grep "^Date: "|grep -o '[0-9/]*'
git log --follow --date=format:%m/%d/%Y -- \
"$file" | grep "^Date: "|grep -o '[0-9/]*'
The first and the last lines contain the last modification and the creation date. I store these dates for all my .md
files in build/file_dates.json
. The script is run once when I rebuild the site. One minor drawback to this approach is that getting the last modifications dates this way requires all files to be committed. Calculating the dates changes the file build/file_dates.json
. Thus I typically --amend
the last Git commit once the dates are recalculated.
Actually, I use this approach for the creation date, only. I get the last modification date with
git blame -fewt -- "$file" |\
awk '{if (!last || ($4 > last && $7 != "§")) last = $4} \
END {if (last) print strftime("%m/%d/%Y", last); \
else print "'$created'"}'
git blame -fewt -- "$file" |\
awk '{if (!last || ($4 > last && $7 != "§")) last = $4} \
END {if (last) print strftime("%m/%d/%Y", last); \
else print "'$created'"}'
The advantage is that I can ignore lines with consistency checks when calculating the last modification date.
The JSON File
Typically, build/file_dates.json
changes from build to build because at least one file was altered during the process. To keep the differences between two versions small, I use a special format for the file: The entries are sorted by filename and there are two lines for each file. The first line contains the filename and the creation date, the second line contains the last modification date. This way, usually only the lines with the last modification dates change frequently.
{
"/basics/certificate": { "created": "04/19/2022",
"lastModified": "05/27/2022" },
...
{
"/basics/certificate": { "created": "04/19/2022",
"lastModified": "05/27/2022" },
...
The Vue Component
The HTML for the dates is rendered by the <AsOf>
component:
<template>
<div class="float-right font-mono text-xs text-right
text-brand-dark/75 dark:text-brand/75"
As of {{ lastModified }}<br />
Est. {{ created }}
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vitepress";
import { onMounted, ref } from "vue";
import _dates from "../build/file_dates.json";
const dates: Record<string, { created: string;
lastModified: string }> = _dates;
const route = useRoute();
const created = ref("");
const lastModified = ref("");
onMounted(() => {
const path = route.path;
created.value = dates[path]?.created ?? "recently";
lastModified.value = dates[path]?.lastModified ?? "just now";
});
</script>
<template>
<div class="float-right font-mono text-xs text-right
text-brand-dark/75 dark:text-brand/75"
As of {{ lastModified }}<br />
Est. {{ created }}
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vitepress";
import { onMounted, ref } from "vue";
import _dates from "../build/file_dates.json";
const dates: Record<string, { created: string;
lastModified: string }> = _dates;
const route = useRoute();
const created = ref("");
const lastModified = ref("");
onMounted(() => {
const path = route.path;
created.value = dates[path]?.created ?? "recently";
lastModified.value = dates[path]?.lastModified ?? "just now";
});
</script>
The component asks the VitePress router for the path of the page, fetches the dates for that path from the JSON file and renders them in two lines. The styling is explained in this jotting.
The Vite Plugin
A Vite plugin inserts <AsOf />
between Frontmatter and Markdown in a loader transformation for each .md
file. This way, dates are automatically added to every page on this website.