Skip to content

200ok-ch/ukko

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

https://github.com/200ok-ch/ukko/actions/workflows/clojure.yml/badge.svg

ukko

ukko is a powerful static site generator written in Clojure.

ukko is published under AGPL-3.0 License.

Installation

You have two options to install ukko.

Locally

This is reasonable if you want to develop on ukko itself.

Prerequisites:

  • Clojure
  • Leiningen
  • rsync
  • pandoc (soon to be optional)
  • linkchecker (optional)
  • sassc (optional)
  • geckodriver (optional), or chromedriver or safari
  1. Clone this repository.
  2. Run lein bin.

Using Docker

Premise: You have Docker installed.

Copy/paste this into your shell and you will have a ~/bin/ukko file.

cat >> ~/bin/ukko <<EOF
#!/bin/sh
docker run -it --rm -v \`pwd\`:/project twohundredok/ukko /bin/bash -c "/bin/ukko \$@"
EOF

chmod +x ~/bin/ukko

Usage

Much like any other static site generator ukko collects information from input files and generates and writes output files.

🧐 For brevity the documentation follows some general typographic rules:

  1. Keys (aka. properties) will be written in italics
  2. Values will be written in code blocks (monospaced font)
  3. Explanations will generally use the default values (in code blocks) with the corresponding key in parenthesis and italics

Here is an example:

Output files are written to public (target-path).

😎 This means the path files are written to, here public, can be changed by setting the option target-path in ukko.yml.

ukko collects information from 5 locations:

  • ukko.yml
  • assets (assets-path)
  • site (site-path)
  • layouts (layouts-path)
  • data (data-path)

Input ukko.yml

If present ukko reads the file ukko.yml, which can be used to overwrite any global settings and defaults.

Global settings

  • assets-path, default: assets
  • site-path, default: site
  • layouts-path, default: layouts
  • data-path, default: data
  • target-path, default: public
  • ignore-file-patterns, default: ["^\\."]
    • Changes to a file matching one of these patterns will not trigger a rebuild.
    • The default pattern ignores temporary files written by Emacs.
  • linkcheck-params, default: nil
    • Additional parameters that will be applied to linkcheck when running ukko -l.

Default settings

  • target-extension, default: .html
  • format, default: passthrough
  • layout, default: [post, blog]
  • priority, default: 50

Additional settings

As the data provided by ukko.yml is easily accessible from any template it may very well be used to provide any additional metadata like:

  • site-url
  • site-title

Input assets

All files in assets (assets-path) are treated as ready-to-publish and will be synced (via rsync) to public (target-path) without any further processing.

Input site

Files in site (site-path), in ukko called “artifacts”, are expected to need processing before being published. Furthermore any file in site (site-path) is expected to provide a YAML front matter.

🤓 The concept of a YAML front matter was popularized by the static site generator jekyll, although webby by Tim Pease had it as early as 2008. Credit where credit is due!

The YAML front matter is used to provide instructions on how to process the artifact for publishing, as well as any additional metadata. The front matter is closed with a YAML document separator --- (a line with only three dashes). The remainder of the file, after the front matter, is called template.

🧐 It is not necessarily a template, it can also be just content. In ukko it is still called template.

The naming and location of the files in site (site-path) generally will be used to determine the naming and location in public (target-path). But as you’ll see later there are exceptions to that rule. Solely the file extension is irrelevant, as it will be replaced with .html (target-extension).

As the default format is passthrough (format) any file that does not specify format in its front matter explicitly will just have its template copied into its target location (target-path). It still needs to have a front matter, though. Files in site that do not have a valid front matter (invalid or none) will be ignored during processing.

🤓 It is allowed to place files without front matter in site (site-path). For example files containing org fragments to be included in other org files. In that case it is considered a feature that these files due to the absence of a front matter will be ignored.

Within ukko an artifact is represented as a Clojure map of its front matter with the following additional keys

  • path (the path to the source file)
  • template (the content of the source file without the front matter)
  • mtime (the date of last modification of the file as iso date string)

Here are some properties that control how artifacts are processed:

format

Formats transform the template. Available formats are:

  • passthrough
  • md (Markdown, via flexmark)
  • org (org-mode, via Emacs)
  • fleet (templating, via fleet)
  • scss (via sassc)
  • All 40+ formats supported by Pandoc

Formats can be chained. By providing a list of formats the template can be passed through mulitple formats. This could for example be used to generate Markdown from a Fleet template, which is then converted to HTML.

🤓 Transforms are implemented with Clojure’s multimethods and thus are easily extendable. Pull requests are very welcome!

layout

Layout specifies templates from layouts (layouts-path) that will be used the wrap the resulting html fragment. More about that in the section about layouts.

scope

When using a templating format, like fleet, the template receives a context “ctx” in which it is evaluated. Without setting scope the context is the global context with the current artifact merged.

🤓 This means that any property set in ukko.yml will act as a default and any default can be overwritten by the artifact’s front matter.

priority

Sometimes an artifact’s template depends on other artifacts. In this case the order of processing is crucial. Artifacts are processed in order of priority, and in case of equal priority alphabetically. By overwriting the default priority of 50 with a higher value it can be ensured that the given artifact is processed later.

collection

Collection is a powerful property that allows to render one template into multiple output files. Collection is used to provide a list (or vector, or map) of which each item results in its own output file. There are several ways in which the value of collection will be interpreted, based on the type of value provided:

  • a vector (aka. YAML list)
  • a string (any YAML string)
  • a map (aka. YAML object)

A vector needs to be a list of Clojure keywords and will be used to navigate the context as with Clojure’s get-in. It is mainly used to drill down into the context, so this doesn’t need to happen in the template itself. The items of the structure retrieved with the navigator will be the new context passed to the template.

A string is the most versatile way to define a collection, as the string will be evaluated as Clojure code. The return value will be the new context passed to the template.

A map will yield a cross-product of the values of the map interpreted as navigators. The items if the collections will be available in the cross-product items under the keys of the map. The cross-product items will be the new context passed to the template. This means that during processing any artifact that defines a collection will in fact be replaced by multiple artifacts, one for each item in the collection. The target-path of the new artifact is relative to original artifact (it shares its path), but will be derived from the id of the item.

😎 This will be your new SEO-Power-Tool.

Input layouts

Layouts are handled much like artifacts in site (site-path), but – as they are used to wrap html fragments generated by artifacts – need to provide an actual template using a templating format, like fleet. (As opposed to artifacts, layouts can currently only be transformed by one format.)

Layouts can be chained, much like formats. This means artifacts can specify a list of layouts where the former will be wrapped by the later. In other words layouts will be applied in the order they are listed.

🤓 In fact by default layout is defined as [post, blog], assuming that the majority of files in a typical setup will be blog posts, so that when writing a blog post you can omit layout and go with the default.

Input data

ukko uses fsdb to collect information from data (data-path) and thus supports the most common formats for structured data. It provides what it finds as structured data via data in the root context to any template.

😎 This in combination with scope or collection makes it really powerful. Just imagine the possibilities.

Options

ukko without any argument will generate the site, write it to public (target-path) and quit. Additional features can be turned on by passing arguments:

-c, --continuous       Regenerate site on file change
-l, --linkcheck        After generating the site check links
-p, --port PORT        Port for http server, default: 8080
-f, --filter FILTER    Generate only files matching the regex FILTER
-q, --quiet            Suppress output (not yet implemented)
-s, --server           Run a http server
-b, --browser BROWSER  Start a browser with live-reload (either firefox, chrome, or safari)
-v, --verbose          Verbose output (not yet implemented)

Browser

By default, your browser will start with an empty profile. Optionally, if you want to start your browser with a specific profile (for example for HiDPI settings or to include addons), you can set the profile in an environment variable:

FIREFOX_PROFILE=~/.mozilla/firefox/xmcjb934.geckodriver ukko -c -s -b firefox

Create and find a profile in Firefox

  • Run Firefox with -P, -p or -ProfileManager key as the official page describes.
  • Create a new profile and run the browser.
  • Setup the profile as you need.
  • Open about:support page. Near the Profile Folder caption, press the Show in Finder button. A new folder window should appear. Copy its path from there.

Create and find a profile in Chrome

  • In the right top corner of the main window, click on a user button.
  • In the dropdown, select “Manage People”.
  • Click “Add person”, submit a name and press “Save”.
  • The new browser window should appear. Now, setup the new profile as you want.
  • Open chrome://version/ page. Copy the file path that is beneath the Profile Path caption.

Showcases

Our very own https://200ok.ch is, of course, generated via ukko.

Examples

😭 An example project would be nice, but sadly there is none atm.

Here is an initial directory structure to run ukko against.

.
├── assets
├── data
├── layouts
├── public (will be created by ukko)
├── site
└── ukko.yml (optional)

About

The axe of perun - a static site generator.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published