public/ramblings/genfeed.ts

93 lines
2.8 KiB
TypeScript

import { Marked } from "npm:marked@11.1.1";
import hljs from "npm:highlight.js@11.5.1";
import { markedHighlight } from "npm:marked-highlight@2.1.0";
const marked = new Marked(
markedHighlight({
langPrefix: 'hljs language-',
highlight(code: string, lang: string) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
},
})
)
type Item = {
path: string,
title: string,
content: string,
mtime: Date,
}
const renderMarkdown = (item: Item) => `
<!DOCTYPE html>
<html lang="en">
<head>
<title>${item.title}</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel=alternate title="feed" type=application/atom+xml href="/ramblings/feed.xml">
<link rel="stylesheet" href="/assets/style2.css" />
<link rel="stylesheet" href="/assets/code.css" />
</head>
<body>
<header>
<h1>${item.title}</h1>
</header>
<article>
${marked.parse(item.content.split("\n").slice(2).join("\n"))}
</article>
</body>
</html>`.trim();
const renderIndex = (entries: Array<Item>) => {
const a = [...entries];
a.sort((a, b) => +b.mtime - +a.mtime);
return renderMarkdown({
title: "index",
mtime: new Date(),
path: "/index.html",
content: "\n\n" + a.map(i => `- [${i.title}](${i.path.replace(/\.md$/, ".html")})`).join("\n"),
});
}
const renderItem = (item: Item) => `
<item>
<title>${item.title}</title>
<guid>${item.path.replace(/\.md$/, ".html")}</guid>
<link>https://celery.eu.org/ramblings/${item.path.replace(/\.md$/, ".html")}</link>
<content type="html">${marked.parse(item.content)}</content>
<updated>${item.mtime.toISOString()}</updated>
</item>
`.trim();
const renderFeed = (entries: Array<Item>) => `
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/ramblings/feed.xsl" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="https://celery.eu.org/rss.xml" rel="self" type="application/rss+xml" />
<title>celery rss</title>
<link>https://celery.eu.org/ramblings/feed.xml</link>
<description>rss feed for celery.eu.org</description>
${entries.map(renderItem)}</channel>
</rss>
`.trim();
const fileNames = [...Deno.readDirSync(".")].filter(i => i.name.endsWith(".md") && i.isFile).map(i => i.name);
const files: Array<Item> = fileNames.map(i => {
const stat = Deno.statSync(i);
const text = Deno.readTextFileSync(i);
return {
title: text.split("\n")[0].slice("# ".length),
mtime: stat.mtime!,
content: text,
path: i,
}
});
Deno.writeTextFileSync("feed.xml", renderFeed(files));
Deno.writeTextFileSync("index.html", renderIndex(files));
for (const file of files) {
Deno.writeTextFileSync(file.path.replace(/\.md$/, ".html"), renderMarkdown(file));
}