packages feed

hakyllbars-1.0.0.0: site/Main.hs

module Main where

import Data.List (isSuffixOf)
import Data.Maybe (fromMaybe)
import Data.String.Utils (join, split)
import Data.Time
import Hakyll
import Hakyllbars as HB
import System.Environment (lookupEnv)
import Text.Pandoc.Highlighting (haddock, styleToCss)

main :: IO ()
main = do
  deployEnv <- fromMaybe Prod . ((=<<) deployEnvFromStr) <$> lookupEnv "DEPLOY_ENV"
  time <- utcToZonedTime <$> getCurrentTimeZone <*> getCurrentTime
  let dateConfig = HB.defaultDateConfigWith defaultTimeLocale time
  hakyllWith config do
    css' <- css
    js' <- js
    templates' <- templates
    rulesExtraDependencies [css', js', templates'] do
      pages deployEnv dateConfig

config :: Configuration
config =
  defaultConfiguration
    { providerDirectory = "site",
      destinationDirectory = "_site"
    }

css :: Rules Dependency
css = do
  match "css/**" do
    route idRoute
    compile getResourceBody
  create ["css/code-style.css"] do
    route idRoute
    compile $ makeItem (styleToCss haddock)
  makePatternDependency "css/**"

js :: Rules Dependency
js = do
  match "js/**" do
    route idRoute
    compile getResourceBody
  makePatternDependency "js/**"

-- Precompile all templates
templates :: Rules Dependency
templates = do
  match templatePattern do
    -- Use this to compile templates
    compile $
      -- Get the content of the template
      getResourceBody
        -- Compile the template
        >>= HB.compileTemplateItem
        -- Create an item from the template
        >>= makeItem
  makePatternDependency templatePattern
  where
    templatePattern =
      "_layouts/**"
        .||. "_partials/**"
        .||. "_templates/**"
        .||. "_sections/**"

pages :: DeployEnv -> HB.DateConfig -> Rules ()
pages deployEnv dateConfig = do
  match "*.md" do
    route $ setExtension "html" `composeRoutes` indexRoute
    -- This is where Hakyllbars is applied
    compile do
      getResourceBody >>= HB.applyTemplates do
        -- Sets the root context used in the templates
        HB.applyContext (context deployEnv dateConfig)
        -- Applies the item content as a template
        HB.applyContent
        -- Applies the final template
        HB.applyTemplate "_layouts/from-context.html"

indexRoute :: Routes
indexRoute = customRoute appendIndexHtml
  where
    appendIndexHtml = join "/" . reverse . indexIt . reverse . split "/" . toFilePath
    indexIt [] = []
    indexIt a@(x : xs)
      | x == "index.html" = a
      | ".html" `isSuffixOf` x = (head (split "." x) ++ "/index.html") : xs
      | otherwise = a

-- This uses Hakyllbars' Context, not Hakyll's
context :: DeployEnv -> HB.DateConfig -> HB.Context String
context deployEnv dateConfig =
  HB.gitFields "site" "https://github.com/keywordsalad/hakyllbars/tree"
    <> HB.includeField "section" (Just "_sections") (Just ".md")
    <> HB.includeField "partial" (Just "_partials") (Just ".md")
    <> HB.dateFields dateConfig
    -- Using the default fields is very recommended
    <> HB.defaultFields host siteRoot
  where
    host = deployEnvHost deployEnv
    siteRoot = deployEnvSiteRoot deployEnv

data DeployEnv = Prod | Dev

deployEnvFromStr :: String -> Maybe DeployEnv
deployEnvFromStr = \case
  "prod" -> Just Prod
  "dev" -> Just Dev
  _ -> Nothing

deployEnvHost :: DeployEnv -> String
deployEnvHost = \case
  Prod -> "https://keywordsalad.github.io"
  Dev -> "http://localhost:8000"

deployEnvSiteRoot :: DeployEnv -> String
deployEnvSiteRoot = \case
  Prod -> "/hakyllbars"
  Dev -> ""