/ *
* 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 do 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 } ;