views:

98

answers:

1

I want to create a table of contents and endnotes in a Jinja2 template. How can one accomplish these tasks?

For example, I want to have a template as follows:

 {% block toc %}
 {# ... the ToC goes here ... #}
 {% endblock %}

 {% include "some other file with content.jnj" %}

 {% block endnotes %}
 {# ... the endnotes go here ... #}
 {% endblock %}

Where the some other file with content.jnj has content like this:

{% section "One" %}
Title information for Section One (may be quite long); goes in Table of Contents
...
Content of section One

{% section "Two" %}
Title information of Section Two (also may be quite long)

<a href="#" id="en1">EndNote 1</a> 
<script type="text/javsacript">...(may be reasonably long)
</script> {# ... Everything up to here is included in the EndNote #}

Where I say "may be quite/reasonably long" I mean to say that it can't reasonably be put into quotes as an argument to a macro or global function.

I'm wondering if there's a pattern for this that may accommodate this, within the framework of Jinja2.

My initial thought is to create an extension, so that one can have a block for sections and end-notes, like-so:

{% section "One" %}
Title information goes here.
{% endsection %}

{% endnote "one" %}
<a href="#">...</a>
<script> ... </script>
{% endendnote %}

Then have global functions (that pass in the Jinja2 Environment):

{{ table_of_contents() }}

{% include ... %}

{{ endnotes() }}

However, while this will work for endnotes, I'd presume it requires a second pass by something for the table of contents.

Thank you for reading. I'd be much obliged for your thoughts and input.

Brian

+1  A: 

Seems like you are heading down the right path in defining a consistent structure for each section (i.e title, body, endnotes). Would storing this information in regular Python data structures - rather than Jinja blocks and/or custom extensions - be acceptable? Example below.

in content.jnj:

{% set sections = [] %}
{% do sections.append({
'title': 'Section One title',
'body': 
"""
Section one main body text...
""",
'endnotes': 
"""
<a href='#'>...</a>
<script> ... </script>
""",
})
%}
{# append more sections #}

in template.jnj:

{% from 'content.jnj' import sections as sections %}
{# table of contents #}
{% for section in sections %}
    {{ loop.index }}. {{ section['title'] }}
{% endfor %}
{# body #}
{% for section in sections %}
    {{ section['title'] }}
    {{ section['body'] }}
{% endfor %}
{# endnotes #}
{% for section in sections %}
    {{ loop.index }}. {{ section['endnotes'] }}
{% endfor %}

Note that content.jnj requires the Jinja2 do extension to be enabled (e.g. env = jinja2.Environment(extensions=['jinja2.ext.do']).)

It may be overkill for your purposes, but another option is to store the content in a markup language, such as reStructuredText, and design the presentation layer as a Sphinx theme (Jinja2 is the default template format).

crewbum