#template #fragment #engine #html #path #tags #split

template-fragments

template-fragments for jinja-like engines

1 unstable release

0.2.0 Jun 11, 2023

#399 in Template engine

MIT license

46KB
1K SLoC

Rust 1K SLoC // 0.0% comments Python 114 SLoC

template-fragments for jinja-like engines

Usage with minijinja (see also examples/minijinja.rs):

use template_fragments::{join_path, split_templates};

let mut source = minijinja::Source::new();

for (path, template) in  [
    ("index.html", include_str!("templates/index.html")),
    ("users.html", include_str!("templates/users.html")),
] {
    for (fragment_name, template_fragment) in split_templates(template)? {
        source.add_template(join_path(path, &fragment_name), &template_fragment)?;
    }
}

lib.rs:

Pre-process Jinja-like templates with fragment tags

template_fragments offers a way to split a template that is annotated with fragment tags ({% fragment NAME %}, {% endfragment %}) into fragments. For example:

<body>
# Header
{% fragment items %}
{% for item in items %}
    {% fragment item %}
        <div>{{ item }}</div>
    {% endfragment %}
{% endfor %}
{% endfragment %}
<body>

This template defines three fragments:

  • "": the whole template without any fragment markers
  • "items": the template looping over all items
  • "item": the innermost div

template_fragments offers two ways to pre-process such a template:

  • [filter_template]: given a fragment name, only return those parts of the template that belong to the fragment. This function is designed to be used when templates are requested dynamically
  • [split_templates]: split a template into all its fragments. This function is designed to be used when to extract all templates once at application startup

Syntax

  • Fragments start with {% fragment NAMES... %} or {% fragment-block NAMES %}
  • {% fragment-block NAME %} and {% endfragment-block %} define fragment blocks: they are rendered as a block, if the fragment is included. This is equivalent to wrapping a block with a fragment of the same name.
  • Fragments end with {% endfragment %} or {% endfragment-block %}
  • Fragments can occur multiple times in the document
  • Multiple fragments can be started in a single tag by using multiple whitespace separated names in the start tag
  • Fragment tags must be contained in a single line and there must not be any other non-whitespace content on the same line
  • Fragment names can contain any alphanumeric character and '-', '_'.

Example using minijinja

One way to use fragment tags with minijinja is to build a template source with the split templates at application start up like this

use template_fragments::{split_templates, join_path};

let mut source = minijinja::Source::new();

for (path, template) in [("index.html", include_str!("../examples/templates/index.html"))] {
    for (fragment_name, template_fragment) in split_templates(template)? {
        source.add_template(join_path(path, &fragment_name), &template_fragment)?;
    }
}

Note the different fragments can be rendered by requesting the relevant template, e.g., env.get_template("index.html") or env.get_template("index.html#fragment").

No runtime deps