MIT licensed
Maintained by Steven Vandevelde
This version can be pinned in stack with:shikensu-0.4.1@sha256:25a8acfc0a53dcd9db2ff5dadacc263cdfc7826e050f402e338c57d430cf27b1,2272

Shīkensu

シーケンス
Sequence

Run a sequence of functions on in-memory representations of files.
Build static websites with ease, without conforming to a specific structure.

Markdown example

import Shikensu
import Shikensu.Contrib (clone, copyPropsToMetadata, permalink, renameExt, renderContent)
import Shikensu.Contrib.IO (read, write)

import Data.ByteString (ByteString)
import Flow
import Prelude hiding (read)
import qualified Data.Text.Encoding as Text (decodeUtf8, encodeUtf8)


main :: IO Dictionary
main =
  -- This IO operation will read the files matching the glob pattern `src/**/*.md`,
  -- transform them (see the `flow` function) and then write them to the `build` directory.
  dictionary_io


dictionary_io :: IO Dictionary
dictionary_io =
    Shikensu.listRelative ["src/**/*.md"] "./"
        >>= read
        >>= flow
        >>= write "./build"


flow :: Dictionary -> IO Dictionary
flow =
       renameExt ".md" ".html"
    .> permalink "index"
    .> clone "index.html" "200.html"
    .> copyPropsToMetadata
    .> renderContent markdownRenderer
    .> return


markdownRenderer :: Definition -> Maybe ByteString
markdownRenderer def =
    content def
        |> fmap Text.decodeUtf8
        |> fmap Markdown.render
        |> fmap Text.encodeUtf8

This lists all the markdown files in the ./src directory
and then does the following in this exact order:

  1. Change the extension of each matched file to .html.
  2. Change the path of each matched file to %matched_path/%file_basename/index.%file_extension.
  3. Make an in-memory copy of the file that has the index.html path.
  4. Copy the information of each definition (aka. file) to its metadata “object” (so we can use that information in our content renderer).
  5. Map the content property of each definition (in this case we are rendering markdown).
  6. {post-flow} Write to the ./build directory.

Why?

Because this allows me to easily define a workflow for building a static website, and more specifically:

  • Have a clear overview of what’s happening.
  • Do a bunch of actions in memory and then write it to disk in one go.
  • Have a list of information about the other files in the project which can then be shared with, for example, templates.

Usage examples

Changes

Changelog

v0.4.1

Update flow dependency.

v0.4.0

Update dependencies, in particular, aeson v2.

Breaking changes: Replaces usage of Data.HashMap.Strict (unordered-containers package) with Data.Aeson.KeyMap (aeson package) for the metadata, the API for both data structures is mostly the same.

v0.3.11

Add CHANGELOG and README to the stack tarball.

v0.3.10

Added missing test files to the stack tarball.

v0.3.9

Adjusted version ranges for test dependencies.

v0.3.8

  • Update dependencies
  • Add Shikensu.Contrib.transformContent as an alias for renderContent
  • Add Shikensu.Contrib.setContent

v0.3.7

  • Windows support

v0.3.6

  • Use Stackage Nightly

v0.3.5

  • Fix package.yaml file (nothing was exported)

v0.3.4

  • Some light refactoring
  • Types are now in an internal module and re-exported in the main Shikensu module

v0.3.3

  • Rename (⚡) and (⚡⚡) to (~>) and (!~>) respectively

v0.3.2

  • Fix code in comment 🤦‍♂️

v0.3.1

  • Adjust base version range to fix cabal compile failures on older versions of GHC (pre 7.10)

v0.3.0

  • Added listRelative and it’s flipped relative
  • Updated dependencies

v0.2.1

  • Fix order of the list function parameters

v0.2.0

  • Split up Utilities to internal and non-internal
  • Add more Utilities (sequence utils, metadata helpers, etc.)
  • Clean up code

v0.1.3

  • Fix Contrib.prefixDirname which didn’t change pathToRoot and parentPath like it should

v0.1.2 - v0.1.1

  • Fix code samples in docs

v0.1.0

  • Initial release 🎉