The ginger package

[Tags:library, mit, program, test]

Ginger is Jinja, minus the most blatant pythonisms. Wants to be feature complete, but isn't quite there yet.


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.1.0, 0.1.1.1, 0.1.1.2, 0.1.2.0, 0.1.3.0, 0.1.4.0, 0.1.5.0, 0.1.6.0, 0.1.7.0, 0.1.8.0, 0.2.0.0, 0.2.1.0, 0.2.2.0, 0.2.3.0, 0.2.4.0, 0.2.5.0, 0.2.6.0, 0.2.7.0, 0.2.8.0, 0.3.0.0, 0.3.2.0, 0.3.5.0, 0.3.5.1, 0.3.5.3, 0.3.7.0, 0.3.7.1, 0.3.7.2, 0.3.8.0, 0.3.9.0, 0.3.9.1, 0.5.0.0, 0.5.1.0, 0.5.1.2 (info)
Change log CHANGELOG.md
Dependencies aeson, base (>=4.8 && <5), bytestring, data-default (>=0.5), filepath (>=1.3), ginger, http-types, mtl (>=2.2), parsec (>=3.0), safe (>=0.3), scientific (>=0.3), text, time (>=0.1.6.0), transformers (>=0.3), unordered-containers (>=0.2.5), utf8-string, vector [details]
License MIT
Author Tobias Dammers
Maintainer tdammers@gmail.com
Category Text
Home page https://bitbucket.org/tdammers/ginger
Bug tracker https://github.com/tdammers/ginger/issues
Uploaded Wed Feb 22 19:59:29 UTC 2017 by TobiasDammers
Distributions LTSHaskell:0.5.1.2, NixOS:0.5.1.2, Stackage:0.5.1.2, Tumbleweed:0.3.9.1
Downloads 1268 total (111 in the last 30 days)
Votes
0 []
Status Docs available [build log]
Last success reported on 2017-02-22 [all 1 reports]

Modules

[Index]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees

Readme for ginger

Readme for ginger-0.5.1.2

Ginger

Build Status Hackage

A Haskell implementation of the Jinja2 template language.

A note of warning: the git repository at https://bitbucket.org/tdammers/ginger has been deleted and restored with a rewritten commit tree on 2016-04-06 in order to clean up the messy history. This means that if you have a checkout from before that date, merging the bitbucket repo will most likely break things; please do a fresh clone to fix this. Sorry for the inconvenience.

Introduction

Ginger provides most of the original Jinja2 template language, as much as that makes sense in a Haskell host application.

We do, however, some of the most blatant Pythonisms, especially when we felt the features in question were more of an accidental result of binding template constructs to Python constructs.

On top of that, we deviate on a few points, and add some features that we think are very useful and help make the language better and more consistent.

Installation

Ginger is available from Hackage, and it is in Stackage, so you can use it in plain Cabal projects as well as Stack ones.

Installing with Cabal:

cabal install ginger

Installing with Stack:

stack install ginger

Using as part of another project:

Add the following to your .cabal's build-depends:

ginger >=0.3.9.1 && <0.4

Template Syntax

Full template syntax documentation is available from the /docs subdirectory in the project repository itself, or from the User Guide section on the Ginger website.

Minimal example template

<!DOCTYPE html>
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    {# This is a comment. Comments are removed from the output. #}
    <body>
        <menu id="nav-main">
        {% for item in navigation %}
            <li><a href="{{ item.url }}">{{ item.label }}</a></li>
        {% endfor %}
        </menu>
        <div class="layout-content-main">
            <h1>{{ title }}</h1>
            {{ body }}
        </div>
    </body>
</html>

There are two kinds of delimiters. {% ... %} and {{ ... }}. The first one is used to execute statements such as for-loops or assign values, the latter prints the result of an expression to the template.

Not implemented yet: Jinja2 allows the programmer to override the default tags from {% %} and {{ }} to different tokens, e.g. <% %> and << >>. Ginger does not currently support this.

Haskell API

The Haskell API is documented fully through Haddock documentation, available from Hackage. We'll just provide a short overview here.

General

On the Haskell side of things, executing a template is a two-step process. First, template source code is parsed into a 'Template' data structure, which is then fed to 'runGinger' or 'runGingerT'.

Parsing

Because Ginger templates can include other templates, the parser needs a way of resolving template names. Instead of hard-wiring the parser into 'IO' though, Ginger will work on any Monad type, but requires the caller to provide a suitable template resolver function. For 'IO', the resolver would typically load a file from a template directory, but other monads might have access to some sort of cache, or expose template compiled into a program, or simply return 'Nothing' unconditionally to disable any and all imports. A suitable example implementation for 'IO' would look like this:

loadFile fn = openFile fn ReadMode >>= hGetContents

loadFileMay fn =
    tryIOError (loadFile fn) >>= \e ->
         case e of
            Right contents ->
                return (Just contents)
            Left err -> do
                print err -- remove this line if you want to fail silently
                return Nothing

(Taken from cli/GingerCLI.hs). This interprets the template name as a filename relative to the CWD, and returns the file contents on success or 'Nothing' if there is any error.

If you don't need a monadic context for resolving includes (e.g. because you have pre-loaded all template sources), you can use the pure 'parseGinger' flavor, which does not rely on a host monad.

Running

The core function for running a template is 'runGinger' (or its monadic flavor 'runGingerT'); in order to pass an initial context to the template engine, pass a suitable 'GingerContext', which you can create using the 'makeContext' / 'makeContextM' functions.

An example call (for running a template in 'IO') would look something like this:

runGingerT (makeContextM scopeLookup (putStr . Text.unpack . htmlSource)) tpl