Content Transformations
Converting pages to their output is done by filtering the content through the appropriate Glim::Filter
subclasses (provided by a plugin written in ruby).
A subclass needs to specify transforms
and implement the transform
method, for example to transform HAML to HTML we can write this subclass:
class HTMLAbstractionMarkupLanguage < Glim::Filter
transforms 'haml' => 'html'
def transform(content, page, options)
engine = Haml::Engine.new(content)
engine.render
end
end
In the above filter we change HAML into HTML but we can also write a filter that doesn’t change the format, for example we may allow our Markdown files to set references
in their front matter to a file that should be appended to the content before HTML conversion, this can be done as follows:
class AddReferencesToMarkdown < Glim::Filter
transforms 'markdown' => 'markdown'
def transform(content, page, options)
if path = page.data['references']
content + "\n\n" + File.read(path)
else
content
end
end
end
Glim will apply this filter before it applies the 'markdown' => 'html'
filter, as it wants to construct the longest chain of filters.
There are 3 default filters which transform:
'liquid' => '*'
: Expand liquid tags in the content.'markdown' => 'html'
: Convert to HTML using Kramdown.'*' => 'output'
: Wrap the content in the specified layout (read from_layouts/
).
It is possible to override these by creating a filter that declares the same transformation. In such override, it is possible to call super
in the transform
method to call on the next-best filter to handle the transformation. Filters each have a priority, the default is :normal
and all the default filters have :lower
, therefor a new filter will by default have higher priority than the default filters.
From the above we have 4 formats (liquid
, markdown
, html
, and output
) but formats can also have a subtype: When Glim loads a file it sets the format of that file to liquid.«extension»
, meaning that a file named main.css
gets assigned an initial format of liquid.css
.
The initial format can be explicitly set in the page’s front matter, e.g. setting format: css
will bypass expansion of liquid tags.
When a filter transforms something to *
then the output format will be the input format’s subtype. So in the case of main.css
where the input format is liquid.css
, Glim will apply the 'liquid' => '*'
filter and after that, the format will be css
and it will then look for a filter that can transform css
.
By default we have no filters for css
but we do have '*' => 'output'
so that filter will be used. When the input of a filter is *
then the output format’s subtype will be the input format’s main type.
That means in the case of our css
format, after filtering it through '*' => 'output'
the new format will be output.css
.
Giving an example of a markdown file the process looks as follows:
- Read
index.markdown
: Set format toliquid.markdown
. - Apply
liquid => *
: Format changed fromliquid.markdown
tomarkdown
. - Apply
markdown => html
: Format changed frommarkdown
tohtml
. - Apply:
* => output
: Format changed fromhtml
tooutput.html
. - No suitable filters for
output.html
, filtering complete.
It was previously said that the initial format is liquid.«extension»
but if there is a mapping of the extension to a format then we will use that first, which is how both index.md
and index.mdown
will get the same initial format of liquid.markdown
.
This mapping is provided by filters who use the extensions
class method, for example in the case of Markdown our subclass could look like this:
class MarkdownFilter < Glim::Filter
transforms 'markdown' => 'html'
extensions 'markdown' => %w( mkdown mkdn mkd md )
def transform(content, page, options)
…
end
end
What the above means is that the markdown
format should be used for files with any of the specified extensions. We leave out markdown
since files with markdown
extension already have the correct value for their format.