You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.2 KiB
97 lines
3.2 KiB
/*
|
|
* Implements a simple markdown blog loader that's used primarily in the
|
|
* `rendered/pages/blog` example. It supports generating an RSS/Atom/JSON
|
|
* feed of pages, loading an index of .md pages, and render markdown with
|
|
* the headers. It uses the `lib/docgen.js:render_with_code` to do the
|
|
* main markdown processing.
|
|
*/
|
|
import path from "path";
|
|
import glob from "fast-glob";
|
|
import assert from "assert";
|
|
import { render_with_code } from "./docgen.js";
|
|
import fs from "fs";
|
|
import { Feed } from "feed";
|
|
// have to use the client config to avoid pino crashing rollup with json errors
|
|
import { base_host } from "../client/config.js";
|
|
|
|
// caches the posts so we don't load them repeatedly during runs
|
|
const POSTS = {};
|
|
|
|
// this keeps POSTS alive, for some reason it disappears during processing
|
|
process.POSTS = POSTS;
|
|
|
|
/*
|
|
Takes a directory of `.md` files and returns all of them rendered
|
|
to HTML+Metadata using `lib/docgen.js:render_with_code`.
|
|
|
|
+ `source string` -- Source directory to read.
|
|
*/
|
|
export const load = (source) => {
|
|
assert(source !== undefined, "source for markdown processing can't be undefined");
|
|
// just a dumb cache to avoid reading the files over and over
|
|
// cache only works if load isn't async!
|
|
let cache = POSTS[source];
|
|
|
|
if(cache === undefined) {
|
|
cache = []; // this is fresh so make a new one
|
|
|
|
let source_path = path.join(process.cwd(), "..", source);
|
|
let posts_regex = path.join(source_path, "*.md");
|
|
assert(!posts_regex.includes("//"), `You have a // in your path which fast-glob hates: ${posts_regex}`);
|
|
|
|
const files = glob.sync(posts_regex.replace(/\\/g, "/"));
|
|
|
|
for(let post of files.reverse()) {
|
|
try {
|
|
const {content, toc, metadata} = render_with_code(source_path, post);
|
|
assert(content && toc && metadata, `Rendering ${source} failed.`);
|
|
|
|
// so many Svelte builders (like 7ty) need slug that we should so it here
|
|
cache.push({content, toc, metadata, slug: metadata.slug});
|
|
} catch(error) {
|
|
console.error(error, `Failure processing post: ${post}`);
|
|
}
|
|
}
|
|
|
|
POSTS[source] = cache;
|
|
return cache;
|
|
} else {
|
|
return cache;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Renders the `/public/feed.rss`, `/public/feed.atom`, and `/public/feed.json` files
|
|
based on the `index_config` and posts from `load`. The `index_config` is a `.json`
|
|
file that describes the blog. The current configuration can be
|
|
found in `renderd/feed_config.json`.
|
|
|
|
|
|
+ `index_config string` -- The path to the `feed_config.json` file.
|
|
+ `posts Array` -- List of posts.
|
|
*/
|
|
export const render_feed = (index_config, posts) => {
|
|
const index = JSON.parse(fs.readFileSync(index_config));
|
|
const feed = new Feed(index);
|
|
index.updated = new Date();
|
|
|
|
for(let post of posts) {
|
|
post.url = `${base_host}/blog/${post.slug}/`;
|
|
|
|
feed.addItem({
|
|
title: post.metadata.title,
|
|
id: post.metadata.url,
|
|
link: post.metadata.url,
|
|
date: new Date(post.metadata.date),
|
|
description: post.metadata.summary,
|
|
content: post.content,
|
|
author: index.author
|
|
});
|
|
}
|
|
|
|
fs.writeFileSync('../public/feed.rss', feed.rss2());
|
|
fs.writeFileSync('../public/feed.json', feed.json1());
|
|
fs.writeFileSync('../public/feed.atom', feed.atom1());
|
|
}
|
|
|
|
export default { load, render_feed };
|
|
|