Templer
A modular extensible static-site-generator written in perl.
Install / Use
/learn @skx/TemplerREADME
Templer
Templer is yet another static site generator, written in Perl.
It makes use of the HTML::Template module for performing variable expansion within pages and layouts, along with looping and conditional-statement handling.
Templer has evolved over time for my own personal use, but I believe it is sufficiently generic it could be useful to others.
My motivation for putting it together came from the desire to change several hand-made, HTML-coded, sites to something more maintainable such that I could easily change the layout in one place.
The design evolved over time but the key reason for keeping it around is that it differs from many other simple static-generators in several ways:
- You may define global variables for use in your pages/layouts.
- A page may define and use page-specific variables.
- You may change the layout on a per-page basis if you so wish.
- This was something that is missing from a lot of competing tools.
- Conditional variable expansion is supported, via
HTML::Template. - File contents, shell commands, and file-globs may be used in the templates
- This allows the trivial creation of galleries, for example.
- These are implemented via plugins.
- Plugins are documented in the file PLUGINS.md.
- You may also embed perl code in your pages.
Another key point is that the layouts allow for more than a single simple "content" block to be placed into them - you can add arbitrary numbers of optional side-menus, for example.
Although this tool was written and used with the intent you'd write your site-content in HTML you can write your input pages in Textile or Markdown if you prefer (these inputs are supported via plugins).
Concepts
A templer site comprises of three things:
- A global configuration file.
- This defines the paths to search for input pages, layout templates, plugins, etc.
- This may contain global variable declarations.
- Please see the example configuration file:
templer.cfg.
- A layout.
- This is used to format the output pages, defining the common look and feel.
- A series of pages & assets.
- Pages have their content processed and inserted into the layout to produce output HTML.
- Assets are not processed, but are copied into the output directory literally.
In general we assume there is a tree like so:
├── input
│ ├── index.wgn
│ ├── ...
│ ├── ...
│ ├── favicon.ico
│ └── robots.txt
├── layouts
│ └── default.layout
├── output
└── templer.cfg
Every file in the input directory is either considered to be a page which is converted into HTML, or an asset which is copied into the output-tree with no changes made.
In the example above input/index.wgn would become output/index.html.
NOTE The
.wgnsuffix is an example. You can define which suffix is considered a page via the configuration file.
There is also an "in-place" mode. When working in-place there is no distinct output directory, instead output is written to the same directory in which is encountered. Given an input directory you might see this kind of transformation:
index.wgn -> index.html
about.wgn -> about.html
favicon.ico [Ignored and left un-modified.]
robots.txt [Ignored and left un-modified.]
..
There is also a synchronized mode. When working synchronized any file in the output directory which do not have a source file in input directory (page or asset) is removed each time the site is rebuild.
Pages
Your site will be made of pages, which are snippets of HTML you write. These snippets will be processed and inserted into the layout file before being output to disk.
A page is a simple file which contains a header and some content. This is a sample page:
Title: This is the title page.
----
<p>This is the body of the page</p>
The header of the page is delimited from the body by four dashes (----) and
can contain an arbitrary number of variable definitions.
Special Page Variables
In your page you can define, and refer to, an arbitrary number of variables but some names are reserved - and any variable with one of those names will be treated specially:
The special variable layout may be used to specify a different layout
template for the current page. If there is no per-page layout specified then
the global layout declared in the templer.cfg file will be used.
The special variable template-filter may be used to specify some filters to
apply on the used layout in order to transform it into valid HTML::Template
file. If there is no per-page layout filter specified then the global layout
declared in the templer.cfg file will be used.
The special variable output may be used to specify an alternative output
file. For example the input file index.wgn would normally become
index.html, but you could make it become something else.
The special variable format may be given a value of textile, markdown, or
perl to enable processing the page body with the appropriate filter. These
formatters are implemented as plugins, and will be available
assuming their dependencies are installed.
Textile and markdown are well-known, and allow you to write your page content naturally. The perl-formatter is used to allow you to write dynamic content in Perl in your page-body, via the Text::Template module. Perl code to be executed is wrapped in { and } characters. Here is a sample page:
Title: This page has code in it
format: perl
----
<p>This page has some code in it.</p>
<p>I am running on { `hostname` }...</p>
<p>I am {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
$year += 1900;
$year - 1976;
} years old.</p>
NOTE: Formatters may be chained. For example "
format: perl, markdown".
Variable Definitions
Within the header of each page you may declare an arbitrary number of per-page variables. These variable declarations are then available for use within the page-body, using the standard HTML::Template expansion facilities:
Title: Page title
Name: Steve Kemp
----
<p>Hello, my name is <!-- tmpl_var name='name' -->.</p>
NOTE: All variable-names are transformed to lower-case for consistency, which is why we refer to the variable
namerather than the definedName.
As well as simple "name: value" pairs there are also additional options implemented in plugins;
- A variable may refer to the contents of a given file.
- Using
read_file.
- Using
- A variable may refer to a list of filenames, matching a pattern.
- Using
file_glob.
- Using
- A variable may contain the output of running a command.
- Using
run_command.
- Using
- A variable may be based on the timestamp of the input page.
- Using
timestamp.
- Using
- A variable may contain the contents of a remote RSS feed.
- Using
rss(count, URL).
- Using
- A variable may contain the result of a key-lookup from a Redis server.
- Using
redis_get('foo').
- Using
In addition to declaring variables in a page-header you may also declare
global variables in your templer.cfg file, or upon the command-line
via --define foo=bar.
Defining global variables is demonstrated in the sample templer.cfg file.
File Globbing Variables
We've already seen simple variables declared by key: value in the page header,
in addition to this you may define a variable that refers to a number of files
by pattern.
Here is a simple example of creating a gallery which will include files matching
the pattern img/*.jpg:
Title: My gallery
Images: file_glob( "img/*.jpg" )
---
<!-- tmpl_if name='images' -->
<!-- tmpl_loop name='images' -->
<p><img src="<!-- tmpl_var name='file' -->"
height="<!-- tmpl_var name='height' -->"
width="<!-- tmpl_var name='width' -->" /> </p>
<!-- /tmpl_loop -->
<!-- tmpl_else -->
<p>No images were found.</p>
<!-- /tmpl_if -->
TIP: If your images are numbered numerically you can ensure their correct order by doing this:
Title: This is my title
images: file_glob( img/[0-9].jpg img/1[0-9].jpg )
----
<p>My gallery is now included in ascending numerical order:</p>
This facility is implemented in the Templer::Plugin::FileGlob plugin.
The file glob is primarily designed for handling image-galleries, which is why it will set the height and width attributes if your glob matches *.jpg, *.png, etc. However it can also be used for non-images.
If your glob matches files which are not images it will populate the member content, being the text-content of the matching files. This allows you to include files easily. For example:
Title: This is my news-page
news: file_glob( news-*.txt )
----
<p>Here are the recent events:</p>
<!-- tmpl_loop name='news' -->
<p><!-- tmpl_var name='content' --></p>
<!-- /tmpl_loop -->
This assumes you have files such as news-20130912.txt, etc, and will show the contents of each file in (glob)order.</p>
If matching files are templer input files then all templer variables are populated instead of the text-content of the matching files.
In all cases it will populate dirname, basename and extension, being parts of each matching files name.
File Inclusion
The [HTML::Template](http://search.cpan.org/perldoc?HTML%3
Related Skills
node-connect
347.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
347.0kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
