93 lines
2.8 KiB
TypeScript
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));
|
|
}
|