mksite

A file format-agnostic static site generator

Installation

If you already have Rust and Cargo installed:

sh cargo install mksite

Alternatively, you can install via git:

sh cargo install --git https://github.com/alterae/mksite

Usage

```help mksite

Commands: build Build the site according to mksite.toml clean Delete all build outputs init Initialize a mksite.toml file in the current directory new Scaffold an empty site in a new directory help Print this message or the help of the given subcommand(s)

Options: -q, --quiet Do not print log messages --log-level What level of logging to enable (error, warn, info, debug, or trace) [default: info] -h, --help Print help information -V, --version Print version information ```

mksite is a program for turning a tree of text files into a different tree of text files, usually a website. A typical mksite project has the following structure:

Config

An example mksite.toml file looks like this:

```toml dirs.src = "src" dirs.out = "out" dirs.static = "static" dirs.layout = "layout"

[data] author = { name = "Jane Doe", email = "email@example.com" } copyright = 2022

[transforms] md.html = "pandoc -f markdown -t html" scd.html = ["scdoc", "pandoc -f man -t html"] ```

The first four lines tell mksite the names of the src/, out/, static/, and layout/ directories, respectively. Changing these will change where mksite reads and writes data. For example, dirs.out = "www" would cause mksite to write the build output in a folder called www/.

Note The dirs keys are optional. However, if any of them are present, the rest must also be present.

Next is the data section, which is where you can define arbitrary data that will be passed to the template rendering. In templates, this data will be made available under the data variable. For details on the template syntax, see the Tera documentation.

Finally, we have the transforms section. Transforms are commands or chains of commands that take a stream of bytes on standard input, and return a stream of bytes for standard output. Transforms can be used to trivially implement many features mksite does not natively support, such as markdown rendering and syntax highlighting. The basic syntax of a transform definition is in.out = "command" or in.out = ["command1", "command2", ...] where in is the file extension the transform operates on, out is the file extension the transform produces, and command is a command to pipe the page through. For more details on the finer points of transforms, see below.

Layouts

Layouts are simply Tera templates located in the layout/ directory that accept an additional content variable. Layouts must be valid UTF-8, but aside from that they can be any format.

An example layout file looks like this.

html <!-- layout/_.html --> <!DOCTYPE html> <html> <head></head> <body> <!-- The "| safe" prevents Tera from html-escaping the content. --> {{ content | safe }} </body> </html>

There are two kinds of layouts: default layouts and override layouts:

Override layouts have the same name, extension, and relative path as a specific file in the out/ directory, and only apply to that file. For example, the layout layout/blog/index.html will only apply to the page out/blog/index.html.

Default layouts have the name _.ext, where ext is some file extension. Default layouts apply to all files in the corresponding directory and in nested directories that don't have a default layout. For example:

layout/ _.html blog/ _.html index.html

In this example, layout/blog/_.html will apply to all html files in out/ except index.html, and layout/_.html will apply to every html file in out/ except the contents of the blog directory.

Note Layouts are applied after transforms, based on the file extension of the transform output. As a result, a layout like _.html will apply to all generated html files, regardless of whether these html files were hand-written or generated from markdown or something else via a transform.

If no applicable layouts are found for a file, or if there is no layout/ no layout will be applied.

If an applicable layout exists, but you would like to prevent it from being applied to a file or folder, you can define an "empty" layout like so:

{{ content | safe }}

Transforms

A transform has an input extension, an output extension, and a command or chain of commands.

Each page in src/ with a file extension matching a transform's input extension is piped into the transform as a stream of bytes, and the resulting stream of bytes is written to a file in the out/ directory with the same name and path, and a file extension matching the transform's output extension. Each page can be piped to multiple transforms, and multiple transforms can output the same format. The relationship between inputs and outputs is many-to-many.

Warning It is important to note that the inputs and outputs of transforms are streams of arbitrary bytes, not necessarily valid UTF-8 strings. This is important for interfacing with external non-rust tools, but there are some caveats:

Though this may change in the future, at present all templates and layouts must be valid UTF-8. This means that while transforms can both input and output arbitrary bytes, the original input to a transform (a file in the src/ directory) will be UTF-8. Additionally, layouts for non-UTF-8 files are not supported, and attempting to define a layout for, say, a .pdf file will result in an error.

If a transform has a single command, pages are piped to that command, and the output of the command is written to the output file. For example, these transforms:

toml [transforms] md.html = "pandoc -f markdown" md.pdf = "pandoc -f markdown -t pdf"

Will use pandoc to produce an html file and a pdf document in out/ for every markdown file in src/.

If a transform has a chain of commands, pages are piped to each command in the chain in order, and the ouput of the last command is written to the output file, like with shell pipelines. For example:

toml [transforms] scd.html = ["scdoc", "pandoc -f man"]

Will use scdoc to generate a man page from each .scd file, and immediately pipe that man page to pandoc to convert it to html.

Contributing

Pull requests and issues are welcome, but please ensure you run cargo fmt before submitting a PR.

Example

See the docs/ folder for an example of a website built using mksite.

License

mksite is licensed under the MIT License.