ninjadog: pug + jinja2 == ❤️ — ninjadog 0.5.1 documentation

# ninjadog: pug + jinja2 == ❤️

## ninjadog

Pug template (formerly jade) support in Python

- Free software: MIT license
- Documentation: http://journalpanic.com/ninjadog
- GitHub: https://github.com/knowsuchagency/ninjadog

### Installation

ninjadog requires Python 3, node-js, npm, and the pug-cli library

    brew install npm
    npm install -g pug-cli
    pip install ninjadog

For use with Pyramid, just add it to the configuration

    config.include('ninjadog')

### Usage

ninjadog leverages the pug-cli library, written in nodejs, to render pug templates in Python.

It allows you to take something like this

    html
        head
            title my pug template
        body
            #content
                h1 Hello #{name}
                .block
                    input#bar.foo1.foo2
                    input(type="text", placeholder="your name")
                    if name == "Bob"
                        h2 Hello Bob
                    ul
                        for book in books
                            li= book
                        else
                            li sorry, no books

and sprinkle some Python over it

    from ninjadog import render

    context = {
        'name': 'Bob',
        'books': ['coloring book', 'audio book', "O'Reilly book"],
        'type': 'text',
    }

    print(render(file=filepath, context=context, pretty=True))

to render this

    <!DOCTYPE html>
    <html>
      <head>
        <title>my pug template</title>
      </head>
      <body>
        <div id="content">
          <h1>Hello Bob</h1>
          <div class="block">
            <input class="foo1 foo2" id="bar">
            <input type="text" placeholder="your name">
            <h2>Hello Bob</h2>
            <ul>
              <li>coloring book</li>
              <li>audio book</li>
              <li>O'Reilly book</li>
            </ul>
          </div>
        </div>
      </body>
    </html>

You can even combine jinja2 syntax for unparalleled template-rendering power.

    from ninjadog import render

    def stop_believing():
        return False

    context = {
        'stop_believing': stop_believing,
        'happy': {
            'birthday': 'today',
        }
    }

    template_string = """
    h1 hello, world
    if happy.birthday == 'today'
        p it's time to celebrate!
        p {{ "Don't" if not stop_believing() }} stop believing
    """

    print(render(template_string,
                 context=context,
                 pretty=True,
                 with_jinja=True))

    <h1>hello, world</h1>
    <p>it's time to celebrate!</p>
    <p>Don't stop believing</p>

### Why?

Pug templates are a super elegant and expressive way to write html, IMO.

There exists a project, pyjade and a less-popular fork, pypugjs, that are pure-python implementations of the pug template engine, but they have some minor bugs and the maintenance is a bit lacking.

I figured it would be good to have an alternative method to render pug templates that used the native javascript rendering engine.

ninjadog does this by spawning the pug cli as a subprocess. This means that it can’t be as fast as a native template engine like pyjade, but it will likely be more reliable over time as it’s leveraging the popular and well-maintained nodejs implementation.

### Gotchas

Currently, rendering a template with jinja2 syntax goes through the following process:

1. Render elements on the initial template through jinja2
2. Pass the output to the pug-cli, gathering extensions and inclusions in the process
3. Render the output through jinja2 again, since the original template may have extended or included other templates that countained jinja2 syntax themselves.

What this means is that if you want to escape jinja2 syntax, you need to do it twice.

For example, to have a literal `{{ escaping inception }}` rendered, you’ll need to have `{{ "{{ '{{ escaping inception }}' }}" }}` in your template.

对不起

### Command Line Interface

    ninjadog v0.5.1

    Render pug templates to html.

    Usage:
        ninjadog string [options] <string>
        ninjadog file [options] <file>
        ninjadog dir [options] <source> [<destination>]
        ninjadog - [options]
        ninjadog -h | --help
        ninjadog -V | --version

    Options:
        -h --help                 show help and exit
        -V --version              show version and exit
        -f --file <file>          the filepath to the template
        -p --pretty               pretty print output
        -c --context <context>    json string to be passed as context
        -j --with-jinja           render jinja2 syntax as well as pug
        -v --verbose              verbose output
        -n --dry-run              verbose output and exit without executing
        <destination>             destination directory to render pug files to

    Strings may be passed via pipe using `-` argument.

    i.e.

    echo 'h1 hello {{ name }}' | ninjadog - -j -c '{"name": "Sam"}'

    outputs

    <h1>hello Sam</h1>

### Pyramid

You can avoid having to render each template anew with every HTTP request. In your Pyramid configuration, you can have ninjadog cache templates by setting the `ninjadog.cache` option to true like so

    [app:main]
    ninjadog.cache = true

    Configurator(settings={'ninjadog.cache': True})
    # ...

… however you like to configure your app.

While this will make each page load much faster after the first visit, IT ALSO MEANS YOU CANNOT HAVE ANY MUTABLE STATE IN YOUR TEMPLATE as the template itself will only be rendered once.

Rendered templates will be saved alongside the original template with `.html` replacing `.pug` as the suffix. This ensures relative paths in templates won’t break.

It may be best to prototype by using ninjadog as normal - mutable state, conditionals, mixins… whatever - but to set the aformentioned option to true and move any logic dealing with mutable state into javascript for production. The choice yours.

### API Documentation

- ninjadog package
  - Subpackages
    - ninjadog.ext package
      - Submodules
      - ninjadog.ext.pyramid module
      - Module contents
  - Submodules
  - ninjadog.cli module
  - ninjadog.constants module
  - ninjadog.decorators module
  - ninjadog.ninjadog module
  - ninjadog.utils module
  - Module contents

### Indices and tables

- Index
- Module Index
- Search Page