diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | LICENSE | 12 | ||||
-rw-r--r-- | README.md | 61 | ||||
-rw-r--r-- | stack.yaml | 4 | ||||
-rw-r--r-- | sticks.cabal | 10 | ||||
-rw-r--r-- | sticks.hs | 47 |
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 @@ -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 |