< index | 2021-06-02 | this static sit…

this static site generator

Jekyll and Hugo are overkill for me, so I wrote this small static site generator.

First, I write metadata files in TOML. These contain the post title for slug generation, the date, and a content source, which holds a path to a markdown body text. The generator reads post metadata files, converts the markdown body html, and finally renders a complete html file using a template. It’s about 50 lines of code.

post metadata

# post.toml

title = "some title"
date = 2021-05-31T00:00:00Z
content = "post.md"

The program uses glob to read any .toml files in the source directory. For each metadata file, it also reads the markdown file specified by content.

// main.rs

// `?`s for brevity here.
for mdfile in glob("posts/**/*.toml")? {
	let md: Metadata = toml::from_str(
		&fs::read_to_string(mdfile?)?;
	...
}

content

After reading the post body from the content metadata key, the generator converts the markdown to HTML using the pulldown-cmark crate.

// main.rs

let markdown = &fs::read_to_string(
	format!("posts/{}", &md.content))?;
let mut html_out = String::new();

let parser = Parser::new_ext(&markdown, options);
html::push_html(&mut html_out, parser);

let mut ctx = Context::new();
ctx.insert("title", &md.title);
ctx.insert("content", &html_out);

tera.render_to(
	"post.html",
	&ctx,
	File::create(
		format!("public/{}.html", slugify(&md.title)))?
)?;

HTML templates

I wrote an HTML template for posts in the Tera template language.

The program combines metadata fields with the converted markdown to render a template like this one:

<!-- post.html -->

<html>
	<head>
		<title>{{ title }}</title>
	</head>
	<body>
		<article>
			{{ content }}
		</article>
	</body>
</html>