2022-02-11 Haskell

Hakyll Draft Posts

There are multiple approaches,At least this and that.

to dealing with draft posts in Hakyll, which is something I wanted to do.

Being a simple kind of man, I did something else.

Drafty articles go in posts/drafts, but are otherwise as normal. When they’re ready, they can just be moved up to posts/. Makefile targets support either just including them for local review or, possibly, publishing them unreferenced for someone else’s review, given the URL (of the form .../posts/drafts/...).

The choice is made through the environment, so we need that first:

import System.Environment             (getEnvironment)
...
main = do
    env <- getEnvironment

If HAKYLL_DRAFT=all, we want to build the site as if any drafts weren’t, and if HAKYLL_DRAFT=onlyposts, build it without including drafts in the generation of tags or the archive list. There are two functions, to be called in appropriate places (which perhaps could be done more neatly):

-- Maybe also format posts in draft/, depending on environment setting:
-- "all" to generate corresponding tags and archive entries, "onlyposts"
-- to omit those.
-- If posts, we're only routing posts, otherwise doing tags or the archive.
pubPosts :: Bool -> [(String, String)] -> Pattern
pubPosts posts env =
  case lookup "HAKYLL_DRAFT" env of
    Just "all" -> allposts
    Just "onlyposts" -> if posts then allposts else "posts/*"
    _ -> "posts/*"
  where allposts = "posts/*" .||. "posts/draft/*"

Then, for instance, tags are built like

tags <- buildTags (pubPosts False env) (fromCapture "tags/*.html")

and posts are processed like

match (pubPosts True env) $ do
            route $ setExtension "html"
            ...

with make rules like

draft: site
	HAKYLL_DRAFT=all site rebuild

That seems to do the job.