Strange

The name says it all. Or not.

Strange is a static site generator.

It converts any site structure from commonmark (standardized markdown) to HTML.

Introduction

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:

The directory structure will be kept as is.

Create a new site

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:

All 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:

Example:

sh strange init -e handlebars -s source -d dest -t templates

Create a new page

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:

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

- random-thoughts

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

tags: [intro, "Complex tag", help]

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.

Supported extensions

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.

And so on.

Building the site

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.

Cleaning the destination 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.

Watching changes and serving through a local webserver

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.

The config file

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

Strange configuration file

site: # The title of the site. It will be used in the and possibly in some plugins title: My beatiful test site</p> <p># The URL of the website. Do not append "/index.html" at the end. url: http://example.net</p> <p>templates: # Select the templating engine. Available: <code>tera</code>, <code>handlebars</code>. Default: <code>tera</code> engine: tera</p> <p>pages: # If set to true, automatically prepend date to pages' filename, like <code>strange new -d</code>. Default: <code>false</code> date: true</p> <p># If set to true, automatically prepend time to pages' filename, like <code>strange new -dt</code>. Default: <code>false</code> time: false</p> <p>paths: # Sets the path to the folder containing source files. Default: <code>src</code> src: src</p> <p># Sets the path to the destination where pages will be built files. Default: <code>build</code> dest: build</p> <p># Sets the path to the folder containing page templates. Default: <code>tpl</code> tpl: tpl</p> <p>serve: # Sets the IP address on which the <code>strange serve</code> command will start a webserver. Default: 127.0.0.1 ip: 127.0.0.1</p> <p># Sets the port on which the webserver will listen port: 9876</p> <p>plugins: data: dir: dataplugin rss: enabled: true filename: rss.xml num: 10 ```</p> <h2>Page templates</h2> <p>By default <em>strange</em>, during the <code>init</code> phase, only creates one page template, called <code>page.html.tera</code>, in the <code>tpl</code> directory.</p> <p>This is the default page template if a page does not request a different one, via the <code>layout</code> setting in the YAML prelude (see <a href="#create-a-new-page">Create a new page</a>).</p> <p>You can <strong>create new layout templates</strong> by creating new files in the tpl directory, by following a simple rule: if you want to be able to use, for example, <code>post</code> as a layout, create a file named <code>post.html.tera</code>, or <code>post.html.twig</code>, or <code>post.html.j2</code> to use a jinja2-style template, or <code>post.html.hbs</code> to use a handlebars-style template.</p> <p>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 <code>extends</code> command in jinja2-style templates.</p> <p>For example, you can have a <code>_base.html.tera</code> like this:</p> <p>```twig <!doctype html> <html> <head> {% block head %} <meta charset="utf-8"> <title>{% block title %}{{ title }}{% endblock title %} {% endblock head %}

{% block header %}

My site

{% endblock header %}

{% block main %}{{ body }}{% endblock main %}
```

and a page.html.tera like this:

```twig {% extends "_base.html" %}

{% block main %}

{{ title }}

{{ body }}
{% endblock main %} ```

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.

Placeholders

Most of the placeholders are available during the conversion from markdown/CommonMark to page HTML and during the handlebars templates to final HTML conversion.

Plugins

All plugins use some basic objects:

Page object

A page object contains meta-information about the page.

It contains all the values described in Placeholders except body, page and site

Date object

Contains information about a date:

Nav

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:

Example

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}}

Sitemap

This plugin provides a tree of all the pages in the site.

page.sitemap contains:

Example

In Tera:

```html

Sitemap pages

```

In Handlebars:

```html

Sitemap pages

```

Tag

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

Example

In Tera:

```html

Tags

```

In Handlebars:

```html

Tags

```

Data

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.

Example

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

Server

{{ site.data.server.url }}:{{ site.data.server.port }}

Me

HI, I'm {{ site.data.info.name }} and I live {{ site.data.info.address.street }}. ```

Configuration

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.

RSS

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:

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.

Example

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>

LICENSE

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/.

TODO