aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--LICENSE12
-rw-r--r--README.md61
-rw-r--r--stack.yaml4
-rw-r--r--sticks.cabal10
-rw-r--r--sticks.hs47
6 files changed, 138 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d2a7949
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+_cache
+_site
+.stack-work
+stack.yaml.lock
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ee017c5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,12 @@
+Copyright (C) 2024 JJ <https://toki.la>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5b9cfcf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,61 @@
+# sticks: a dead simple static site generator
+
+`sticks` is a tiny and customizable static site generator.
+
+it leverages [hakyll](https://jaspervdj.be/hakyll/) and [pandoc](https://pandoc.org/) to great extent, and so checks in at just under 50 lines of haskell.
+
+### features
+
+- html templating: directly through pandoc
+- support for markdown, restructured text, asciidoc, org-mode...
+- [todo] renders latex and typst directly to pdfs
+- supports pandoc flavoured markdown, including:
+ - lists with meaningful numeric order
+ - line blocks and nested quotes
+ - code blocks <!-- and syntax highlighting -->
+ - a wide variety of tables
+ - inline latex via mathml
+ - yaml metadata blocks
+
+### usage
+
+```bash
+$ stack build
+$ stack exec sticks -- --help
+Usage: sticks [-v|--verbose] COMMAND
+
+ sticks - Static site compiler created with Hakyll
+
+Available options:
+ -h,--help Show this help text
+ -v,--verbose Run in verbose mode
+
+Available commands:
+ build Generate the site
+ check Validate the site output
+ clean Clean up and remove cache
+ rebuild Clean and build again
+ server Start a preview server
+ watch Autocompile on changes and start a preview server.
+```
+
+### about
+
+pandoc (and by extension hakyll and sticks) operates on:
+- **files** containing *metadata* and *content*, and
+- **templates** containing *variables* and *expressions*.
+
+files may be prefixed with a YAML metadata block ("front matter") declaring variables (ex. title, subtitle, author...) for use by *templates*. a special `template` variable denotes the template to be used. without a `template` entry in the metadata block, they will be assumed to be free-standing documents (disregarding YAML front matter).
+
+templates are simply an html, or pdf, or etc file containing the content needed (ex. header and footer material) for a free-standing document. they must contain the special `$body$` variable somewhere for file injection. they may refer to variables declared by files with `$variable$`. basic control flow is also supported and is documented in [the pandoc manual](https://pandoc.org/MANUAL.html#template-syntax) (note only the `$foo$` syntax is supported, not `${foo}`).
+
+sticks expects all templates to be placed in the `_templates` folder and will throw an error for any templates referenced by front matter that do not exist there. templates may include each other with the `$partial("_template/template.html")$` syntax.
+
+the aforementioned YAML metadata blocks may be placed before files of any type. they look like the following:
+```yaml
+---
+template: default
+title: a really cool document
+subtitle: https://www.youtube.com/watch?v=dQw4w9WgXcQ
+---
+```
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
index 0000000..36d8e5b
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,4 @@
+resolver: lts-22.30
+system-ghc: true
+packages:
+- .
diff --git a/sticks.cabal b/sticks.cabal
new file mode 100644
index 0000000..e5612f0
--- /dev/null
+++ b/sticks.cabal
@@ -0,0 +1,10 @@
+name: sticks
+version: 0.1
+build-type: Simple
+cabal-version: >= 1.10
+
+executable sticks
+ main-is: sticks.hs
+ build-depends: base == 4.*, hakyll == 4.16.*, pandoc == 3.*
+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
+ default-language: Haskell2010
diff --git a/sticks.hs b/sticks.hs
new file mode 100644
index 0000000..36607d8
--- /dev/null
+++ b/sticks.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import Hakyll
+
+-- Applies the template specified in a post's metadata, if it exists
+applyMetadataTemplate :: Context String -> Item String -> Compiler (Item String)
+applyMetadataTemplate context item = do
+ field <- getMetadataField (itemIdentifier item) "template"
+ case field of
+ Just path ->
+ let templatePath = "_templates/" ++ path ++ ".html" in
+ loadAndApplyTemplate (fromFilePath templatePath) context item
+ _ -> return item
+
+main :: IO ()
+main = hakyll $ do
+ -- Compile templates for future use
+ match "_templates/*" $ compile templateBodyCompiler
+
+ -- Detect whether HTML files are standalone or in need of a template
+ match ("**.html" .||. "**.htm") $ do
+ route idRoute
+ compile $ do
+ identifier <- getUnderlying
+ field <- getMetadataField identifier "layout"
+ case field of
+ Just _ -> pandocCompiler
+ Nothing -> getResourceBody
+ >>= applyMetadataTemplate defaultContext
+ >>= relativizeUrls
+
+ -- Match all other renderable files and apply their template, if it exists
+ match ("**.md" .||. "**.rst" .||. "**.org" .||. "**.adoc") $ do
+ route $ setExtension "html"
+ compile $ pandocCompiler
+ >>= applyMetadataTemplate defaultContext
+ >>= relativizeUrls
+
+ -- Additionally copy non-HTML files verbatium
+ match ("**.md" .||. "**.rst" .||. "**.org" .||. "**.adoc") $ version "raw" $ do
+ route idRoute
+ compile pandocCompiler
+
+ -- Copy all additional files verbatium
+ match "**" $ do
+ route idRoute
+ compile copyFileCompiler