Fix metagen by using gitea as a source

Signed-off-by: Paul W. <contact@paulw.xyz>
This commit is contained in:
Paul W. 2025-01-04 18:25:49 -05:00
parent c39203207d
commit f282471c76
Signed by: lambda
GPG Key ID: DF12EBB915A949ED

View File

@ -1,136 +1,130 @@
const fs = require('fs/promises'); const path = require('path')
const { createReadStream } = require('fs'); const fs = require('fs/promises')
const path = require('path');
const readline = require('readline/promises'); const gitRef = process.env.WWW_GIT_REF ?? 'master'
// const { info } = require('console');
async function readFirstLines(filePath, lineCount = 1) { async function readFirstLines(filePath, lineCount = 1) {
return new Promise((resolve, reject) => { const gitFileFetch = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/raw/${filePath}?ref=${gitRef}`)
try { if (!gitFileFetch.ok) return null
const stream = createReadStream(filePath, { encoding: 'utf-8' }); const file = await gitFileFetch.text()
const rl = readline.createInterface({ input: stream }); const lines = file.split('\n')
let counter = 0; const out = []
const lines = []; for (let i = 0; i < lineCount && i < lines.length; i++) {
rl.on('line', (line) => { out.push(lines[i])
counter++;
lines.push(line);
if (counter >= lineCount) {
rl.close();
rl.removeAllListeners();
} }
}); return out
rl.on('close', () => {
resolve(lines)
});
} catch (e) {
reject(e)
}
});
} }
async function getTitle(filePath) { async function getTitle(filePath) {
const firstLines = await readFirstLines(filePath); const firstLines = await readFirstLines(filePath)
if (firstLines === undefined || firstLines.length === 0) if (firstLines === null || firstLines === undefined || firstLines.length === 0) return null
return null; let title = firstLines[0]
let title = firstLines[0];
if (title.substring(0, 2) !== '# ') if (title.substring(0, 2) !== '# ') return null
return null;
title = title title = title
.substring(1, firstLines[0].length) .substring(1, firstLines[0].length)
.trim(); .trim()
if (title.length < 3) if (title.length < 3)
return null; return null
return title; return title
} }
async function getMarkdownMetadata(dir) { async function getMarkdownMetadata(dir) {
const dirPath = path.join(process.cwd(), dir); const dirGitInfoFetch = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/contents/${dir}/?ref=${gitRef}`)
const files = (await fs.readdir(dirPath, 'utf-8')) if (!dirGitInfoFetch.ok) return {}
.filter((file) => {
return /^[^.].*.md$/.test(file); 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)
const out = {}; if (!(file.last_commit_sha in commits)) {
for (const file of files) { const lastCommitSha = await fetch(`https://git.paulw.xyz/api/v1/repos/lambdapaul/www/git/commits/${file.last_commit_sha}`)
const filePath = path.join(dirPath, file); if (lastCommitSha.ok) {
const title = await getTitle(filePath); const commitJson = await lastCommitSha.json()
if (title === null) commits[commitJson.sha] = (new Date(commitJson.created))
continue; }
}
mtime = commits[file.last_commit_sha]
const slug = file.replace(/\.md$/, '');
// const pagePath = path.join('/', dir, slug);
out[slug] = { out[slug] = {
title: title, title: title,
// path: pagePath, mtime: mtime.toISOString(),
mtime: (await fs.stat(filePath)).mtime,
};
} }
return out; }
return out
} }
async function readFilesMetadata(dir) { async function readFilesMetadata(dir) {
const filePath = jsonFilePath(dir); const filePath = jsonFilePath(dir)
try { try {
const fileContent = await fs.readFile(filePath, 'utf-8'); const fileContent = await fs.readFile(filePath, 'utf-8')
const metadata = JSON.parse(fileContent); const metadata = JSON.parse(fileContent)
return metadata; return metadata
} catch { } catch {
return []; return []
} }
} }
async function writeFilesMetadata(filePath, metadata) { async function writeFilesMetadata(filePath, metadata) {
try { try {
await fs.writeFile(filePath, JSON.stringify(metadata), 'utf-8'); await fs.writeFile(filePath, JSON.stringify(metadata, null, 4), 'utf-8')
} catch (error) { } catch (error) {
console.error(error); console.error(error)
} }
} }
function jsonFilePath(dir) { function jsonFilePath(dir) {
return path.join(process.cwd(), 'public', `${dir}.json`); return path.join(process.cwd(), 'public', `${dir}.json`); // ehh
} }
async function generateNotesMetadata() { async function generateNotesMetadata() {
const dir = 'notes'; const dir = 'notes'
await writeFilesMetadata(jsonFilePath(dir), await getMarkdownMetadata(dir)); await writeFilesMetadata(jsonFilePath(dir), await getMarkdownMetadata(dir))
} }
async function generatePostsMetadata() { async function generatePostsMetadata() {
const dir = 'posts'; const dir = 'posts'
const currMetadata = await readFilesMetadata(dir); const currMetadata = await readFilesMetadata(dir)
const generatedMetadata = await getMarkdownMetadata(dir); const generatedMetadata = await getMarkdownMetadata(dir)
const newMetadata = {}; const newMetadata = {}
for (const [name, data] of Object.entries(generatedMetadata)) { for (const [name, data] of Object.entries(generatedMetadata)) {
let otime; let otime = new Date()
if (currMetadata[name] !== undefined && currMetadata[name].otime !== undefined) if (currMetadata[name]?.otime !== undefined && currMetadata[name]?.otime !== null)
otime = currMetadata[name].otime otime = currMetadata[name].otime ?? otime
else else
otime = data.mtime; otime = data.mtime ?? otime
newMetadata[name] = { ...data, otime } newMetadata[name] = { ...data, otime }
} }
await writeFilesMetadata(jsonFilePath(dir), newMetadata); await writeFilesMetadata(jsonFilePath(dir), newMetadata)
} }
async function generateSiteMap() { async function generateSiteMap() {
await generateNotesMetadata(); await generateNotesMetadata()
await generatePostsMetadata(); await generatePostsMetadata()
const sitemap = { const sitemap = {
title: 'PaulW.XYZ', title: 'PaulW.XYZ',
pages: await readFilesMetadata('home') 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); const pages = ['posts', 'notes']
for (const page of pages) {
sitemap.pages[page].pages = await readFilesMetadata(page)
}
await writeFilesMetadata(jsonFilePath('sitemap'), sitemap)
} }
generateSiteMap(); generateSiteMap()