flog - MultiMarkdown-based static site/blog generator
flog [-avbOBP] [-d level] [-C css] [-A author] [-S count] [-T fmt] [-D dir] [-U url] [-p count] [-I count] [-N blogname]
Flog is a static blog generator based on MultiMarkdown.
You write the outer bits of your blog and each post in MultiMarkdown.
Flog will generate the bits of MultiMarkdown that summarize the pages and posts in the blog and the archives of previous posts.
The generated bits are meant to be pulled in to e.g.
index.md
via MultiMarkdown file inclusion.
You can look at https://haqistan.net for an example of what a Flog-generated site looks like.
Flog generates MultimarkDown,
not HTML.
It produces files meant to be included in other multimarkdown files via the file inclusion syntax: {{file}}
.
The site author has the flexibility to decide where these bits of generated content go and how the whole site is structured.
Flog takes care of generating the archives,
which contains indices into the content by date,
title and tag.
Flog also spits out the multimarkdown
invocations that should be executed to create the static HTML site.
It prints them,
one per line,
on stdout.
This is the usual incantation to completely regenerate your site:
$ flog | sh
By default the resulting tree will be placed in a subdirectory of the current directory called tmp
. You can then tar up ./tmp
to the web server docroot, or use the -D
option to specify another output directory (lke your docroot).
Flog accepts the following options:
./index.md
and look for all other pages in pages/
.lvl
. The default, zero, drops all drafts. Most reasonable drafts are at level 1. Deeper drafts are generally... draftier../tmp
.flogger.css
flogger
which is probably not right...openbsd: https://www.openbsd.org markdown: https://markdownguide.org ...
It is then possible to refer to these links by name in posts using the (link:name) shortcut, in the same way you can easily link to a Twitter or Mastodon handle using a shorthand.
Flog generates a directory tree populated with MultiMarkdown files; we call this directory the docroot in what follows. The docroot is based on a set of input files, also multimarkdown, which it finds by various means. The directory structure and naming covention used in the docroot is completely different than that of the input files.
The input files represent one of three kinds of things:
All three of these different kinds of entities are realized in MultiMarkdown. Flog distinguishes among them based on where they are in the input file tree, but it expects the same kinds of metadata in all of them.
By convention, flog expects to be run from the root of your site's source tree, preferably via make(1) using a simple `Makefile` such as that used to generate haqistan.net. Flog expect to find all blog posts under posts/
, static pages under pages/
, books under books/
and papers under papers/
.
Every post, page, chapter in a book or section of a paper should have certain basic metadata at the top, separated by a blank line from the content of the posts. There should not be any kind of title or head matter other than the metadata; Flog generates a title and summary for each file on its way to the docroot.
The template I use to start something new looks like this:
Title: The Title name: some-stuff Date: 2016-08-05 Edit: 2016-08-05 Tags: blah draft: 1 No title here.
Metadata names are always compared in lowercase in flog, but are usually capitalized by convention in multimarkdown.
The draft
metadata should be set (to anything) if the file in question is a draft; this means it is ignored under normal circumstances. Drafts can made visible in the docroot with the -d
option.
Tags
is optional, but if present should be a comma-separated list of tags that apply to the file (whitespace is ignored).
The name
metadata is used to form the final filename of the generated multimarkdown file in the docroot. The name of the input file in the filesystem is used as a default if no name
key is given.
The title
metadata is used in title of the final HTML file. Multimarkdown does this on its own when it generates HTML.
There are two dates that flog cares about: date
and edit
. The former is the date used to sort blog posts in time (descending). Filesystem metadata such as the mtime of the source file is ignored, only the date
metadata matters, so it must be present. The edit
date is displayed in summaries. The Time::ParseDate module is used to parse the values, so anything that module accepts can appear as a value (although not all forms make sense in this context, but hey).
There are two other keys that don't appear in the template that have meaning to flog: featured
and order
. Both take integer values. They will be covered below, as they only apply to certain kinds of inputs.
Blog posts are ordered backwards by time of publication (the date
metadata). They are found by default in the posts
subdirectory of wherever flog is run. Flog searches for all *.md
files under posts
recursively, so it doesn't matter where they are. This allows the site author to organize their posts using the filesystem in whatever way makes sense to them.
In the docroot blog posts are stored under directories based on the date of the post. Consider this hypothetical post, under posts/tech/why-i-do-this.md
:
Title: Why Do I Do this? name: why-do-i-do-this Date: 2017-06-08 ...
The URI for this post would end up being /2017/06/08/why-do-i-do-this.html
, even though the input file has a different name.
name
Metadata and Internal Link TypesIn addition to providing the base name for the markdown file generated in the docroot, this metadasta has other uses.
First, it is also used as the name of the by-name
index directory in the docroot, which contains a link to every post by name, assuming the names are actually unique.
Second, it can be used to refer directly to another post via the page
internal link type. The "Link Types" section, below, summarizes all of the special link types available.
[a post](post:name)
a link to the post named name
in /by-name/
[a page](page:about)
a link to the About page[text](wiki:name)
synonym for page:...
[something](tag:boring)
a link to the archive section posts tagged borking
|[wow](wiki(pedia|quote|media|source):foo)
link to the appropriate WikiCommons resource[doc](man:foo)
link to the OpenBSD man page on foo[watch](youtube:vid)
link to the given YouTube video[useless](github:haqistan)
link to a github repository[fuck elon must](@haqistan)
link to a twitter profile[twoot](@haqistan@foo)
link to a mastodon profileStatic pages can be considered a very simple wiki. Any MultiMarkdown files in the pages
subdirectory are processed and added to the overall list of pages, which is turned into pages.md
in the docroot. This is effectively a navbar for your pages, suitable for inclusion in boilerplate. We pull pages.md
into every page in the final docroot, in the header. The order
metadata in pages is used to sort them, it should be an integer and there is no default, so it will cause warnings if you omit it.
Books and papers both share a hierarchical structure and are therefore treated more or less the same by Flog. The only differences are cosmetic: books are comprised of named chapters where as papers have numbered sections. The order of chapters and sections is determined by the Order
metadata, which should be an integer. The chapters and sections of books and papers are sorted by their Order
metadata in the docroot.
As with pages, the order of chapters and sections is determined by the Order
metadata, which should be an integer.
In the final docroot each book or paper will display the hierarchical structure of the files in the input.
0.1.24 19 Jul 2024 attila fix og:... meta.md fu 0.1.23 19 Mar 2024 attila add -L links.txt, link:... 0.1.22 07 Feb 2024 attila add -a (no_archives) 0.1.21 12 Dec 2023 attila merge changes from other laptop 0.1.20 24 Jul 2023 attila fix -Y, parselapsed, clean up 0.1.19 04 Feb 2023 attila add RSS, draftiness levels 0.1.18 23 Jan 2023 attila add content warning functionality 0.1.17 16 Nov 2022 attila add -y option 0.1.16 21 Feb 2022 attila add post: links and /by-name/ OOify and refactor a little 0.1.15 04 Sep 2017 attila fix generator.md link 0.1.14 03 Sep 2017 attila clerical error 0.1.13 03 Sep 2017 attila -b => -O, new -b = $bare_pages, fix -C and -N, add hidden pages 0.1.12 04 Jul 2017 attila dump_tags 0.1.11 13 Jun 2017 attila $ignored_meta_re, page summs, more POD 0.1.10 11 Jun 2017 attila funkylinks, flog POD improvements 0.1.9 27 May 2017 attila strip text for summaries, fix titles 0.1.8 24 May 2017 attila Modern::Perl, $no_{books,papers} 0.1.7 16 Dec 2016 attila make pages obey draft attr 0.1.6 26 Sep 2016 attila add draft feature via metadata 0.1.5 10 Aug 2016 attila bug: featured ^ recent 0.1.4 06 Aug 2016 attila Featured posts, timestamp 0.1.3 04 Aug 2016 attila Refactored for books + papers 0.1.2 03 Aug 2016 attila Books 0.1.1 01 Aug 2016 attila First working version 0.1.0 12 Jul 2016 attila Started