The name says it all. Or not.
Strange is a static site generator.
It converts any site structure from commonmark (standardized markdown) to HTML.
The site should be created in the src/
directory, with the desired structure
(see Create a new site for info).
Any file ending in .md
will be parsed by commonmark to generate the page body,
and then wrapped in a template of your choice made with tera/twig/jinja2 or
handlebars syntax to generate the final page.
The file extension will be changed to .html
.
For example, an index.md
file will become index.html
.
The final wrapping engine can be chosen in the config between tera and handlebars (see The config file below).
You can add parsing steps to the process by naming the file accordingly.
For example, if you name a file index.md.tera
(or index.md.twig
, or index.md.j2
)
the file will first be parsed with tera, then with markdown, and finally wrapped
in a template as explained.
And a file names index.md.hbs
will be parsed by handlebars first, then markdown, and
finally wrapped in a template.
Every other file will be copied over without modifications.
Exceptions are:
.
) are ignored_
) are ignored.bak
or in ~
are ignoredThe directory structure will be kept as is.
You can create a new site by creating a new directory called "sitename" with the following command:
sh
strange init sitename
If you already have a directory and want to create a site inside it,
just cd
or chdir
into the directory and use
sh
strange init
The command, by default, will create 4 directories and one config file:
src
will contain the source of the sitetpl
will contain the handlebars templatesbuild
will contain the generated siteconfig.yaml
will contain the site configurationAll the pages and assets for the site must be put in src
, building
the structure as if it was the final site.
You can configure some settings that will be written into the config file:
-e <ENGINE>
: select the rendering engine for the templates: tera
(default) or handlebars
-s <SOURCEDIR>
: select the source directory name. Default: src
-d <DESTDIR>
: select the destination directory name. Default: build
-t <TPLDIR>
: select the page templates directory name. Default: tpl
Example:
sh
strange init -e handlebars -s source -d dest -t templates
While inside the site directory (NOT the src/
subdirectory) you can
create a new page with
sh
strange new Insert the page title here
The new
command accepts several parameters:
-d
: Prepends the current date to file name-t
: (Usable only with -d) Also prepends the time-p <PATH>
: Creates the page inside the specified (relative to src/
) path.Example, if on the 19th of March 2017, at 12:34:56 you run:
sh
strange new -dtp posts/2017 My new blog post
It will create a file named src/posts/2017/2017-03-19-1234-my-new-blog-post.md
.
A page normally has an .md
extension and is formed by a prelude in YAML format between ---
markers,
and the body of the page after it. Example:
```markdown
title: My new blog post date: 2017-03-19T12:34:56Z author: Alex layout: post caption: | A short (3-4 lines) caption of the page, to be shown as a preview tags: - blogpost
This is the full text of the blog in markdown format.
It supports the commonmark specification.
Tables and footnotes are enabled in the parser.
```
If you rename the page by adding a .tera
extension (or .twig
, or .j2
), you can use the jinja2
syntax in the page, and will have access to most of the Placeholders.
For example, a file named src/my-page.md.twig
could contain:
```markdown
title: My Page date: 2017-03-20T10:00:00Z author: Alex layout: page caption: A short caption
My page can contain a list of its tags:
{% for tag in tags %} - {{ tag }} {% endfor %}
```
WARNING: If a page uses a template engine, it's highly recommended to have a caption in the YAML prelude. This is because if it's not present, strange will try to use the first 2 paragraph in the body to generate a caption, and this could truncate template constructs, generating an invalid template to parse.
.md
will parse the page with a commonmark/markdown syntax and generate a .html
file.
.twig
, .j2
, .tera
will parse the page with Tera, a Jinja2-inspired engine, and remove the extension.
.hbs
will parse the page with handlebars and remove the extension
A file not ending with an engine-supported extension will not be parsed. Any file that, after the initial parsing,
ends with a .html
extension will be wrapped by the specified (or default, which is page
) page template.
my-post.html
will not be parsed, but it will be wrapped in the page template
my-post.twig.html
will not be parsed, but it will be wrapped in the page template
my-post.html.twig
will be parsed by tera and wrapped in the page template, and renamed my-post.html
my-post.md
will be parsed by markdown and wrapped in the page template, and renamed my-post.html
my-post.twig
will be parsed by tera, renamed my-post
and not wrapped in a page template
main.css.twig
will be parsed by tera and renamed main.css
main.js.twig
will be parsed by tera and renamed main.js
And so on.
You can build the site with:
sh
strange build
This will completely wipe the build
directory, re-create it and
convert all pages, copy all assets and recreate the directory structure
you have in the src
directory.
You can clean the destination directory with:
sh
strange clean
This will delete all the files in the destination directory (as defined during init
and in the config.yaml
file), leaving it empty.
You can instruct strange to look for changes to files in the project and automatically rebuild it with:
sh
strange watch
You can also start a local webserver to serve the generated pages with:
sh
strange serve
While serve
is active, watch
is also in action, so refreshing your page in the browser will show the
new version of the page. Please allow a few seconds to rebuild the project, especially if it's big.
The default config is to start a server on http://127.0.0.1:9876
You can configure serve
to listen on a particular IP and/or port via the command line:
sh
strange serve -a 192.168.1.1 -p 8080
or via the config file (strange.yaml
):
yaml
serve:
ip: 192.168.1.1
port: 8080
Both serve
and watch
will hold the terminal where they are run. You can press CTRL-C to end them, and you will
need to open a separate terminal (or terminal window) to issue different commands.
Strange is configured via a global config file in the root of the project, called strange.yaml
.
This file contains both the general project settings and the configurable plugins settings.
For the project settings, see the inline comments.
For the plugin settings, see the Plugins section in this documentation.
Example:
```yaml
site: # The title of the site. It will be used in the
# The URL of the website. Do not append "/index.html" at the end. url: http://example.net
templates:
# Select the templating engine. Available: tera
, handlebars
. Default: tera
engine: tera
pages:
# If set to true, automatically prepend date to pages' filename, like strange new -d
. Default: false
date: true
# If set to true, automatically prepend time to pages' filename, like strange new -dt
. Default: false
time: false
paths:
# Sets the path to the folder containing source files. Default: src
src: src
# Sets the path to the destination where pages will be built files. Default: build
dest: build
# Sets the path to the folder containing page templates. Default: tpl
tpl: tpl
serve:
# Sets the IP address on which the strange serve
command will start a webserver. Default: 127.0.0.1
ip: 127.0.0.1
# Sets the port on which the webserver will listen port: 9876
plugins: data: dir: dataplugin rss: enabled: true filename: rss.xml num: 10 ```
By default strange, during the init
phase, only creates one page template, called page.html.tera
,
in the tpl
directory.
This is the default page template if a page does not request a different one, via the layout
setting in the YAML
prelude (see Create a new page).
You can create new layout templates by creating new files in the tpl directory, by following a simple rule:
if you want to be able to use, for example, post
as a layout, create a file named post.html.tera
, or
post.html.twig
, or post.html.j2
to use a jinja2-style template, or post.html.hbs
to use a handlebars-style
template.
Files starting with an underscore are ignored, so you can use this trick to create an inheritance hierarchy for your
templates, for example via the extends
command in jinja2-style templates.
For example, you can have a _base.html.tera
like this:
```twig
{% block head %}and a page.html.tera
like this:
```twig {% extends "_base.html" %}
{% block main %}
{{ title }}
{{ body }}
Just remember: the name you put in extends
is the file name without the .tera
, .twig
or .j2
extension,
while the name you use in the page preludes must also be without the .html
extension.
Most of the placeholders are available during the conversion from markdown/CommonMark to page HTML and during the handlebars templates to final HTML conversion.
title
(string)
The title of the page
Not available during .skel
files processing.
date
(Date object)
The date of the page
url
(string)
The absolute URL of the page
author
(string)
The author as specified in the prelude, or empty string
Not available during .skel
files processing.
caption
(string)
The caption as specified in the prelude, or first 2 paragraph of the page body.
It supports commonmark and gets converted to HTML.
tags
(array of strings)
The list of tags associated to the page in the prologue
type
(string)
The template selected in the prelude
body
(string)
The (parsed) body of the page.
Not available in markdown/commonmark templates
page
The is a special placeholder, containing all the plugins data
specific for the current page (see Plugins for a list of values
available).
Not available during .skel
files processing.
site
The is a special placeholder, containing all the plugins data for
the whole site (see Plugins for a list of values available)
All plugins use some basic objects:
A page object contains meta-information about the page.
It contains all the values described in Placeholders except body
, page
and site
Contains information about a date:
year
month
day
hour
minute
second
datetime
(yyyy-mm-dd hh:ii)
full
(yyyy-mm-dd hh:ii:ss)
iso
(yyyy-mm-ddThh:ii:ssZ)
date
(yyyy-mm-dd)
time
(hh:ii)
fulltime
(hh:ii:ss)
Ths plugin provides informations about the previous and next page and the pages at the same level as the current one.
Pages are ordered alphabetically by name.
page.nav
contains:
prev
(optional, object)
An object representing the previous page. It contains a Page object.
next
(optional, object)
An object representing the following page. It contains a Page object.
pages
(array)
A list of Page objects representing the pages in the same folder (at
the same level) as the current one, including the current one.
in Tera:
html
{% if page.nav.prev %}
<a class="prev" href="{{ page.nav.prev.url }}">{{ page.nav.prev.title }}</a>
{% endif %}
{% if page.nav.next %}
<a class="next" href="{{ page.nav.next.url }}">{{ page.nav.next.title }}</a>
{% endif %}
In Handlebars:
html
{{#if page.nav.prev }}
<a class="prev" href="{{ page.nav.prev.url }}">{{ page.nav.prev.title }}</a>
{{/if}}
{{#if page.nav.next }}
<a class="next" href="{{ page.nav.next.url }}">{{ page.nav.next.title }}</a>
{{/if}}
This plugin provides a tree of all the pages in the site.
page.sitemap
contains:
pages
(array)
This array contains a list of all the pages at a certain level of
the tree as Page objects.
pages_rev
(array)
This array contains a list of all the pages at a certain level of
the tree as Page objects, in reverse order.
folders
(object)
This is an object in which every key is the name of the containing
folder, and each item is an object containing the same keys as the
"root" object (pages and children).
In Tera:
```html
```
In Handlebars:
```html
```
This plugin groups all the pages in the site by tag
site.tag
is an object where keys are tags and each contains an array of
Page objects
In Tera:
```html
```
In Handlebars:
```html
```
This plugin scans a directory named data
in the root of your project
(not inside src
), looking for YAML files and transforming them into a
tree structure.
Nested subdirectories are not supported.
Files can have .yml
or .yaml
extension and must be well-formed (with the
initial ---
).
YAML multi-documents are not supported: only the first one will be parsed.
Given a structure like this:
+ src/
| + page1.md
| ...
| data/
| + info.yml
| + server.yaml
| build/
If info.yml is
```
name: My name address: street: somewhere number: 123 exists: false tags: - one - two - three ```
and server.yaml
is
```
url: example.net port: 8080 ```
You can use, in the template:
```html
{{ site.data.server.url }}:{{ site.data.server.port }}
HI, I'm {{ site.data.info.name }} and I live {{ site.data.info.address.street }}. ```
The directory containing the data files can be configured in the strange.yaml
config file:
yaml
plugins:
data:
dir: mydatadir
NOTE: It is recommended to not use the source, the destination or the template directories to
store data files (or the data
plugin directory), as this could lead to loss of data or
spurious files generation.
This plugin generates an RSS file with the latest articles. By default it will generate
a file named rss.xml
in the configured destination directory (build/
by default)
containing the latest 10 articles, as detected by their date
metadata field
(see Create a new page for more information).
The plugin can be configured in the strange.yaml
config file:
yaml
plugins:
rss:
enabled: true
filename: rss.xml
num: 10
The available options are:
enabled
: if set to true
, it will generate the file. If set to false
, it will not.
Default: true
filename
: the path to the filename, relative to the destination directory.
For example: feeds/rss.xml
or feed.xml
or some/deep/dir/myfeed.rss.xml
Default: rss.xml
num
: the number of pages to include in the feed.
Default: 10
This plugin also exposes a variable you can use in your templates to have the URL to the
generated file. You must configure the site URL in the strange.yaml
config file.
html
<!doctype html>
<html>
<head>
<link
href="{{ site.rss.url }}"
rel="alternate"
type="application/rss+xml"
title="My wonderful web site"
/>
</head>
<body>
{{ body }}
</body>
</html>
Strange is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
Strange is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Strange. If not, see http://www.gnu.org/licenses/.
strange serve
to serve built pages[x] strange watch
to auto-recompile changed files
[ ] Find a way to have absolute links in plugins