1
0
mirror of https://git.sr.ht/~adnano/kiln synced 2024-11-08 10:09:18 +01:00
kiln/docs/kiln.1.scd
2022-10-31 13:01:19 -04:00

938 lines
23 KiB
Markdown

kiln(1)
# NAME
kiln - a simple static site generator
# SYNOPSIS
*kiln* build [-c _config_]
*kiln* new _path_
# DESCRIPTION
*kiln build* builds a kiln site.
*kiln new* creates a new kiln site at the given path.
# OPTIONS
## kiln build
*-c* _config_
Specifies the configuration file to use. Defaults to "config.toml".
# OVERVIEW
A kiln site is built in one or more steps called *tasks*. Tasks read content
from the content directory, process the content, and write the content to the
output directory. Tasks can also be configured to copy static content to the
output directory.
The following directories are common to all tasks:
[[ *Directory*
:[ *Description*
| content/
: Content directory
| templates/
: Templates directory
The basic unit of a kiln site is the *page*. Each page either represents a
content file or a subdirectory containing other pages. Pages may be
preprocessed, run through templates, and postprocessed (in that order). Each
operation takes the output of the last operation as input.
# CONTENT DIRECTORY
The content directory contains site content files which can be nested in
subdirectories. Any file or directory in the content directory whose name begins
with "\_" will be ignored, with the exception of files with the name "\_index"
(e.g. "\_index.gmi").
Content files can specify dates in their filenames. For example, the file
content/2020-11-20-Hello-world.gmi will result in a page with a path of
/Hello-world/ and a date of November 20, 2020.
Files with the name "\_index" are treated specially. They can be used to provide
frontmatter and content for the parent directory which will otherwise have none.
If an "\_index" file is present in a directory, an index page (e.g. "index.gmi")
for that directory will be generated and written to the output directory.
## FRONTMATTER
Pages can specify additional metadata in frontmatter. Frontmatter is delimited
by "---" and is specified in YAML. Newlines after the closing delimiter are
removed from the content.
Example:
```
---
title: Page title
date: 2021-04-24
params:
key: value
---
Page content
```
The following keys are supported:
*title*
The title of the page.
Example:
```
---
title: My first post
---
```
*date*
The date of the page. Pages are sorted by date in reverse order, so newer
pages will be placed above older pages.
Example:
```
---
date: 2021-05-21
---
```
*weight*
The weight of the page. Pages are sorted by weight in increasing order, so
pages with a smaller weight will be placed above pages with a larger weight.
Example:
```
---
weight: 1
---
```
*outputs*
Optionally specifies a list of tasks that can build this page. Defaults to
all tasks.
Example:
```
---
outputs: ["Gemini", "HTTPS"]
---
---
outputs: [] # Excluded from all tasks
---
```
*template*
Optionally specifies the name of the template to use when building this
page. If unspecified, defaults to "page" for regular pages and "index" for
index pages. The template is then found according to *TEMPLATE RESOLUTION*.
Example:
```
---
title: About me
template: about
---
```
*params*
Specifies extra parameters to be provided to templates.
Example:
```
---
params:
key: value
---
```
## SORTING
Pages are sorted automatically. Pages are first ordered by weight in increasing
order, then by date from newest to oldest, and then by filename in alphabetical
order.
# TEMPLATES DIRECTORY
The templates directory contains templates for use when building the site.
Templates use the Go templating language. The following templates are supported:
[[ *Template*
:[ *Description*
| page.ext
: Page template
| index.ext
: Directory index template
| base.ext
: Base template from which the page and index templates inherit
| atom.xml
: Atom feed template
The extension of page and index templates is configurable and will replace
".ext" above. See *CONFIGURATION*.
For more information on the Go templating language, see
https://golang.org/pkg/text/template/.
## PAGE AND INDEX TEMPLATES
The content for page and index templates can be accessed using the *.Content*
page variable. For example:
```
page header
{{ .Content }}
page footer
```
Other page variables are documented in *PAGE VARIABLES*.
In HTML templates, page content is escaped by default. If the content is known
to be safe, it must be marked as safe to avoid escaping. For example:
```
<body>
{{ .Content | safeHTML }}
</body>
```
See *TEMPLATE FUNCTIONS* for more information.
## BASE TEMPLATES
Base templates are inherited only by page and index templates. Base templates
generally define at least one block which can optionally be customized by page
and index templates, according to the Go templating language.
For example, the base template could contain:
```
{{ block "body" . }}
Blocks can have default content
{{ end }}
{{ block "extra_content" . }}{{ end }}
```
The page and index templates can then optionally customize these blocks, for
example:
```
{{ define "body" }}
Body goes here
{{ end }}
```
## TEMPLATE RESOLUTION
The scope of a template is limited by the directory it is placed in. For
example, a page template in the templates/blog/ directory will only apply to
files in content/blog/. A page template placed in templates/ will only apply to
files in content/ and not its subdirectories.
Fallback templates can be specified in the templates/\_default/ directory. These
templates will apply only when the required kind of template is not found in the
template directory.
The template for a specific page can be overridden by setting the *template* key
in the page's frontmatter. See *FRONTMATTER* for more details.
For example, the page file content/blog/my_first_post.gmi will be rendered with
the template templates/blog/page.ext. If that template is not found, it falls
back to templates/\_default/page.ext. If that template is also not found, then
no template will be used.
Base templates also follow the same rules. For example, the index template
templates/blog/index.ext inherits firstly from templates/blog/base.ext, and
then falls back to templates/\_default/base.ext if present.
There is no override mechanism for base templates.
## PARTIAL TEMPLATES
Partial templates can be placed in the templates/\_partials directory.
Partial templates can be executed from any other template using the *partial*
function. For example, a template could contain:
```
{{ partial "navbar.ext" . }}
```
Then templates/\_partials/navbar.ext is executed. Since argument . is
provided, all data from the current context is provided. See *TEMPLATE
FUNCTIONS* for more information.
In HTML templates, the partial template content is escaped by default. If the
content is known to be safe, it must be marked as safe to avoid escaping. For
example:
```
<body>
{{ partial "navbar.ext" . | safeHTML }}
</body>
```
See *TEMPLATE FUNCTIONS* for more information.
# CONFIGURATION
By default, kiln looks for a configuration file named "config.toml". An
alternative configuration file can be specified with the *-c* flag. See
*OPTIONS*.
The configuration file uses the _TOML_ format.
The following keys are supported:
[[ *Key*
:[ *Description*
| title
: Site title
| params
: Extra parameters made available to templates
## TASKS
Tasks can be specified in the [[tasks]] array of tables.
The following configuration options are supported per task:
*name*
An optional name for the task.
Example:
```
[[tasks]]
name = "Gemini"
[[tasks]]
name = "HTML export"
```
*input*
A list of input file extensions. Files in the content directory with a
matching extension will be processed.
Example:
```
[[tasks]]
input = [".gmi", ".md"]
```
*output*
The output file extension. Files written to the output directory will use
this extension.
Example:
```
[[tasks]]
output = ".html"
```
*template*
The template file extension. Templates with this file extension will be used
to format the content. If unset, no templates will be used.
Example:
```
[[tasks]]
template = ".gmi"
```
*preprocess*
Maps file extensions to preprocess commands. Preprocess commands will run
before templating. The commands will be provided the content of the page as
standard input and should write the processed content to standard output.
Example:
```
[[tasks]]
input = [".gmi", ".md"]
output = ".html"
preprocess.gmi = "gmnitohtml"
preprocess.md = "mdtohtml"
```
*postprocess*
Specifies a command which will run after templating and before content is
written to the output directory. It will be provided the content of the page
as standard input and should write the processed content to standard output.
Example:
```
[[tasks]]
input = [".gmi"]
output = ".html"
template = ".gmi"
postprocess = "gmnitohtml"
```
*static_dir*
Specifies a directory from which to read static content. All files in this
directory will be copied to the output directory without modificiation.
Static assets like images should be stored in this directory. If unset, no
static content directory will be used.
Example:
```
[[tasks]]
static_dir = "static"
```
*output_dir*
Specifies the directory to which output files will be written.
Example:
```
[[tasks]]
output_dir = "public"
```
*url*
The base URL to use for page URLs. The base URL should not have trailing
forward slashes.
*ugly_urls*
Specifies whether page paths will contain file extensions. By default,
clean paths without any extension are used.
Example:
```
[[tasks]]
ugly_urls = true
```
The following configuration builds a simple Gemini site.
```
[[tasks]]
input = [".gmi"]
output = ".gmi"
template = ".gmi"
output_dir = "public"
```
The following configuration generates a Gemini text site and also exports an
HTML version of the site. This configuration makes use of the *gmnitohtml*(1)
command to convert Gemini text to HTML.
```
# Build the site
[[tasks]]
input = [".gmi"]
output = ".gmi"
template = ".gmi"
static_dir = "static"
output_dir = "public"
# Export an HTML version of the site
[[tasks]]
input = [".gmi"]
output = ".html"
template = ".gmi"
postprocess = "gmnitohtml"
static_dir = "static"
output_dir = "public_html"
```
The following configuration generates an HTML site from Markdown and Gemini text
files in the content directory and HTML templates in the templates directory.
This configuration makes use of the *mdtohtml*(1) command to convert Markdown to
HTML, and the *gmnitohtml*(1) command to convert Gemini text to HTML.
```
[[tasks]]
input = [".md", ".gmi"]
output = ".html"
template = ".html"
preprocess.md = "mdtohtml"
preprocess.gmi = "gmnitohtml"
static_dir = "static"
output_dir = "public"
```
## PERMALINKS
Permalinks can be used to rewrite page paths. Permalinks are specified in the
\[tasks.permalinks] table of the configuration file. Keys denote a path to a
directory, and values use the Go templating language to rewrite the final path
of pages in that directory. The templates have the same data that page templates
have available to them (see *PAGE VARIABLES*).
The following configuration will rewrite the paths of pages in the content/blog
directory to /YYYY/MM/DD/slug. For example, the file
content/blog/2021-05-12-hello-world.gmi will have a path of
/2021/05/12/hello-world/.
```
[[tasks]]
# ...
[tasks.permalinks]
"/blog/" = "/{{ .Date.Format `2006/01/02` }}/{{ path.Base .Path }}"
```
For more information on templates, see *TEMPLATES*.
## FEEDS
Feeds can be specified in the [[tasks.feeds]] array of tables. Multiple feeds
can be specified per task.
Example feed configuration:
```
[[tasks]]
# ...
# This generates a feed for the files in content/blog
# and writes it to blog/atom.xml (relative to the output directory)
[[tasks.feeds]]
input_dir = "blog"
title = "My Blog"
template = "atom.xml"
output = "blog/atom.xml"
# You can generate multiple feeds per task
# The generated feed can be written anywhere
# Here it is written to feed.xml (relative to the output directory)
[[tasks.feeds]]
input_dir = "blog"
title = "My Blog"
template = "custom_feed.xml"
output = "feed.xml"
```
*input_dir*
the content folder with which to populate the feed
*title*
the title of the feed, accessible via {{ .Title }} in the feed template
*template*
the template to use for the feed
*output*
the output path for the rendered feed
# TEMPLATES
Templates have certain data and functions available to them.
## SITE VARIABLES
The following site-wide variables are available:
*.Title*
The title of the site.
*.Params*
Extra parameters specified in configuration.
*.Generated*
Site generation time.
*.Root*
The root page of the site. See *PAGE VARIABLES*.
Some of these variables are defined in your site's configuration. See
*CONFIGURATION*.
Site variables can be accessed from templates with the *site* function. See
*TEMPLATE FUNCTIONS*.
## PAGE VARIABLES
The following page variables are available:
*.Title*
The title of the page
*.Date*
The date of the page
*.Weight*
The weight of the page
*.Path*
The path to the page
*.URL*
The URL of the page. If no base URL is configured, it is equivalent to
*.Path*.
*.FilePath*
The path of the page file or directory relative to the content directory
*.Content*
The contents of the page
*.Params*
Extra parameters specified in frontmatter
*.Prev*
The previous page in sorted order
*.Next*
The next page in sorted order
*.Pages*
List of pages in this directory
*.Dirs*
List of subdirectories in this directory
Some of these variables are defined in page frontmatter. See *FRONTMATTER*.
Page variables can be accessed from page and index templates.
## PAGE FUNCTIONS
The following page functions are available:
*.GetPage* _path_
Retrieves the page in this directory with the given _path_, which may be
relative or absolute.
Example:
```
{{/* Retrieve a directory relative to the root directory
and iterate over its pages */}}
{{ with site.Root.GetPage "/blog" }}
{{ range .Pages }}
{{ .Title }}
{{ end }}
{{ end }}
{{/* Retrieve a directory relative to the current directory
and iterate over its pages */}}
{{ with .GetPage "posts" }}
{{ range .Pages }}
{{ .Title }}
{{ end }}
{{ end }}
{{/* Retrieve a page relative to the current directory */}}
{{ with .GetPage "posts/hello-world.gmi" }}
{{ .Title }}
{{ end }}
```
Page functions can be accessed from page and index templates.
## FEED VARIABLES
The following feed variables are available:
*.Title*
The title of the feed
*.Path*
The path to the feed directory
*.URL*
The URL of the feed directory
*.Pages*
List of pages in this feed
Some of these variables are defined in feed configuration. See *FEEDS*.
Feed variables can be accessed from feed templates.
## PARTIAL TEMPLATES
Partial templates can be placed in the templates/\_partials directory.
Partial templates can be executed from any other template with the *partial*
function. See *TEMPLATE FUNCTIONS*.
## TEMPLATE FUNCTIONS
All templates have the following functions available to them:
*and* _args..._
Returns the boolean AND of its arguments by returning the
first empty argument or the last argument, that is,
"and x y" behaves as "if x then y else x". All the
arguments are evaluated.
*call* _function_, _args..._
Returns the result of calling the first argument, which
must be a function, with the remaining arguments as parameters.
Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
Y is a func-valued field, map entry, or the like.
The first argument must be the result of an evaluation
that yields a value of function type (as distinct from
a predefined function such as print). The function must
return either one or two result values, the second of which
is of type error. If the arguments don't match the function
or the returned error value is non-nil, execution stops.
*eq* _arg1_, _arg2_
Returns the boolean truth of _arg1_ == _arg2_.
*exec* _command_, _input_
Executes the given external command with _input_ provided as standard input.
Returns its standard output.
*ge* _arg1_, _arg2_
Returns the boolean truth of _arg1_ >= _arg2_.
*gt* _arg1_, _arg2_
Returns the boolean truth of _arg1_ > _arg2_.
*html* _args..._
Returns the escaped HTML equivalent of the textual
representation of its arguments. This function is unavailable
in HTML templates, with a few exceptions.
*index* _collection_, _args..._
Returns the result of indexing its first argument by the
following arguments. Thus "index x 1 2 3" is, in Go syntax,
x[1][2][3]. Each indexed item must be a map, slice, or array.
*js* _args..._
Returns the escaped JavaScript equivalent of the textual
representation of its arguments.
*le* _arg1_, _arg2_
Returns the boolean truth of _arg1_ <= _arg2_.
*len* _list_
Returns the integer length of its argument.
*lt* _arg1_, _arg2_
Returns the boolean truth of _arg1_ < _arg2_.
*math.Add* _arg1_, _arg2_
Returns _arg1_ + _arg2_ as an integer if both arguments are
integers, otherwise as a float.
*math.Sub* _arg1_, _arg2_
Returns _arg1_ - _arg2_ as an integer if both arguments are
integers, otherwise as a float.
*math.Mul* _arg1_, _arg2_
Returns _arg1_ \* _arg2_ as an integer if both arguments are
integers, otherwise as a float.
*math.Div* _arg1_, _arg2_
Returns _arg1_ / _arg2_ as a float.
*math.Mod* _arg1_, _arg2_
Returns _arg1_ % _arg2_ as an integer.
*math.Ceil* _arg_
Returns the least integer value greater than or equal to _arg_.
*math.Floor* _arg_
Returns the greatest integer value less than or equal to _arg_.
*math.Log* _arg_
Returns the natural logarithm of _arg_ as a float.
*math.Max* _arg1_, _arg2_
Returns the greater of _arg1_ and _arg2_ as an integer if both arguments are
integers, otherwise as a float.
*math.Min* _arg1_, _arg2_
Returns the lesser of _arg1_ and _arg2_ as an integer if both arguments are
integers, otherwise as a float.
*math.Pow* _arg1_, _arg2_
Returns _arg1_ ^ _arg2_ as a float.
*math.Round* _arg_
Returns the nearest integer to _arg_, rounding half away from zero.
*math.Sqrt* _arg_
Returns square root of _arg_ as a float.
*ne* _arg1_, _arg2_
Returns the boolean truth of _arg1_ != _arg2_.
*not* _arg_
Returns the boolean negation of its single argument.
*or* _args..._
Returns the boolean OR of its arguments by returning the
first non-empty argument or the last argument, that is,
"or x y" behaves as "if x then x else y". All the
arguments are evaluated.
*partial* _name_, _data_
Executes the named partial template with the provided data. See *PARTIAL
TEMPLATES*.
Example:
```
{{ partial "header.gmi" . }}
```
*path.Base* _path_
Returns the last element of _path_.
*path.Clean* _path_
Returns the shortest path name equivalent to _path_.
*path.Dir* _path_
Returns all but the last element of _path_, typically the path's directory.
*path.Ext* _path_
Returns the filename extension used by _path_.
*path.Join* _elem..._
Joins any number of path elements into a single path.
*print* _args..._
Formats using the default formats for its operands and returns the resulting
string. Spaces are added between operands when neither is a string.
*printf* _format_, _args..._
Formats according to a format specifier and returns the resulting string.
*println* _args..._
Formats using the default formats for its operands and returns the resulting
string. Spaces are always added between operands and a newline is appended.
*reverse* _list_
Returns a reversed copy of the provided slice or array.
*safeCSS* _css_
Encapsulates known safe CSS content.
*safeHTML* _html_
Encapsulates a known safe HTML document fragment.
*safeHTMLAttr* _attr_
Encapsulates an HTML attribute from a trusted source.
*safeJS* _js_
Encapsulates a known safe JavaScript expression.
*safeURL* _url_
Encapsulates a known safe URL or URL substring.
*site*
Returns site information (see *SITE VARIABLES*).
*slice* _list_, _args..._
slice returns the result of slicing its first argument by the
remaining arguments. Thus "slice x 1 2" is, in Go syntax, x[1:2],
while "slice x" is x[:], "slice x 1" is x[1:], and "slice x 1 2 3"
is x[1:2:3]. The first argument must be a string, slice, or array.
*strings.Count* _string_, _substr_
Counts the number of non-overlapping instances of _substr_ in _string_.
If _substr_ is an empty string, Count returns 1 + the number of Unicode code
points in _string_.
*strings.HasPrefix* _string_, _prefix_
Reports whether _string_ begins with _prefix_.
*strings.HasSuffix* _string_, _suffix_
Reports whether _string_ ends with _suffix_.
*strings.Join* _elems_, _sep_
Concatenates the elements of its first argument to create a single string.
The separator string _sep_ is placed between elements in the resulting
string.
*strings.Repeat* _string_, _count_
Returns a new string consisting of _count_ copies of _string_.
It panics if _count_ is negative or if the result of
(len(_string_) \* _count_) overflows.
*strings.Replace* _string_, _old_, _new_, _n_
Returns a copy of _string_ with the first _n_ non-overlapping instances of
_old_ replaced by _new_. If _old_ is empty, it matches at the beginning of
the string and after each UTF-8 sequence, yielding up to k+1 replacements
for a k-rune string. If _n_ < 0, there is no limit on the number of
replacements.
*strings.ReplaceAll* _string_, _old_, _new_
Returns a copy of _string_ with all non-overlapping instances of _old_
replaced by _new_. If _old_ is empty, it matches at the beginning of the
string and after each UTF-8 sequence, yielding up to k+1 replacements for a
k-rune string.
*strings.Split* _string_, _sep_
Slices _string_ into all substrings separated by _sep_ and returns a slice
of the substrings between those separators.
If _string_ does not contain _sep_ and _sep_ is not empty, Split returns a
slice of length 1 whose only element is _string_.
If _sep_ is empty, Split splits after each UTF-8 sequence. If both _string_
and _sep_ are empty, Split returns an empty slice.
*strings.Title* _string_
Returns a copy of the string with all Unicode letters that begin words
mapped to their Unicode title case.
*BUG:* The rule Title uses for word boundaries does not handle Unicode
punctuation properly.
*strings.ToLower* _string_
Returns _string_ with all Unicode letters mapped to their lower case.
*strings.ToUpper* _string_
Returns _string_ with all Unicode letters mapped to their upper case.
*strings.Trim* _string_, _cutset_
Returns a slice of _string_ with all leading and trailing Unicode code
points contained in _cutset_ removed.
*strings.TrimLeft* _string_, _cutset_
Returns a slice of _string_ with all leading Unicode code points contained
in _cutset_ removed.
To remove a prefix, use *strings.TrimPrefix* instead.
*strings.TrimPrefix* _string_, _prefix_
Returns _string_ without the provided leading _prefix_ string. If _string_
doesn't start with _prefix_, it is returned unchanged.
*strings.TrimRight* _string_, _cutset_
Returns a slice of _string_ with all trailing Unicode code points contained
in _cutset_ removed.
To remove a suffix, use *strings.TrimSuffix* instead.
*strings.TrimSpace* _string_
Returns a slice of _string_ with all leading and trailing white space
removed, as defined by Unicode.
*strings.TrimSuffix* _string_, _suffix_
Returns _string_ without the provided trailing _suffix_ string. If _string_
doesn't end with _suffix_, it is returned unchanged.
*urlquery* _args..._
Returns the escaped value of the textual representation of
its arguments in a form suitable for embedding in a URL query.
This function is unavailable in HTML templates, with a few
exceptions.