See the README for installation and usage. The rest of this document shows examples of its use.
There are other projects that use Nancy, and further illustrate its use:
- python-project-template is a simple customizable Python project template
Note: the techniques used here, and more, are bundled into a convenient tool that builds on Nancy, called Linton.
Suppose a web site has the following page design:
Most of the elements are the same on each page, but the breadcrumb trail has to show the canonical path to each page, and the logo is bigger on the home
page, which is index/index.html.
Suppose further that the web site has the following structure, where each line corresponds to a page:
├── Home page
├── People
│ ├── Hilary Pilary
│ └── Jo Bloggs
├── Places
│ ├── Timbuktu
│ └── Vladivostok
The basic page template looks something like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="$run(path-to-root.in.sh,$path)/style.css">
<title>$include(title.in.txt)</title>
</head>
<body>
<div class="wrapper">
<div class="logo">$include(logo.in.html)</div>
<div class="breadcrumb.in"><div class="breadcrumb-content">$include(breadcrumb.in.html)</div></div>
</div>
<div class="wrapper">
<div class="menu">$include(menu.in.html)</div>
<div class="main">$include(main.in.html)</div>
</div>
</body>
</html>
Making the menu an included file is not strictly necessary, but makes the template easier to read. The pages will be laid out as follows:
├── index
│ └── index.html
├── People
│ ├── Hilary Pilary
│ │ └── index.html
│ ├── index
│ │ └── index.html
│ └── Jo Bloggs
│ └── index.html
├── Places
│ ├── index
│ │ └── index.html
│ ├── Timbuktu
│ │ └── index.html
│ └── Vladivostok
│ └── index.html
├── nancy-small.png
├── nancy-tiny.png
└── style.css
The corresponding source files are laid out as follows. This may look a little confusing at first, but note the similarity to the HTML pages, and hold on for the explanation!
├── index
│ ├── index.nancy.html
│ ├── logo.in.html
│ ├── main.in.html
│ └── title.in.txt
├── People
│ ├── Hilary Pilary
│ │ ├── breadcrumb.in.html
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ ├── index
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ ├── Jo Bloggs
│ │ ├── breadcrumb.in.html
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ └── breadcrumb.in.html
├── Places
│ ├── index
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ ├── Timbuktu
│ │ ├── breadcrumb.in.html
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ ├── Vladivostok
│ │ ├── breadcrumb.in.html
│ │ ├── index.nancy.html
│ │ ├── main.in.html
│ │ └── title.in.txt
│ └── breadcrumb.in.html
├── breadcrumb.in.html
├── logo.in.html
├── menu.in.html
├── nancy-small.png -> ../../../logo/nancy-small.png
├── nancy-tiny.png -> ../../../logo/nancy-tiny.png
├── path-to-root.in.sh
├── style.css
└── template.in.html
Note that there is only one menu fragment (the main menu is the same for every page), while each section has its own breadcrumb trail (breadcrumb.in.html), and each page has its own content (main.in.html).
Now consider how Nancy builds the page whose URL is Places/Vladivostok/index.html. Assume the source files are in the directory source. This page is built from source/Places/Vladivostok/index.nancy.html, whose contents is $include(template.in.html). According to the rules given in the Operation section of the manual, Nancy will look first for files in source/Places/Vladivostok, then in source/places, and finally in source. Hence, the actual list of files used to assemble the page is:
source/breadcrumb.in.htmlsource/logo.in.htmlsource/menu.in.htmlsource/path-to-root.in.shsource/Places/breadcrumb.in.htmlsource/Places/Vladivostok/breadcrumb.in.htmlsource/Places/Vladivostok/main.in.htmlsource/Places/Vladivostok/title.in.txtsource/template.in.html
For the site’s index page, the file index/logo.in.html will be used for the logo fragment, which can refer to the larger graphic desired.
The breadcrumb.in.html fragments, except for the top-level one, contain the command
$include(breadcrumb.in.html)
When expanding source/Places/breadcrumb.in.html, Nancy ignores that file, since it is already expanding it, and goes straight to source/breadcrumb.in.html. This means that the breadcrumb trail can be defined recursively: each breadcrumb.in.html fragment includes all those above it in the source tree.
This scheme, though simple, is surprisingly flexible; this example has covered all the techniques most users will ever need.
The site is built by running Nancy on the sources directory:
nancy sources site
Given a simple page template, a datestamp can be added by using the date
command with $paste:
# Title
Page contents.
--
Last updated: $expand{$run(python,-c,import datetime; print(datetime.now().strftime('%Y-%m-%d')))}
This gives a result looking something like:
# Title
Page contents.
--
Last updated: 2016-10-12
Since output file and directory names are expanded from input names, you can use commands to determine the name of an output file or directory.
For example, given a file called author.in.txt containing the text Jo Bloggs, an input file in the same directory called $include(author.in.txt).txt would be called Jo Bloggs.txt in the output.
Sometimes it is more convenient to customize a Nancy template on the command line than by putting information into files; for example, when Nancy is run to set up a project that does not itself use Nancy.
This can be done conveniently with environment variables, by invoking Nancy as follows:
env VARIABLE1=value1 VARIABLE2=value2 … nancy …
Then, you can use $run(printenv,VARIABLE1) (or the equivalent in Python or other languages) in the template files. python-project-template uses this technique to generate skeleton Python projects.
Source code examples can be added inline as normal in Markdown code blocks, but it’s often more convenient to include code directly from a source file. This can be done directly with $paste, or you can use the cat command to include a file that is not in the Nancy input tree: $run(cat,/path/to/source.js).
The output of commands can similarly be included in documents. The output of terminal commands may be better included in a code block, to preserve formatting that depends on a fixed-width font.
Look at the source for the Cookbook for more examples of these techniques, including the use of sed and grep to filter the contents of files and output of commands.
Nancy is mostly intended for templating text files. Sometimes, we would like to create binary files, for example an image containing context-dependent text. This can be done with a .nancy file just as for text.
Sometimes it is desirable to process the output, rather than the input. For this, you can run Nancy once to produce an initial set of results, and then run it again to produce further outputs. For example, suppose you want to produce Zip files of the contents of certain directories in Nancy’s output.
The following script will produce a Zip file of a directory, excluding .nancy files:
#!/bin/sh
cd $(dirname "${NANCY_INPUT}")
zip -r archive.zip . --exclude *.nancy.*
Assuming it is called make-zip.in.in.sh, it can be used thus, from a file called archive.nancy.zip:
$run(make-zip.in.sh)
The OUTPUT argument to Nancy can be an existing directory. If you want to update an existing project, you can re-use a previous output directory, and existing files will be overwritten. However, if some files are no longer generated, the old copies will be left there. To delete files that are not regenerated by Nancy, use the --delete option.
If you have a project that you frequently update, but that takes a long time to process, usually because some $run commands are long-running, you may want to avoid regenerating files whose contents would be identical. In general, this is not possible, as Nancy cannot tell what output a $run command will produce. However, it can assume that they make no difference. If you use the --update flag, Nancy will find all the files mentioned in $include, $paste and $run commands, and will only expand a template file if at least one of those has a timestamp newer than the corresponding output file. Input files and plain files are similarly only copied if they are newer than the corresponding output.
This can also be useful for other programs that rely on the timestamps of files in Nancy’s output; for example, a program that uploads a web site from a copy produced by Nancy might upload only those files whose timestamp is newer than the version already online. For a large web site, this could save a lot of time to update it.
Sometimes it’s desirable to override parts of a project, for example to have settings for a web site that are useful in development, but not production. This can be achieved by using UnionFS (on operating systems that support it) to combine two directory trees.