ErlyDTL Build Status

ErlyDTL compiles Django Template Language to Erlang bytecode.

Project homepage: https://github.com/erlydtl/erlydtl/wiki

ErlyDTL implements the Django Template Language as documented for version 1.6, here: https://django.readthedocs.org/en/1.6.x/ref/templates/builtins.html

Despite our best efforts to be completely compatible with the Django Template Languge, there are still a few differences.

Call for maintainers

My current position in life does not give me the time I feel this project deserves. So, if you feel that there are things that ought to be done, and have the skills and time to do them, please get in touch. – @kaos

The erlydtl branches & tags

We follow a gitflow inspired branching model, where master is the latest released version (a.k.a. stable), and use develop for stuff that may break from time to time.

master branch

Releases are made from the master branch, with dependency versions pinned down and a hard coded version number in the app file.

develop branch

This is were all the action is, and at times may be slightly broken. Suitable for early adopters who aren’t afraid of a little debugging and hopefully also reporting issues.

release tags

Whenever master is deemed stable with a nice set of additions/changes, it is tagged for a new release.

As we’re still going for the big 1.0 release, breaking changes may be introduced also on minor release bumps; but after that, we’ll stick with semver.

Compilation

To compile ErlyDTL, run

make

in this directory.

Do not use Erlang R16B03

The erl syntax tools is broken in Erlang R16B03, use R16B03-1 or any other supported version instead.

Do use a recent version of rebar

In case of compilation issues, make sure your version of rebar is up-to-date.

Older versions of rebar does not support the raw option for dependencies, and may produce an error message like this:

ERROR: Invalid dependency specification {merl,".*",
                                         {git,
                                          "git://github.com/erlydtl/merl.git",
                                          "28e5b3829168199e8475fa91b997e0c03b90d280"},
                                         [raw]} 

Template compilation

Usage:

erlydtl:compile_file("/path/to/template.dtl", my_module_name)

erlydtl:compile_file("/path/to/template.dtl", my_module_name, Options)

erlydtl:compile_template("<html>{{ foo }}</html>", my_module_name)

erlydtl:compile_template("<html>{{ foo }}</html>", my_module_name, Options)

Result:

{ok, Module}
{ok, Module, Warnings}
{ok, Module, Binary}
{ok, Module, Binary, Warnings}

error
{error, Errors, Warnings}

Options is a proplist possibly containing:

Helper compilation

Helpers provide additional templating functionality and can be used in conjunction with the custom_tags_module option above. They can be created from a directory of templates thusly:

erlydtl:compile_dir("/path/to/dir", my_helper_module_name)

erlydtl:compile_dir("/path/to/dir", my_helper_module_name, Options)

The resulting module will export a function for each template appearing in the specified directory. Options is the same as for compile/3.

Compiling a helper module can be more efficient than using custom_tags_dir because the helper functions will be compiled only once (rather than once per template).

Notice: The exported template functions return an iolist() on success only, failures are non-local (e.g. as a throw). To get the result in wrapped tuple {ok, iolist()} | {error, Reason} call one of the render functions: render(Tag) | render(Tag, Vars) | render(Tag, Vars, Opts).

Usage (of a compiled template)

render/1

my_compiled_template:render(Variables) -> {ok, IOList} | {error, Err}

Variables is a proplist, dict, gb_tree, or a parameterized module (whose method names correspond to variable names). The variable values can be atoms, strings, binaries, or (nested) variables.

IOList is the rendered template.

render/2

my_compiled_template:render(Variables, Options) -> {ok, IOList} | {error, Err}

Same as render/1, but with the following options:

translatable_strings/0

my_compiled_template:translatable_strings() -> [String]

List of strings appearing in {% trans %} and _(..) tags.

translated_blocks/0

my_compiled_template:translated_blocks() -> [String]

List of strings appearing in {% blocktrans %}...{% endblocktrans %} blocks; the translations (which can contain ErlyDTL code) are hard-coded into the module and appear at render-time. To get a list of translatable blocks before compile-time, use the provided blocktrans_extractor module.

source/0

my_compiled_template:source() -> {FileName, CheckSum}

Name and checksum of the original template file.

dependencies/0

my_compiled_template:dependencies() -> [{FileName, CheckSum}]

List of names/checksums of templates included by the original template file. Useful for frameworks that recompile a template only when the template’s dependencies change.

variables/0

my_compiled_template:variables() -> [Variable::atom()]

Sorted list of unique variables used in the template’s body. The list can be used for determining which variable bindings need to be passed to the render/3 function.

default_variables/0

my_compiled_template:default_variables() -> [Variable::atom()]

Like variables/0, but for any variable which have a default value provided at compile time.

constants/0

my_compiled_template:constants() -> [Variable::atom()]

Like default_variables/0, but these template variables has been replaced with a fixed value at compile time and can not be changed when rendering the template.

Custom tags and filters

Starting with release 0.9.1, the recommended way to add custom tags and filters are to register a module implementing the erlydtl_library behaviour. There are two functions needed to implement a custom library: version/0 and inventory/1.

The version/0 function is to be able to keep backwards compatibility in face of an evolving library behaviour, and should return the version of the behaviour the library supports. The valid range of versions is in the spec for the version/0 callback in erlydtl_library.erl.

Library version 1

The inventory/1 function is called with either filters or tags as argument, and should return a list of all filters or tags available in that library, respectively (see spec in erlydtl_library.erl for details on syntax for this list).

Tag functions must take a list of arguments, and may take a list of render options, and should return an iolist() as result value (see custom_tags_modules compile option).

Filter functions must take an iolist() value to filter, and may take an argument, and should return an iolist() as result value (see custom_filters_modules compile option).

Differences from standard Django Template Language

Tests

From a Unix shell, run:

make tests

Note that the tests will create some output in tests/output in case of regressions.

License

ErlyDTL is released under the MIT license.