[svn] add first part of jinja documentation
--HG--
branch : trunk
diff --git a/docs/build/jinjabanner.png b/docs/build/jinjabanner.png
new file mode 100644
index 0000000..c672118
--- /dev/null
+++ b/docs/build/jinjabanner.png
Binary files differ
diff --git a/docs/build/jinjalogo.png b/docs/build/jinjalogo.png
new file mode 100644
index 0000000..17d6dc3
--- /dev/null
+++ b/docs/build/jinjalogo.png
Binary files differ
diff --git a/docs/build/style.css b/docs/build/style.css
new file mode 100644
index 0000000..64cba24
--- /dev/null
+++ b/docs/build/style.css
@@ -0,0 +1,196 @@
+body {
+ background-color: #333;
+ margin: 0;
+ padding: 0;
+ font-family: 'Georgia', serif;
+ font-size: 15px;
+ color: #111;
+}
+
+#content {
+ background-color: white;
+ background-image: url(watermark.png);
+ padding: 10px;
+ margin: 25px;
+ border: 4px solid #ddd;
+}
+
+h1 {
+ margin: 0;
+ padding: 0;
+ height: 80px;
+ background-image: url(jinjabanner.png);
+ background-repeat: no-repeat;
+}
+
+h1 span {
+ display: none;
+}
+
+h2.subheading {
+ margin: -55px 0 35px 200px;
+ font-weight: normal;
+ font-size: 30px;
+ color: #444;
+}
+
+h2.plain {
+ margin: 0;
+}
+
+#jinjalogo {
+ background-image: url(jinjalogo.png);
+ background-repeat: no-repeat;
+ width: 400px;
+ height: 160px;
+}
+
+#contentwrapper {
+ max-width: 700px;
+ padding: 0 0 20px 18px;
+}
+
+#contentwrapper h3,
+#contentwrapper h3 a {
+ color: #b41717;
+ font-size: 26px;
+ margin: 20px 0 0 -5px;
+}
+
+#contentwrapper h4,
+#contentwrapper h4 a {
+ color: #b41717;
+ font-size: 20px;
+ margin: 20px 0 0 0;
+}
+
+table.docutils {
+ border-collapse: collapse;
+ border: 2px solid #aaa;
+ margin: 0.5em 1.5em 0.5em 1.5em;
+}
+
+table.docutils td {
+ padding: 2px;
+ border: 1px solid #ddd;
+}
+
+p, li, dd, dt, blockquote {
+ color: #333;
+}
+
+p {
+ line-height: 150%;
+ margin-bottom: 0;
+ margin-top: 10px;
+ text-align: justify;
+}
+
+hr {
+ border-top: 1px solid #ccc;
+ border-bottom: 0;
+ border-right: 0;
+ border-left: 0;
+ margin-bottom: 10px;
+ margin-top: 20px;
+}
+
+dl {
+ margin-left: 10px;
+}
+
+li, dt {
+ margin-top: 5px;
+}
+
+dt {
+ font-weight: bold;
+}
+
+th {
+ text-align: left;
+ padding: 3px;
+ background-color: #f2f2f2;
+}
+
+a {
+ color: #b41717;
+}
+
+a:hover {
+ color: #444;
+}
+
+pre {
+ background-color: #f9f9f9;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ padding: 5px;
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+}
+
+tt {
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ color: black;
+ padding: 1px 2px 1px 2px;
+ background-color: #f0f0f0;
+}
+
+cite {
+ /* abusing <cite>, it's generated by ReST for `x` */
+ font-size: 13px;
+ font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace;
+ font-weight: bold;
+ font-style: normal;
+}
+
+div.admonition {
+ margin: 10px 0 10px 0;
+ padding: 10px;
+ border: 1px solid #ccc;
+ background-color: #f8f8f8;
+}
+
+div.admonition p.admonition-title {
+ margin: -3px 0 5px 0;
+ font-weight: bold;
+ color: #b41717;
+ font-size: 16px;
+}
+
+div.admonition p {
+ margin: 0 0 0 40px;
+}
+
+#toc {
+ margin: 0 -10px 10px 15px;
+ padding: 10px;
+ width: 200px;
+ float: right;
+ background-color: #f8f8f8;
+ border: 1px solid #ccc;
+ border-right: none;
+}
+
+#toc h2 {
+ font-size: 20px;
+ margin: 0 0 10px 0;
+ padding: 0;
+ color: #444;
+}
+
+#toc ul {
+ margin: 0 0 0 30px;
+ padding: 0;
+}
+
+#toc ul + h2 {
+ margin-top: 10px;
+}
+
+#toc ul li {
+ padding: 0;
+ margin: 2px 0 2px 0;
+}
diff --git a/docs/build/watermark.png b/docs/build/watermark.png
new file mode 100644
index 0000000..297d899
--- /dev/null
+++ b/docs/build/watermark.png
Binary files differ
diff --git a/docs/generate.py b/docs/generate.py
new file mode 100755
index 0000000..0c155c0
--- /dev/null
+++ b/docs/generate.py
@@ -0,0 +1,275 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ Generate Jinja Documentation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Generates a bunch of html files containing the documentation.
+
+ :copyright: 2006-2007 by Armin Ronacher, Georg Brandl.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
+import re
+import inspect
+from datetime import datetime
+from cgi import escape
+
+from docutils import nodes
+from docutils.parsers.rst import directives
+from docutils.core import publish_parts
+from docutils.writers import html4css1
+
+from jinja import Environment
+
+from pygments import highlight
+from pygments.lexers import get_lexer_by_name
+from pygments.formatters import HtmlFormatter
+
+def generate_list_of_filters():
+ from jinja.filters import FILTERS
+ result = []
+
+ filters = {}
+ for name, f in FILTERS.iteritems():
+ if not f in filters:
+ filters[f] = ([name], inspect.getdoc(f))
+ else:
+ filters[f][0].append(name)
+ for names, _ in filters.itervalues():
+ names.sort(key=lambda x: -len(x))
+
+ for names, doc in sorted(filters.values(), key=lambda x: x[0][0].lower()):
+ name = names[0]
+ if len(names) > 1:
+ aliases = '\n\n :Aliases: %s\n' % ', '.join(names[1:])
+ else:
+ aliases = ''
+
+ doclines = []
+ for line in doc.splitlines():
+ doclines.append(' ' + line)
+ doc = '\n'.join(doclines)
+ result.append('`%s`\n%s%s' % (name, doc, aliases))
+
+ return '\n'.join(result)
+
+def generate_list_of_tests():
+ from jinja.tests import TESTS
+ result = []
+
+ tests = {}
+ for name, f in TESTS.iteritems():
+ if not f in tests:
+ tests[f] = ([name], inspect.getdoc(f))
+ else:
+ tests[f][0].append(name)
+ for names, _ in tests.itervalues():
+ names.sort(key=lambda x: -len(x))
+
+ for names, doc in sorted(tests.values(), key=lambda x: x[0][0].lower()):
+ name = names[0]
+ if len(names) > 1:
+ aliases = '\n\n :Aliases: %s\n' % ', '.join(names[1:])
+ else:
+ aliases = ''
+
+ doclines = []
+ for line in doc.splitlines():
+ doclines.append(' ' + line)
+ doc = '\n'.join(doclines)
+ result.append('`%s`\n%s%s' % (name, doc, aliases))
+
+ return '\n'.join(result)
+
+def generate_list_of_loaders():
+ from jinja import loaders as loader_module
+
+ result = []
+ loaders = []
+ for item in loader_module.__all__:
+ loaders.append(getattr(loader_module, item))
+ loaders.sort(key=lambda x: x.__name__.lower())
+
+ for loader in loaders:
+ doclines = []
+ for line in inspect.getdoc(loader).splitlines():
+ doclines.append(' ' + line)
+ result.append('`%s`\n%s' % (loader.__name__, '\n'.join(doclines)))
+
+ return '\n\n'.join(result)
+
+e = Environment()
+
+PYGMENTS_FORMATTER = HtmlFormatter(style='pastie', cssclass='syntax')
+
+LIST_OF_FILTERS = generate_list_of_filters()
+LIST_OF_TESTS = generate_list_of_tests()
+LIST_OF_LOADERS = generate_list_of_loaders()
+
+TEMPLATE = e.from_string('''\
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>{{ title }} — Jinja Documentation</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="style.css" type="text/css">
+ <style type="text/css">
+ {{ style|e }}
+ </style>
+</head>
+<body>
+ <div id="content">
+ {% if file_id == 'index' %}
+ <div id="jinjalogo"></div>
+ <h2 class="subheading plain">{{ title }}</h2>
+ {% else %}
+ <h1 class="heading"><span>Jinja</span></h1>
+ <h2 class="subheading">{{ title }}</h2>
+ {% endif %}
+ {% if file_id != 'index' or toc %}
+ <div id="toc">
+ <h2>Navigation</h2>
+ <ul>
+ <li><a href="index.html">back to index</a></li>
+ </ul>
+ {% if toc %}
+ <h2>Contents</h2>
+ <ul class="contents">
+ {% for key, value in toc %}
+ <li><a href="{{ key }}">{{ value }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+ {% endif %}
+ <div id="contentwrapper">
+ {{ body }}
+ </div>
+ </div>
+</body>
+<!-- generated on: {{ generation_date }}
+ file id: {{ file_id }} -->
+</html>\
+''')
+
+def pygments_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ try:
+ lexer = get_lexer_by_name(arguments[0])
+ except ValueError:
+ # no lexer found
+ lexer = get_lexer_by_name('text')
+ parsed = highlight(u'\n'.join(content), lexer, PYGMENTS_FORMATTER)
+ return [nodes.raw('', parsed, format="html")]
+pygments_directive.arguments = (1, 0, 1)
+pygments_directive.content = 1
+directives.register_directive('sourcecode', pygments_directive)
+
+
+def create_translator(link_style):
+ class Translator(html4css1.HTMLTranslator):
+ def visit_reference(self, node):
+ refuri = node.get('refuri')
+ if refuri is not None and '/' not in refuri and refuri.endswith('.txt'):
+ node['refuri'] = link_style(refuri[:-4])
+ html4css1.HTMLTranslator.visit_reference(self, node)
+ return Translator
+
+
+class DocumentationWriter(html4css1.Writer):
+
+ def __init__(self, link_style):
+ html4css1.Writer.__init__(self)
+ self.translator_class = create_translator(link_style)
+
+ def translate(self):
+ html4css1.Writer.translate(self)
+ # generate table of contents
+ contents = self.build_contents(self.document)
+ contents_doc = self.document.copy()
+ contents_doc.children = contents
+ contents_visitor = self.translator_class(contents_doc)
+ contents_doc.walkabout(contents_visitor)
+ self.parts['toc'] = self._generated_toc
+
+ def build_contents(self, node, level=0):
+ sections = []
+ i = len(node) - 1
+ while i >= 0 and isinstance(node[i], nodes.section):
+ sections.append(node[i])
+ i -= 1
+ sections.reverse()
+ toc = []
+ for section in sections:
+ try:
+ reference = nodes.reference('', '', refid=section['ids'][0], *section[0])
+ except IndexError:
+ continue
+ ref_id = reference['refid']
+ text = escape(reference.astext().encode('utf-8'))
+ toc.append((ref_id, text))
+
+ self._generated_toc = [('#%s' % href, caption) for href, caption in toc]
+ # no further processing
+ return []
+
+
+def generate_documentation(data, link_style):
+ writer = DocumentationWriter(link_style)
+ data = data.replace('[[list_of_filters]]', LIST_OF_FILTERS)\
+ .replace('[[list_of_tests]]', LIST_OF_TESTS)\
+ .replace('[[list_of_loaders]]', LIST_OF_LOADERS)
+ parts = publish_parts(
+ data,
+ writer=writer,
+ settings_overrides={
+ 'initial_header_level': 3,
+ 'field_name_limit': 50,
+ }
+ )
+ return {
+ 'title': parts['title'].encode('utf-8'),
+ 'body': parts['body'].encode('utf-8'),
+ 'toc': parts['toc']
+ }
+
+
+def handle_file(filename, fp, dst):
+ now = datetime.now()
+ title = os.path.basename(filename)[:-4]
+ content = fp.read()
+ parts = generate_documentation(content, (lambda x: './%s.html' % x))
+ result = file(os.path.join(dst, title + '.html'), 'w')
+ c = dict(parts)
+ c['style'] = PYGMENTS_FORMATTER.get_style_defs('.syntax')
+ c['generation_date'] = now
+ c['file_id'] = title
+ result.write(TEMPLATE.render(c).encode('utf-8'))
+ result.close()
+
+
+def run(dst, sources=()):
+ path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
+ if not sources:
+ sources = [os.path.join(path, fn) for fn in os.listdir(path)]
+ for fn in sources:
+ if not os.path.isfile(fn):
+ continue
+ print 'Processing %s' % fn
+ f = open(fn)
+ try:
+ handle_file(fn, f, dst)
+ finally:
+ f.close()
+
+
+def main(dst='build/', *sources):
+ return run(os.path.realpath(dst), sources)
+
+
+if __name__ == '__main__':
+ main(*sys.argv[1:])
diff --git a/docs/src/designerdoc.txt b/docs/src/designerdoc.txt
new file mode 100644
index 0000000..c3db752
--- /dev/null
+++ b/docs/src/designerdoc.txt
@@ -0,0 +1,432 @@
+======================
+Designer Documentation
+======================
+
+This part of the Jinja documentaton is meant for template designers.
+
+Basics
+======
+
+The Jinja template language is designed to strike a balance between content
+and application logic. Nevertheless you can use a python like statement
+language. You don't have to know how Python works to create Jinja templates,
+but if you know it you can use some additional statements you may know from
+Python.
+
+Here is a small example template:
+
+.. sourcecode:: html+jinja
+
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+ <title>My Webpage</title>
+ </head>
+ <body>
+ <ul id="navigation">
+ {% for item in navigation %}
+ <li><a href="{{ item.href|e }}">{{ item.caption|e }}</a></li>
+ {% endfor %}
+ </ul>
+
+ <h1>My Webpage</h1>
+ {{ variable }}
+ </body>
+ </html>
+
+This covers the default settings. The application developer might have changed
+the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar. This
+documentation just covers the default values.
+
+A variable looks like ``{{ foobar }}`` where foobar is the variable name. Inside
+of statements (``{% some content here %}``) variables are just normal names
+without the braces around it. In fact ``{{ foobar }}`` is just an alias for
+the statement ``{% print foobar %}``.
+
+Variables are coming from the context provided by the application. Normally there
+should be a documentation regarding the context contents but if you want to know
+the content of the current context you can add this to your template:
+
+.. sourcecode:: html+jinja
+
+ <pre>{{ debug()|e }}</pre>
+
+A context isn't flat which means that each variable can has subvariables, as long
+as it is representable as python data structure. You can access attributes of
+a variable by using the dot and brace operators. The following examples show
+this:
+
+.. sourcecode:: jinja
+
+ {{ user.username }}
+ is the same as
+ {{ user['username'] }}
+ you can also use a variable to access an attribute:
+ {{ users[current_user].username }}
+ If you have numerical indices you have to use the [] syntax:
+ {{ users[0].username }}
+
+Filters
+=======
+
+In the examples above you might have noticed the pipe symbols. Pipe symbols tell
+the engine that it has to apply a filter on the variable. Here a small example:
+
+.. sourcecode:: jinja
+
+ {{ variable|replace('foo', 'bar')|escape }}
+
+If you like you can also put whitespace between the filters.
+
+This will look for a variable variable, passes it to the filter replace with the
+arguments ``'foo'`` and ``'bar'``, and passes the result to the filter `escape`
+that automatically xml escapes the value. The ``e`` filter is an alias for
+``escape``. Here the complete list of supported filters:
+
+[[list_of_filters]]
+
+Tests
+=====
+
+You can use the `is`-operator to perform tests on a value:
+
+.. sourcecode:: jinja
+
+ {{ 42 is numeric }} -> true
+ {{ "foobar" is numeric }} -> false
+ {{ 'FOO' is upper }} -> true
+
+Those tests are especially useful if used in `if`-conditions.
+
+[[list_of_tests]]
+
+Loops
+=====
+
+To iterate over a sequence you can use the `for`-loop. If basically looks like a
+normal python for loop and works pretty much the same:
+
+.. sourcecode:: html+jinja
+
+ <h1>Members</h1>
+ <ul>
+ {% for user in users %}
+ <li>{{ loop.index }} / {{ loop.length }} - {{ user.username|escape }}</li>
+ {% else %}
+ <li><em>no users found</em></li>
+ {% endfor %}
+ </ul>
+
+The optional ``else`` block is only executed if the template did not iterate
+because the sequence was empty.
+
+Inside of a for loop block you can access some special variables:
+
++----------------------+----------------------------------------+
+| Variable | Description |
++======================+========================================+
+| ``loop.index`` | The current iteration of the loop. |
++----------------------+----------------------------------------+
+| ``loop.index0`` | The current iteration of the loop, |
+| | starting counting by 0. |
++----------------------+----------------------------------------+
+| ``loop.revindex`` | The number of iterations from the end |
+| | of the loop. |
++----------------------+----------------------------------------+
+| ``loop.revindex0`` | The number of iterations from the end |
+| | of the loop, starting counting by 0. |
++----------------------+----------------------------------------+
+| ``loop.first`` | True if first iteration. |
++----------------------+----------------------------------------+
+| ``loop.last`` | True if last iteration. |
++----------------------+----------------------------------------+
+| ``loop.even`` | True if current iteration is even. |
++----------------------+----------------------------------------+
+| ``loop.odd`` | True if current iteration is odd. |
++----------------------+----------------------------------------+
+| ``loop.length`` | Total number of items in the sequence. |
++----------------------+----------------------------------------+
+| ``loop.parent`` | The context of the parent loop. |
++----------------------+----------------------------------------+
+
+Loops also support recursion. For example you have a sitemap where each item
+might have a number of child items. Such a template could look like this:
+
+.. sourcecode:: html+jinja
+
+ <h1>Sitemap
+ <ul id="sitemap">
+ {% for item in sitemap recursive %}
+ <li><a href="{{ item.url|e }}">{{ item.title|e }}</a>
+ {% if item.children %}<ul>{{ loop(item.children) }}</ul>{% endif %}</li>
+ {% endfor %}
+ </ul>
+
+Now. What happens here? Basically the first thing that is different to a normal
+loop is the additional ``recursive`` modifier in the `for`-loop declaration.
+It tells the template engine that we want recursion. If recursion is enabled
+the special loop variable is callable. If you call it with a sequence it will
+automatically render that loop at that position with the new sequence as argument.
+
+Cycling
+=======
+
+Sometimes you might want to have different classes for each row in a list. For
+example to have alternating row colors. You can easily do this by using the
+``{% cycle %}`` tag:
+
+.. sourcecode:: html+jinja
+
+ <ul id="messages">
+ {% for message in messages %}
+ <li class="{% cycle 'row1', 'row2' %}">{{ message|e }}</li>
+ {% endfor %}
+ </ul>
+
+Each time Jinja encounters a cycle tag it will evaluate cycle through the list
+of given items and return the next one. If you pass it one item jinja assumes
+that this item is a sequence from the context and uses this:
+
+.. sourcecode:: html+jinja
+
+ <li style="color: {% cycle rowcolors %}">...</li>
+
+Conditions
+==========
+
+Jinja supports python like ``if`` / ``elif`` / ``else`` constructs:
+
+.. sourcecode:: jinja
+
+ {% if user.active %}
+ user {{ user.name|e }} is active.
+ {% elif user.deleted %}
+ user {{ user.name|e }} was deleted some time ago.
+ {% else %}
+ i don't know what's wrong with {{ user.username|e }}
+ {% endif %}
+
+If the user is active the first block is rendered. If not and the user was
+deleted the second one, in all other cases the third one.
+
+You can also use comparison operators:
+
+.. sourcecode:: html+jinja
+
+ {% if amount < 0 %}
+ <span style="color: red">{{ amount }}</span>
+ {% else %}
+ <span style="color: black">{{ amount }}</span>
+ {% endif %}
+
+.. admonition:: Note
+
+ Of course you can use `or` / `and` and parenthesis to create more complex
+ conditions but usually the logic is already handled in the application and
+ you don't have to create such complex constucts in the template code. However
+ in some situations it might be a good thing to have the abilities to create
+ them.
+
+Operators
+=========
+
+Inside ``{{ variable }}`` blocks, `if`-conditions and many other parts you can
+can use Expressions. In expressions you can use any of the following operators:
+
+ ======= ===================================================================
+ ``+`` add the right operand to the left one.
+ ``{{ 1 + 2 }}`` would return three.
+ ``-`` substract the right operand from the left one.
+ ``{{ 1 - 1 }}`` would return zero.
+ ``/`` divide the right from the left operand.
+ ``{{ 1 / 2 }}`` would return 0.5
+ ``*`` multiply the left operand with the right.
+ ``{{ 2 * 2}}`` would return 4
+ ``**`` raise the left operand to the power of the right
+ operand. ``{{ 2**3 }}`` would return 8
+ ``is`` perform a test on the value. See the section about
+ tests for more information.
+ ``|`` apply a filter on the value. See the section about
+ filters for more information.
+ ``and`` return true if the left and the right operand is true.
+ ``or`` return true if the left or the right operand is true.
+ ``()`` call a callable. ``{{ user.get_username() }}``. Inside of the
+ parenthesis you can use variables: ``{{ user.get('username') }}``.
+ ======= ===================================================================
+
+Note that there is no support for any bit operation or something similar.
+
+Macros
+======
+
+If you want to use a partial template on more than one place you might want to
+create a macro out of it:
+
+.. sourcecode:: html+jinja
+
+ {% macro show_user user %}
+ <h1>{{ user.name|e }}</h1>
+ <div class="test">
+ {{ user.description }}
+ </div>
+ {% endmacro %}
+
+Now you can use it from everywhere in the code by passing it an item:
+
+.. sourcecode:: jinja
+
+ {% for user in users %}
+ {{ show_user(user) }}
+ {% endfor %}
+
+You can also specify more then one value:
+
+.. sourcecode:: html+jinja
+
+ {% macro show_dialog title, text %}
+ <div class="dialog">
+ <h1>{{ title|e }}</h1>
+ <div class="test">{{ text|e }}</div>
+ </div>
+ {% endmacro %}
+
+ {{ show_dialog('Warning', 'something went wrong i guess') }}
+
+Inheritance
+===========
+
+The most powerful part of Jinja is template inheritance. Template inheritance
+allows you to build a base "skeleton" template that contains all the common
+elements of your site and defines **blocks** or **markers** that child
+templates can override.
+
+Sounds complicated but is very basic. It's easiest to understand it by starting
+with an example.
+
+Base Template
+-------------
+
+This template, which we'll call ``base.html``, defines a simple HTML skeleton
+document that you might use for a simple two-column page. It's the job of
+"child" templates to fill the empty blocks with content:
+
+.. sourcecode:: html+jinja
+
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link rel="stylesheet" href="style.css" />
+ <title>{% block title %}{% endblock %} - My Webpage</title>
+ {% block html_head %}{% endblock %}
+ </head>
+ <body>
+ <div id="content">
+ {% block content %}{% endblock %}
+ </div>
+
+ <div id="footer">
+ {% block "footer" %}
+ © Copyright 2006 by <a href="http://mydomain.tld">myself</a>.
+ {% endblock %}
+ </div>
+ </body>
+
+In this example, the ``{% block %}`` tags define four blocks that child templates
+can fill in. All the ``block`` tag does is to tell the template engine that a
+child template may override those portions of the template.
+
+Child Template
+--------------
+
+A child template might look like this:
+
+.. sourcecode:: html+jinja
+
+ {% extends "base.html" %}
+ {% block title %}Index{% endblock %}
+
+ {% block html_head %}
+ <style type="text/css">
+ .important {
+ color: #336699;
+ }
+ </style>
+ {% endblock %}
+
+ {% block content %}
+ <h1>Index</h1>
+ <p class="important">
+ Welcome on my awsome homepage.
+ </p>
+ {% endblock %}
+
+The ``{% extends %}`` tag is the key here. It tells the template engine that
+this template "extends" another template. When the template system evaluates
+this template, first it locates the parent.
+
+The filename of the template depends on the template loader. For example the
+``FileSystemLoader`` allows you to access other templates by giving the
+filename. You can access subdirectory with an slash:
+
+.. sourcecode:: jinja
+
+ {% extends "layout/default.html" %}
+
+But this behavior can depend on the application using Jinja.
+
+Note that since the child template didn't define the ``footer`` block, the
+value from the parent template is used instead.
+
+.. admonition:: Note
+
+ You can't define multiple ``{% block %}`` tags with the same name in the
+ same template. This limitation exists because a block tag works in "both"
+ directions. That is, a block tag doesn't just provide a hole to fill - it
+ also defines the content that fills the hole in the *parent*. If there were
+ two similarly-named ``{% block %}`` tags in a template, that template's
+ parent wouldn't know which one of the blocks' content to use.
+
+Template Inclusion
+==================
+
+You can load another template at a given posiiton using ``{% include %}``.
+Usually it's a better idea to use inheritance but if you for example want to
+load macros ``include`` works better than ``extends``:
+
+.. sourcecode:: jinja
+
+ {% include "myhelpers.html" %}
+ {{ my_helper("foo") }}
+
+If you define a macro called ``my_helper`` in ``myhelpers.html`` you can now
+use it from the template as shown above.
+
+Filtering Blocks
+================
+
+Sometimes it could be a good idea to filter a complete block. For example if
+you want to escape some html code:
+
+.. sourcecode:: jinja
+
+ {% filter escape %}
+ <html>
+ <code>goes here</code>
+ </html>
+ {% endfilter %}
+
+Of course you can chain filters too.
+
+Defining Variables
+==================
+
+You can also define variables in the namespace using the ``{% set %}`` tag:
+
+.. sourcecode:: jinja
+
+ {% set foo = 'foobar' %}
+ {{ foo }}
+
+This should ouputput ``foobar``.
diff --git a/docs/src/devintro.txt b/docs/src/devintro.txt
new file mode 100644
index 0000000..157301c
--- /dev/null
+++ b/docs/src/devintro.txt
@@ -0,0 +1,139 @@
+====================
+Developer Quickstart
+====================
+
+This part of the documentation shows you how to embedd Jinja into your
+application.
+
+Starting Up
+===========
+
+Here the quickest way to create a template from a string and render it:
+
+.. sourcecode:: python
+
+ from jinja import Environment
+ env = Environment()
+ tmpl = env.from_string('Hello {{ name }}!')
+ print tmpl.render(name='John Doe')
+
+This example should output the following string after execution::
+
+ Hello John Doe!
+
+If you receive an error check if you have a typo in your code. If not have
+a look at the `installation`_ page for troubleshooting.
+
+The Environment
+===============
+
+The core component of Jinja is the `Environment`. It helds important shared
+variables like configuration, filters, tests, globals and other stuff.
+
+Here the possible initialisation parameters:
+
+=========================== ==================================================
+``block_start_string`` * the string marking the begin of a block. this
+ defaults to ``'{%'``.
+``block_end_string`` * the string marking the end of a block. defaults
+ to ``'%}'``.
+``variable_start_string`` * the string marking the begin of a print
+ statement. defaults to ``'{{'``.
+``comment_start_string`` * the string marking the begin of a
+ comment. defaults to ``'{#'``.
+``comment_end_string`` * the string marking the end of a comment.
+ defaults to ``'#}'``.
+``trim_blocks`` * If this is set to ``True`` the first newline
+ after a block is removed (block, not
+ variable tag!). Defaults to ``False``.
+``auto_escape`` If this is set to ``True`` Jinja will
+ automatically escape all variables using xml
+ escaping methods. If you don't want to escape a
+ string you have to wrap it in a ``Markup``
+ object from the ``jinja.datastructure`` module.
+``template_charset`` The charset of the templates. Defaults
+ to ``'utf-8'``.
+``charset`` Charset of all string input data. Defaults
+ to ``'utf-8'``.
+``namespace`` Global namespace for all templates.
+``loader`` Specify a template loader.
+``filters`` dict of filters or the default filters if not
+ defined.
+``tests`` dict of tests of the default tests if not defined.
+=========================== ==================================================
+
+All of this variables except those marked with a star(*) are modifyable after
+environment initialisation.
+
+The environment provides the following useful functions and properties
+additional to the initialisation values:
+
+=========================== ==================================================
+``parse(source, filename)`` Parse the sourcecode and return the abstract
+ syntax tree. This tree of nodes is used by the
+ `translators`_ to convert the template into
+ executable source- or bytecode.
+``from_string(source)`` Load and parse a template source and translate it
+ into evaluable python code. This code is wrapped
+ with in a `Template` class that allows you to
+ render it.
+``get_template(name)`` load a template from a loader. If the template
+ does not exist you will get a `TemplateNotFound`
+ exception.
+=========================== ==================================================
+
+There are also some internal functions on the environment used by the template
+evaluation code to keep it sandboxed.
+
+Loading Templates From Files
+============================
+
+Loading templates from a string is always a bad idea. It doesn't allow template
+inheritance and is also slow since it parses and compiles the template again
+and again whereas loaders can cache the template code.
+
+All you have to do is to define a loader and use the `get_template` function.
+
+.. sourcecode:: python
+
+ from jinja import Environment, FileSystemLoader
+ env = Environment(loader=FileSystemLoader('templates'))
+ tmpl = env.get_template('index.html')
+ print tmpl.render(name='John Doe')
+
+This tells jinja to look for templates in the ``templates`` folder. It's a
+better idea to use an absolute path here though. For a list of supported
+loaders or how to write your own, head over to the `loader`_ documentation.
+
+Adding Filters
+==============
+
+If you want to add additional filters to the environment the best way is to
+modify the ``filters`` attribute and not to pass a dict to the environment.
+If you pass it a dict it will not include the default filters!
+
+.. sourcecode:: python
+
+ from mylib import my_cool_filter
+ env.filters['mycoolfilter'] = my_cool_filter
+
+Writing filter functions is explained in the `filter development`_ section.
+
+Adding Tests
+============
+
+Adding additional tests works analog to filters:
+
+.. sourcecode:: python
+
+ from mylib import my_cool_test
+ env.tests['mycooltest'] = my_cool_test
+
+Writing tests is explained in the `test development`_ section.
+
+
+.. _installation: installation.txt
+.. _translators: translators.txt
+.. _loader: loaders.txt
+.. _filter development: filters.txt
+.. _test development: tests.txt
diff --git a/docs/src/fromdjango.txt b/docs/src/fromdjango.txt
new file mode 100644
index 0000000..71b2068
--- /dev/null
+++ b/docs/src/fromdjango.txt
@@ -0,0 +1,108 @@
+===============================
+Differences To Django Templates
+===============================
+
+If you have previously worked with Django templates you should feel very
+familiar. In fact most of the syntax elements look and work the same.
+
+However Jinja provides some more syntax elements covered in the documentation
+and some work a bit different.
+
+Method Calls
+============
+
+In Django method calls work implicit. With Jinja you have to tell it that you
+want to call it. Thus this Django code:
+
+.. sourcecode:: django
+
+ {% for page in user.get_created_pages %}
+ ...
+ {% endfor %}
+
+will look like this in Jinja:
+
+.. sourcecode:: jinja
+
+ {% for page in user.get_created_pages() %}
+ ...
+ {% endfor %}
+
+This allows you to pass variables to the function which is also used for
+macros and loop recursion, both features that don't exist in Django.
+
+Conditions
+==========
+
+In Django you can use the following constructs to check for equality:
+
+.. sourcecode:: django
+
+ {% ifequals foo "bar" %}
+ ...
+ {% else %}
+ ...
+ {% endifequals %}
+
+In Jinja you can use the normal ``if`` statement in combination with
+operators:
+
+.. sourcecode:: jinja
+
+ {% if foo == 'bar' %}
+ ...
+ {% else %}
+ ...
+ {% endif %}
+
+You can also have multiple ``elif`` branches in your template:
+
+.. sourcecode:: jinja
+
+ {% if something %}
+ ...
+ {% elif otherthing %}
+ ...
+ {% elif foothing %}
+ ...
+ {% else %}
+ ...
+ {% endif %}
+
+Filter Arguments
+================
+
+Jinja provides more than one argument for a filter. Also the syntax for argument
+passing is different. A template that looks like this in Django:
+
+.. sourcecode:: django
+
+ {{ items|join:", " }}
+
+looks like this in jinja:
+
+.. sourcecode:: jinja
+
+ {{ items|join(', ') }}
+
+In fact it's a bit more to write but it allows different type of arguments including
+variables and more then one of them.
+
+Tests
+=====
+
+Additionally to filters there also exists tests you can perform using the `is`
+operator. Here some examples:
+
+.. sourcecode:: jinja
+
+ {% if user.user_id is odd %}
+ {{ user.username|e }} is odd
+ {% else %}
+ hmm. {{ user.username|e }} looks pretty normal
+ {% endif %}
+
+For a list of supported tests head over to the `syntax reference`_.
+
+
+.. _syntax reference: designerdoc.txt
diff --git a/docs/src/index.txt b/docs/src/index.txt
new file mode 100644
index 0000000..250a5a3
--- /dev/null
+++ b/docs/src/index.txt
@@ -0,0 +1,25 @@
+======================
+Documentation Overview
+======================
+
+Welcome in the Jinja documentation.
+
+- `Installing Jinja <installation.txt>`_
+
+- Application Developer Documentation:
+
+ - `Quickstart <devintro.txt>`_
+
+ - `Template Loaders <loaders.txt>`_
+
+ - `Filter Functions <filters.txt>`_
+
+ - `Test Functions <tests.txt>`_
+
+ - `Translators <translators.txt>`_
+
+- Template Designer Documentation:
+
+ - `Syntax Reference <designerdoc.txt>`_
+
+ - `Differences To Django <fromdjango.txt>`_
diff --git a/docs/src/loaders.txt b/docs/src/loaders.txt
new file mode 100644
index 0000000..dbe4df3
--- /dev/null
+++ b/docs/src/loaders.txt
@@ -0,0 +1,10 @@
+================
+Template Loaders
+================
+
+This part of the documentation explains how to use and write a template loader.
+
+Builtin Loaders
+===============
+
+[[list_of_loaders]]