From 7ae181e09835a38d88990f18b8f0ed42835959ee Mon Sep 17 00:00:00 2001
From: Igor Pashev <pashev.igor@gmail.com>
Date: Mon, 7 Oct 2019 16:38:46 +0200
Subject: Initial commit

---
 compiler/cabal.project   |  2 +
 compiler/default.nix     | 96 ++++++++++++++++++++++++++++++++++++++++++++++++
 compiler/site/Main.hs    | 86 +++++++++++++++++++++++++++++++++++++++++++
 compiler/site/Rules.hs   | 54 +++++++++++++++++++++++++++
 compiler/site/site.cabal | 16 ++++++++
 5 files changed, 254 insertions(+)
 create mode 100644 compiler/cabal.project
 create mode 100644 compiler/default.nix
 create mode 100644 compiler/site/Main.hs
 create mode 100644 compiler/site/Rules.hs
 create mode 100644 compiler/site/site.cabal

(limited to 'compiler')

diff --git a/compiler/cabal.project b/compiler/cabal.project
new file mode 100644
index 0000000..37b8053
--- /dev/null
+++ b/compiler/cabal.project
@@ -0,0 +1,2 @@
+packages: ./*/*.cabal
+
diff --git a/compiler/default.nix b/compiler/default.nix
new file mode 100644
index 0000000..b9bd640
--- /dev/null
+++ b/compiler/default.nix
@@ -0,0 +1,96 @@
+{ boot ? import <nixpkgs> {} }:
+
+let
+
+  filtFn = root: path: type:
+    let
+      name = baseNameOf path;
+      hidden = builtins.match "\\..+" name != null;
+      nix = builtins.match ".*\\.nix" name != null;
+      r = !hidden && !nix ;
+    in builtins.trace (path + ": " + (if r then "yes" else "no")) r;
+
+  fltsrc = builtins.filterSource (filtFn (builtins.toPath ./. + "/"));
+
+  nixpkgs = boot.pkgs.fetchFromGitHub {
+    owner = "NixOS";
+    repo = "nixpkgs";
+    rev = "897ec814c9c234f3ed9d60a1a713025d2f9fab2d";
+    sha256 = "0alg5h5zmxdrnfdj94fa4yr5g7j7z3424k78aq44r0a0aqm20iy5";
+  };
+
+  config = {
+    allowUnfree = true; # for local packages
+    allowBroken = true; # some nixpkgs' nonsense
+  };
+
+  inherit (import nixpkgs { inherit config; }) pkgs;
+  inherit (pkgs) lib;
+
+  nixHaskellPackages =
+    let
+      isnix = n: _: null != builtins.match ".*\\.nix" n && n != "default.nix";
+      files = lib.filterAttrs isnix (builtins.readDir ./.);
+    in lib.mapAttrs' (n: _:
+          { name = lib.removeSuffix ".nix" n;
+            value = ./. + "/${n}";
+          }) files;
+
+  localHaskellPackages =
+    let
+      islocal = n: t: !lib.hasPrefix "." n && t == "directory";
+      files = lib.filterAttrs islocal (builtins.readDir ./.);
+    in lib.mapAttrs (n: _: fltsrc (./. + "/${n}")) files;
+
+  haskellPackages =
+    let
+
+      hlib = pkgs.haskell.lib;
+
+      set0 = pkgs.haskell.packages.ghc865;
+
+      set1 = set0.extend (
+        self: super:
+          lib.mapAttrs (_: f: super.callPackage f {}) nixHaskellPackages
+      );
+
+      set2 = set1.extend (
+        self: super:
+          lib.mapAttrs (n: d: super.callCabal2nix n d {}) localHaskellPackages
+      );
+
+      set3 = set2.extend (
+        self: super: {
+          mkDerivation = drv: super.mkDerivation (drv // {
+            buildTools = (drv.buildTools or []);
+
+            # XXX a lot of troubles are cause by tests which require fancy packages of features.
+            # XXX Enable tests for critical packages when unsure.
+            doCheck = false;
+
+            doHaddock = false;
+
+            enableExecutableProfiling = false;
+            enableLibraryProfiling = false;
+          });
+
+          primitive = self.primitive_0_7_0_0;
+          primitive-extras = self.primitive-extras_0_8;
+
+        });
+
+      set = set3.extend (
+        self: super:
+          lib.mapAttrs (n: _:
+              hlib.overrideCabal super.${n} (drv:
+                {
+                  doCheck = true;
+                  configureFlags = (drv.configureFlags or []) ++ [
+                    "--ghc-option=-Werror"
+                  ];
+                })
+            ) localHaskellPackages);
+
+    in set;
+
+in haskellPackages
diff --git a/compiler/site/Main.hs b/compiler/site/Main.hs
new file mode 100644
index 0000000..e7fb92f
--- /dev/null
+++ b/compiler/site/Main.hs
@@ -0,0 +1,86 @@
+module Main
+  ( main
+  ) where
+
+import Control.Applicative ((<**>))
+import System.Exit (exitWith)
+
+import qualified Options.Applicative as O
+import System.FilePath ((</>))
+
+import qualified Hakyll.Commands as Cmd
+import qualified Hakyll.Core.Configuration as Conf
+import qualified Hakyll.Core.Logger as Logger
+
+import Rules (rules)
+
+data Command
+  = Build
+  | Clean
+  | Check Cmd.Check
+
+parseCheck :: O.Parser Cmd.Check
+parseCheck =
+  O.flag
+    Cmd.InternalLinks
+    Cmd.All
+    (O.long "all" <> O.short 'a' <> O.help "Check external links as well")
+
+parseCommand :: O.Parser Command
+parseCommand =
+  O.subparser $
+  O.command "build" (O.info (pure Build) (O.progDesc "Build the site")) <>
+  O.command "clean" (O.info (pure Clean) (O.progDesc "Clean")) <>
+  O.command
+    "check"
+    (O.info ((Check <$> parseCheck) <**> O.helper) (O.progDesc "Check links"))
+
+data Options = Options
+  { verbose :: Bool
+  , outDir :: FilePath
+  , srcDir :: FilePath
+  , cacheDir :: FilePath
+  , command :: Command
+  }
+
+parseOptions :: O.Parser Options
+parseOptions =
+  Options <$>
+  O.switch (O.long "verbose" <> O.short 'v' <> O.help "Run in verbose mode") <*>
+  O.strOption
+    (O.long "output" <> O.short 'o' <> O.metavar "DIR" <> O.showDefault <>
+     O.value (Conf.destinationDirectory Conf.defaultConfiguration) <>
+     O.help "Output directory") <*>
+  O.strOption
+    (O.long "source" <> O.short 's' <> O.metavar "DIR" <> O.showDefault <>
+     O.value ("." </> "src") <>
+     O.help "Source directory") <*>
+  O.strOption
+    (O.long "cache" <> O.short 'c' <> O.metavar "DIR" <> O.showDefault <>
+     O.value (Conf.storeDirectory Conf.defaultConfiguration) <>
+     O.help "Cache directory") <*>
+  parseCommand
+
+main :: IO ()
+main = do
+  opts <-
+    O.execParser
+      (O.info
+         (parseOptions <**> O.helper)
+         (O.fullDesc <> O.header "Static site compiler"))
+  let conf =
+        Conf.defaultConfiguration
+          { Conf.destinationDirectory = outDir opts
+          , Conf.providerDirectory = srcDir opts
+          , Conf.storeDirectory = cacheDir opts
+          , Conf.tmpDirectory = cacheDir opts </> "tmp"
+          }
+  log <-
+    Logger.new
+      (if verbose opts
+         then Logger.Debug
+         else Logger.Message)
+  case command opts of
+    Build -> Cmd.build conf log rules >>= exitWith
+    Clean -> Cmd.clean conf log
+    Check chk -> Cmd.check conf log chk >>= exitWith
diff --git a/compiler/site/Rules.hs b/compiler/site/Rules.hs
new file mode 100644
index 0000000..0cbf772
--- /dev/null
+++ b/compiler/site/Rules.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Rules
+  ( rules
+  ) where
+
+import Hakyll
+
+postCtx :: Context String
+postCtx = dateField "date" "%B %e, %Y" <> defaultContext
+
+rules :: Rules ()
+rules = do
+  match "images/*" $ do
+    route idRoute
+    compile copyFileCompiler
+  match "css/*" $ do
+    route idRoute
+    compile compressCssCompiler
+  match (fromList ["about.rst", "contact.markdown"]) $ do
+    route $ setExtension "html"
+    compile $
+      pandocCompiler >>=
+      loadAndApplyTemplate "templates/default.html" defaultContext >>=
+      relativizeUrls
+  match "posts/*" $ do
+    route $ setExtension "html"
+    compile $
+      pandocCompiler >>= loadAndApplyTemplate "templates/post.html" postCtx >>=
+      loadAndApplyTemplate "templates/default.html" postCtx >>=
+      relativizeUrls
+  create ["archive.html"] $ do
+    route idRoute
+    compile $ do
+      posts <- recentFirst =<< loadAll "posts/*"
+      let archiveCtx =
+            listField "posts" postCtx (return posts) <>
+            constField "title" "Archives" <>
+            defaultContext
+      makeItem "" >>= loadAndApplyTemplate "templates/archive.html" archiveCtx >>=
+        loadAndApplyTemplate "templates/default.html" archiveCtx >>=
+        relativizeUrls
+  match "index.html" $ do
+    route idRoute
+    compile $ do
+      posts <- recentFirst =<< loadAll "posts/*"
+      let indexCtx =
+            listField "posts" postCtx (return posts) <>
+            constField "title" "Home" <>
+            defaultContext
+      getResourceBody >>= applyAsTemplate indexCtx >>=
+        loadAndApplyTemplate "templates/default.html" indexCtx >>=
+        relativizeUrls
+  match "templates/*" $ compile templateBodyCompiler
diff --git a/compiler/site/site.cabal b/compiler/site/site.cabal
new file mode 100644
index 0000000..072e8f2
--- /dev/null
+++ b/compiler/site/site.cabal
@@ -0,0 +1,16 @@
+cabal-version: >=1.10
+name: site
+version: 0.1.0.0
+build-type: Simple
+
+executable site
+    main-is: Main.hs
+    other-modules:
+        Rules
+    default-language: Haskell2010
+    ghc-options: -threaded
+    build-depends:
+        base -any,
+        filepath -any,
+        hakyll >=4.10,
+        optparse-applicative -any
-- 
cgit v1.2.3