www/scripts/generate-metadata.js

131 lines
3.9 KiB
JavaScript
Raw Permalink Normal View History

const path = require('path')
const fs = require('fs/promises')
const gitRef = process.env.WWW_GIT_REF ?? 'master'
async function readFirstLines(filePath, lineCount = 1) {
const gitFileFetch = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/raw/${filePath}?ref=${gitRef}`)
if (!gitFileFetch.ok) return null
const file = await gitFileFetch.text()
const lines = file.split('\n')
const out = []
for (let i = 0; i < lineCount && i < lines.length; i++) {
out.push(lines[i])
}
return out
}
async function getTitle(filePath) {
const firstLines = await readFirstLines(filePath)
if (firstLines === null || firstLines === undefined || firstLines.length === 0) return null
let title = firstLines[0]
if (title.substring(0, 2) !== '# ') return null
title = title
.substring(1, firstLines[0].length)
.trim()
if (title.length < 3)
return null
return title
}
async function getMarkdownMetadata(dir) {
const dirGitInfoFetch = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/contents/${dir}/?ref=${gitRef}`)
if (!dirGitInfoFetch.ok) return {}
const commits = {}
const out = {}
const dirGitInfo = await dirGitInfoFetch.json()
for (const file of dirGitInfo) {
if (file.name.startsWith('.') || !file.name.endsWith('.md')) continue
const title = await getTitle(file.path)
if (title === null) continue
const slug = file.name.replace(/\.md$/, '')
let mtime = new Date(); // better to have an incorrect recent date than the more incorrect unix time 0 (assuming the host doesn't have messed up clock)
if (!(file.last_commit_sha in commits)) {
const lastCommitSha = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/git/commits/${file.last_commit_sha}`)
if (lastCommitSha.ok) {
const commitJson = await lastCommitSha.json()
commits[commitJson.sha] = (new Date(commitJson.created))
}
}
mtime = commits[file.last_commit_sha]
out[slug] = {
title: title,
mtime: mtime.toISOString(),
}
}
return out
}
async function readFilesMetadata(dir) {
const filePath = jsonFilePath(dir)
try {
const fileContent = await fs.readFile(filePath, 'utf-8')
const metadata = JSON.parse(fileContent)
return metadata
} catch {
return []
}
}
async function writeFilesMetadata(filePath, metadata) {
try {
await fs.writeFile(filePath, JSON.stringify(metadata, null, 4), 'utf-8')
} catch (error) {
console.error(error)
}
}
function jsonFilePath(dir) {
return path.join(process.cwd(), 'public', `${dir}.json`); // ehh
}
async function generateNotesMetadata() {
const dir = 'notes'
await writeFilesMetadata(jsonFilePath(dir), await getMarkdownMetadata(dir))
}
async function generatePostsMetadata() {
const dir = 'posts'
const currMetadata = await readFilesMetadata(dir)
const generatedMetadata = await getMarkdownMetadata(dir)
const newMetadata = {}
for (const [name, data] of Object.entries(generatedMetadata)) {
let otime = new Date()
if (currMetadata[name]?.otime !== undefined && currMetadata[name]?.otime !== null)
otime = currMetadata[name].otime ?? otime
else
otime = data.mtime ?? otime
newMetadata[name] = { ...data, otime }
}
await writeFilesMetadata(jsonFilePath(dir), newMetadata)
}
async function generateSiteMap() {
await generateNotesMetadata()
await generatePostsMetadata()
const sitemap = {
title: 'PaulW.XYZ',
pages: await readFilesMetadata('home')
}
const pages = ['posts', 'notes']
for (const page of pages) {
sitemap.pages[page].pages = await readFilesMetadata(page)
}
await writeFilesMetadata(jsonFilePath('sitemap'), sitemap)
}
generateSiteMap()