Clean up theme docs and add overview.

This commit is contained in:
Brit Butler 2013-04-28 16:12:08 -04:00
parent 77d1881927
commit 5f76d94e42
2 changed files with 220 additions and 316 deletions

56
docs/overview.md Normal file
View file

@ -0,0 +1,56 @@
## Overall Structure
Conceptually, coleslaw processes a blog as follows:
1. Coleslaw loads the user's config, then reads a directory containing
`.post` files and processes them into POST and INDEX objects.
2. The POST and INDEX objects are then fed to the templating engine
to produce HTML files.
3. A deploy method is called (possibly customized with plugins) to make
the resulting HTML files (and any static content) visible to the web.
## What files are generated anyway?
Before we dive into other details, it is useful to know the directory
structure of the generated content, so you know how the relative path
different content resides at.
The blog's toplevel looks like this:
```
index.html
posts/
date/
tag/
css/
static/ (optional)
```
### index.html
This file is the blog homepage, as you'd expect. It contains a list of
the most recent posts and has links to the different archives.
### posts directory
This directory contains an `.html` file per post. The name of the file
is the post's `slug`.
### date directory
This directory contains an `.html` file per month, for each month with
published content. The name of the file is of the form `yyyy-mm.html`.
### tag directory
This directory contains an `.html` file per tag, each containing all
posts with that tag. The name of the file is the tag's `slug`.
### css directory
This directory is a copy of the `css/` folder of the theme.
### static directory (optional)
This directory is a copy of the `static/` directory of the blog's git repo.

View file

@ -1,377 +1,225 @@
# Themes
The theming support in coleslaw is very flexible, and relatively easy
to use. However it does require some knowledge of HTML, CSS and
[Closure Templates][clt], and of course how coleslaw converts
posts into a collection of HTML files.
The theming support in coleslaw is very flexible and relatively easy
to use. However it does require some knowledge of HTML, CSS, and how
coleslaw processes content.
This document will focus mainly on the part of how coleslaw converts
posts into a blog, and how you can influence the resulting HTML.
To understand how coleslaw processes a blog, a look at the [overview][ovr]
documentation may prove useful. This document will focus mainly on the
template engine and how you can influence the resulting HTML.
## Overall Structure
**NOTE**: Themes are not able to change the generated file names or the
generated file structure on disk. They can change the resulting HTML, nothing more.
Conceptually the process of creating a blog with coleslaw is the following:
## High-Level Overview
1. Coleslaw read a directory containt `.post` files and processes them
into HTML fragments.
Themes are written using [Closure Templates][clt]. Those templates are
then compiled into functions that Lisp calls with the blog data to get
HTML. Since the Lisp code to use theme functions is already written,
your theme must follow a few rules.
2. The HTML fragments of the posts are processed with the templating engine,
to produce different HTML files.
Every theme **must** be in a folder under "themes/" named after the
theme. The theme's templates must start with a namespace declaration
like so: `{namespace coleslaw.theme.$MY-THEME-NAME}`.
And for theming purposes, an important final step
A theme must have three templates which take *specific arguments*
(to be described later).
1. Base
2. Post
3. Index
3. A browser renders the generated HTML and styles it with CSS.
## Two types of pages
The first step, the translation from markdown to HTML fragments is fixed, you cannot
really influence that in a (theming) meaningful way.
Coleslaw generates two types of pages: `index` pages and `post` pages.
Every page other than those in the `posts/` directory is an `index`.
**Every** page uses the `base.tmpl` and fills in the content using
either the `post` or `index` templates.
The theming is done in the last two steps, the templating and the CSS.
* `base.tmpl` This template generates the outer shell of the HTML.
It keeps a consistent look and feel for all pages in the blog. The
actual content (i.e., not header/footer/css) comes from other templates.
Now both steps have a different role:
* `index.tmpl` This template generates the content of the `index` pages.
That is, any page with more than one content object, e.g. the homepage.
1. **Templating**, this determines the file structure of the
generated HTML. This part inserts headers, footers, include
the CSS stylesheets and other resources.
* `post.tmpl` This templates generates content for the individual posts.
Coleslaw already converts the content of the individual post to HTML
by using markdown (or RST). So this template is **not** used to
convert an individual post, merely to give it a standard layout.
This is also the place where you can add for example a table of contents
of the posts, or where the list of tags will be inserted etc.
Here's a visual example to make things clearer:
```
INDEX HTML FILES INDIVIDUAL POST HTML FILES
|-------------------------| |-------------------------|
| base.tmpl | | base.tmpl |
| | | |
| |-------------------| | | |------------------| |
| | index.tmpl | | | | post.tmpl | |
| | | | | | | |
| |-------------------| | | |------------------| |
| | | |
|-------------------------| |-------------------------|
```
Also, very importantly, by generating the right HTML `<div>` elements
it will make it easy to style the resulting HTML with CSS.
2. **CSS**, this is the part which will determine the look of all the components.
For example the font and font size of the titles and sub titles.
But *CSS* is very well covered in the literature and we will not
cover how to use *CSS* in this document. But it is good to remember that
if you are struggling to achieve a certain effect with CSS, it might
be easy to solve by modifying the template. Either by changing the structure
of the document or by adding the right `id` or `class` attributes.
**NOTE** It is not possible to change the generated file names or the generated
file structure on disk. The templating/theming support allows changing the resulting
HTML but nothing more.
## What Files are generated anyway?
Before we dive into the templating itself, it is important to know the
directory structure of the generated content, because when writing a
template you need to be aware of how coleslaw lays out the blog on disk.
The toplevel looks like this:
index.html
posts/
tags/
date/
static/
css/
### index.html
This file is the front page of the blog. It contains a list of the most recent posts and
has links to the different archives.
### posts directory
This directory contains an `.html` file per post. The name of the file
is the `slug` of the post.
### tags directory
This directory contains an `.html` file per tag. Such a file contains
all posts which contain the tag. The name of a tag file is the `slug` of the tag.
### date directory
This directory contains files of the form `yyyy-mm.html` with `yyyy`
the year as a 4 digit number and `mm` as a two digit month number.
These files contain all the posts of the indicated month.
### static directory
This directory is a copy of the `static/` directory of the source folder of coleslaw.
### css directory
This directory is a copy of the `css/` folder of the theme.
## Two type of HTML files
Coleslaw generate two types of HTML files: `index` files and `post` files.
Except for the files in the `posts/` directory all files are `index` files.
The HTML files, as mentioned before, are created by filling in the [Closure Templates] [clt].
And to generate all the HTML files there are three templates relevant:
* `base.tmpl` This template generates the outer shell of the HTML. This is used
to generate a consist look and feel and structure for all pages in the blog.
The actual content (besides fixed headers and footers etc.) is generated by one of the
other two templates
* `index.tmpl` This template generates the content of the `index` files, remember,
these are all files containing more than one post, so including the front page.
* `post.tmpl` This generates the HTML files for the individual posts.
Remember that Coleslaw already converts the content of the individual
post to HTML by using markdown (or ReST). So this template is NOT
used to format or convert an individual post. This template is used
to create the HTML containing that post
Visual it might be clearer this way:
INDEX HTML FILES INDIVIDUAL POST HTML FILES
|-------------------------| |-------------------------|
| base.tmpl | | base.tmpl |
| | | |
| |-------------------| | | |------------------| |
| | index.tmpl | | | | post.tmpl | |
| | | | | | | |
| |-------------------| | | |------------------| |
| | | |
|-------------------------| |-------------------------|
## Note on Style Sheets (css)
If you only want to change the way the blog is styled, it is probably
simplest to either modify the existing default theme, `hyde`, or copy
it in entirety and then tweak only the CSS of your new theme. A large
amount of visual difference can be had with a minimum of (or no)
template hacking. There is plenty of advice on CSS styling on the web.
I'm no expert but feel free to send patches to hyde's `style.css` or a
recommended CSS resource for this guide.
## Creating a Theme from Scratch (with code)
### Step 1. Pick a name
### Step 1. Create the directory.
A theme name should satisfy two conditions:
A theme name must be a valid lisp symbol. For this example, we'll use
`trivial`, so create a `themes/trivial` directory in the *coleslaw* repo.
1. It is a valid lisp symbol name (not containing `:`)
2. It is a valid directory name.
### Step 2. Create the templates.
So for this example lets pick `trivial`.
### Step 2. Create the right directory
Now we need to create a directory containing the theme files.
In the coleslaw system directory should be a directory called `themes/`.
The directory for the theme files is a sub directory of the `themes/` directory,
named after the theme name we picked in step 1.
So in our case, we have to create the directory `themes/trivial/`.
### Step 3. Create the 3 template files
As described above, we need the 3 template files `base.tmpl`, `post.tmpl` and `index.tmpl`.
Before we customize them, create the with the following content:
As described above, we need 3 template files `base.tmpl`, `post.tmpl`
and `index.tmpl`. Initially, let's just create the simplest theme that
compiles correctly.
base.tmpl:
{namespace coleslaw.theme.trivial}
{template base}
{/template}
```
{namespace coleslaw.theme.trivial}
{template base}
{/template}
```
post.tmpl:
```
{namespace coleslaw.theme.trivial}
{template post}
{/template}
```
index.tmpl:
```
{namespace coleslaw.theme.trivial}
{template index}
{/template}
```
post.tmpl
This will create three template functions that coleslaw can find, named
`base`, `post`, and `index`.
{namespace coleslaw.theme.trivial}
{template post}
{/template}
index.tmpl
{namespace coleslaw.theme.trivial}
{template index}
{/template}
The first line in these files, declares the namespace of the template. The namespace must be
`coleslaw.theme.` followed by the theme name.
The remaining two lines `{template ...}{/template ...}` create the empty templates.
### Step 4. Test
This is enough to make coleslaw happy. You can now use the new `trivial` theme in coleslaw
by changing the `:theme` in `.coleslawrc` file to `trivial`.
If you do this and generate the blog with `(coleslaw:main "")`, coleslaw will not complain
and generate all the post files, tag files and front page files as normal. Except that all
these files are empty.
The HTML files are empty because the templates are empty.
### Step 5. Generating valid HTML
The `base.tmpl` generates all the HTML pages, so if we change the base template to:
{namespace coleslaw.theme.trivial}
{template base}
<html>
<head><title>Trivial Theme For Coleslaw</title></head>
<body>
<h1>All my pages have this title</h1>
</body>
</html>
{/template}
We will generate valid HTML. Of course every page is still the same, but at least
it shows that the templating engine works.
### Step 3. Use it in your config.
At this point, you can change the `:theme` in your `.coleslawrc` to
`trivial` and then generate your blog with `(coleslaw:main)`. However,
all the HTML files will be empty because our templates are empty!
### Intermezzo I, The Templating Language
The templating language is documented at [Google closure templates][clt].
The templating language is documented [elsewhere][clt].
However as a short primer:
* Everyting is outputed literally, except template commands
* Template commands are enclosed in `{` and `}`
* Variables, which are provided by coleslaw are referenced
as `$variable.key` inside a template command.
So to insert a variable you have to use `{$variable.key}`.
* Everything is output literally, except template commands.
* Template commands are enclosed in `{` and `}`
* Variables, which are provided by coleslaw, can be referenced
inside a template command. So to use a variable you have to say
`{$variable}` or `{$variable.key}`.
* If statements are written as `{if ...} ... {else} ... {/if}`.
Typical examples are: `{if $injections.body} ... {/if}` or
`{if not isLast($link)} ... {/if}`.
* Loops can be written as `{foreach $var in $sequence} ... {/foreach}`.
Variables are either simple variables, which are referenced as `{$var}`
Or are indexed by a key and written as `{$var.key}`.
* If statements are written as
{if ...} ... {else} ... {/if}
Typical examples are:
{if $injections.body} ... {/fi}
Or
{if not isLast($link)} ... {/fi}
* Loops are typically written as
{foreach $var in $index.posts} ... {/foreach}
### Intermezzo II, Variables provided by coleslaw
### Intermezzo II, Variables provided by Coleslaw
The variable that is available in all templates is:
- **config** This contains the .coleslawrc content
- **config** This contains the `.coleslawrc` content.
#### Base Template Variables
- **raw** the HTML generated by the sub templates, `index.tmpl` or `post.tmpl`
- **content** the data which was used to generate **raw** HTML.
- **pubdate** A string containing the publication date
- **injections** A list containg all injections. Injections are for the plugins to
communicate additional content to be included.
- **raw** HTML generated by a sub template, `index` or `post`.
- **content** The object which was used to generate **raw**.
- **pubdate** A string containing the publication date.
- **injections** A list containing the injections. Injections are used
by plugins mostly to add Javascript to the page.
#### Index Template Variables
- **tags** A list containing all the tags, A tag has values `.name` and `.slug`.
- **months** A list of all months for which there are posts. This is a list
of strings. The strings are formatted as `yyyy-mm`.
- **index** This is the meat of the content. This variable has as keys
- **tags** A list containing all the tags, each with keys
`.name` and `.slug`.
- **months** A list of all months with posts as `yyyy-mm` strings.
- **index** This is the meat of the content. This variable has
the following keys
- `id`, the name of the page that will be rendered
- `posts` a list of posts (see below)
- `title` The title under which this index is know. This should be used
to display a title for the user.
- `posts`, a list of posts (see below)
- `title`, a string title to display to the user
- **prev** If this index file is part of a chain, the `id`
of the previous index html in the chain.
If this is the first file, the value will be empty.
If this is the first file, the value will be empty.
- **next** If this index file is part of a chain, the `id`
of the next index html in the chain.
If this is the last file, the value will be empty.
If this is the last file, the value will be empty.
#### Post Template Variable
- **prev**
- **next**
- **post** All these variables are of the same type, they represent a post.
The **prev** and **next** are the post before this one, or the one
after this one when put in chronological order.
These variables have the following keys
- `tags` a list of tags (a tag has keys `name` and `slug`)
- `slug` the slug of the post
- `date` the date of posting
- `text` the HTML version of the posts body.
- `title` The title of the post
- **prev**
- **next**
- **post** All these variables are post objects. **prev** and
**next** are the adjacent posts when put in
chronological order. Each post has the following keys:
- `tags`, a list of tags (each with keys `name` and `slug`)
- `slug`, the slug of the post
- `date`, the date of posting
- `text`, the HTML of the post's body
- `title`, the title of the post
### Step 6. Including the content
### Step 4. Include the content
We improve the `base.tmpl` to include the content generated by the sub templates.
This is done by adding the line `{$raw |noAutoescape}` to the template in the body section.
*NOTE*: We can keep the template engine from escaping raw HTML by
adding a `|noAutoescape` clause to commands, like so: `{$raw |noAutoescape}`.
The `|noAutoescape` is added because the `$raw` variable is already html and we do
not want the templating engine to escape the html.
Let's now rewrite `base.tmpl` like this:
```
{namespace coleslaw.theme.trivial}
{template base}
<html>
<head><title>Trivial Theme For Coleslaw</title></head>
<body>
<h1>All my pages have this title</h1>
{$raw |noAutoescape}
</body>
</html>
{/template}
```
So the `base.tmpl` now looks like this:
A simple `index.tmpl` looks like this:
```
{namespace coleslaw.theme.trivial}
{template index}
{foreach $post in $index.posts}
<h1>{$post.title}</h1>
{$post.text |noAutoescape}
{/foreach}
{/template}
```
{namespace coleslaw.theme.trivial}
{template base}
And a simple `post.tmpl` is similarly:
```
{namespace coleslaw.theme.trivial}
{template post}
<h1>{$post.title}</h1>
{$post.text |noAutoescape}
{/template}
```
<html>
<head><title>Trivial Theme For Coleslaw</title></head>
<body>
<h1>All my pages have this title</h1>
{$raw |noAutoescape}
</body>
</html>
{/template}
If we run this through coleslaw we do not see any difference and this is because
we have not modified the `index.tmpl` and the `post.tmpl`.
A simple `index.tmpl` looks like this
{namespace coleslaw.theme.trivial}
{template index}
{foreach $post in $index.posts}
<h1>{$post.title}</h1>
{$post.text |noAutoescape}
{/foreach}
{/template}
And a simple `post.tmpl` is similarly
{namespace coleslaw.theme.trivial}
{template post}
<h1>{$post.title}</h1>
{$post.text |noAutoescape}
{/template}
### Wrapup of Example
Basically all the files are now populated with content. There are a few huge gaps still, for example there is no
linking between the pages. So although the archives are fully populated, you cannot get there from the
front page, but if you know the URL it is there.
However linking is not very difficult see next section.
### Conclusion
All of the files are now populated with content. There are still no links
between the pages so navigation is cumbersome but adding links is simple.
Good luck!
## Note on adding links
As mentioned in the beginning, most files have a file name which is a slug of some sort. So if you want to create a link
to a tag file you should do something like this:
<a href="${config.domain}/tags/$tag.slug">$tag.name</a>
## Note on adding style sheets
Style sheets are nothing special. In order to get them to work, you
have to add a `css` folder in your theme folder. The content of this folder
will be copied to the `css` folder at the place where the `html` is generated.
Now to actual use them, you have to include in the head section of the html
(which is in the `base.tmpl`) a link to include the CSS.
As mentioned earlier, most files have a file name which is a slug of
some sort. So if you want to create a link to a tag file you should
do something like this: `<a href="${config.domain}/tags/$tag.slug">$tag.name</a>`.
[clt]: https://developers.google.com/closure/templates/
[ovr]: https://github.com/redline6561/coleslaw/blob/master/docs/overview.md