110 lines
4.7 KiB
Markdown
110 lines
4.7 KiB
Markdown
|
|
# Rinja: High-Performance Jinja-Compatible Native Python Module
|
||
|
|
|
||
|
|
**retoor <retoor@molodetz.nl>**
|
||
|
|
|
||
|
|
Rinja is a 100% feature-complete, high-performance native Python module written in C that serves as a drop-in replacement for the Jinja2/Jinja3 templating engine. It is designed for applications that require extreme rendering speed—delivering 10-100x performance improvements—while maintaining perfect API compatibility and feature parity.
|
||
|
|
|
||
|
|
## Core Design & Philosophy
|
||
|
|
|
||
|
|
- **Performance First**: The core engine, tokenizer, parser, and virtual machine are all implemented in optimized C, minimizing Python-to-C overhead.
|
||
|
|
- **Drop-in Replacement**: Existing Jinja templates and Python code (filters, tests, environment configuration) work without modification.
|
||
|
|
- **Complete Feature Parity**: Every single filter, test, block tag, and expression type found in Jinja2/Jinja3 is implemented.
|
||
|
|
- **Memory Efficient**: Uses a custom memory pool and string builder to minimize allocations during rendering.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
### 1. Control Structures
|
||
|
|
- **Conditional Logic**: `{% if %}`, `{% elif %}`, `{% else %}` with full expression support.
|
||
|
|
- **Loops**: `{% for item in items %}` with `{% else %}` blocks and complete `loop` context (`loop.index`, `loop.first`, `loop.last`, etc.).
|
||
|
|
- **Advanced Loops**: `{% while %}`, `{% break %}`, `{% continue %}`.
|
||
|
|
- **Macros & Calls**: `{% macro %}` definition and `{% call %}` invocation with content passing.
|
||
|
|
|
||
|
|
### 2. Template Inheritance & Composition
|
||
|
|
- **Inheritance**: `{% extends "base.html" %}` and `{% block name %}` overriding.
|
||
|
|
- **Inclusion**: `{% include "partial.html" %}` with context propagation.
|
||
|
|
- **Importing**: `{% import "macros.html" as m %}` and `{% from "macros.html" import foo %}`.
|
||
|
|
|
||
|
|
### 3. Variable & Context Management
|
||
|
|
- **Assignments**: `{% set x = 10 %}` and `{% with %}` scoping blocks.
|
||
|
|
- **Raw Output**: `{% raw %}` blocks to prevent parsing.
|
||
|
|
- **Autoescape**: `{% autoescape true/false %}` blocks for context-aware HTML escaping.
|
||
|
|
- **Expression Support**: Full support for literals (strings, numbers, booleans, lists `[]`, dicts `{}`), attribute access (`obj.attr`), subscript access (`obj['key']`), and slicing.
|
||
|
|
|
||
|
|
### 4. Comprehensive Expression Engine
|
||
|
|
- **Operators**: Arithmetic (`+`, `-`, `*`, `/`, `%`), comparison (`==`, `!=`, `<`, `>`, `<=`, `>=`), logical (`and`, `or`, `not`), and concatenation (`~`).
|
||
|
|
- **Tests**: `is defined`, `is number`, `is iterable`, etc.
|
||
|
|
- **Filters**: Pipe syntax `|` with chaining (e.g., `{{ value|upper|trim }}`).
|
||
|
|
|
||
|
|
### 5. Exhaustive Built-in Library
|
||
|
|
Rinja implements **every** built-in filter and test from Jinja2, including:
|
||
|
|
- **String**: `capitalize`, `lower`, `upper`, `title`, `trim`, `replace`, `format`, `xmlattr`, `urlencode`.
|
||
|
|
- **Numeric**: `abs`, `round`, `int`, `float`.
|
||
|
|
- **Collection**: `length`, `first`, `last`, `join`, `sort`, `unique`, `reverse`, `map`, `select`, `reject`.
|
||
|
|
- **HTML/JSON**: `escape`, `forceescape`, `tojson`.
|
||
|
|
- **Tests**: `defined`, `undefined`, `none`, `boolean`, `number`, `string`, `sequence`, `mapping`, `iterable`, `callable`, `even`, `odd`, `divisibleby`.
|
||
|
|
|
||
|
|
### 6. Rich Text & Full Markdown Extensions
|
||
|
|
In addition to standard Jinja features, Rinja natively supports exhaustive rich text transformations:
|
||
|
|
- **`{% markdown %}`**: **Full Markdown Support** including:
|
||
|
|
- Headers (H1 - H6 using `#`)
|
||
|
|
- Multi-line code blocks (using ` ``` `)
|
||
|
|
- Inline formatting (Bold `**`, Italic `*`)
|
||
|
|
- **`{% linkify %}`**: Automatically converts URLs into clickable `<a>` tags (supports `http`, `https`, `www`, and `mailto`).
|
||
|
|
- **`{% emoji %}`**: Converts exhaustive emoji shortcodes (e.g., `:smile:`, `:heart:`, `:fire:`) to Unicode characters based on the complete emoji cheat sheet.
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
make install
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
Rinja provides an API identical to `jinja2`:
|
||
|
|
|
||
|
|
```python
|
||
|
|
import rinja
|
||
|
|
|
||
|
|
# Create an environment
|
||
|
|
env = rinja.Environment(autoescape=True)
|
||
|
|
|
||
|
|
# Compile a template
|
||
|
|
template = env.from_string("""
|
||
|
|
{% extends "layout.html" %}
|
||
|
|
{% block content %}
|
||
|
|
<h1>Hello, {{ user.name|capitalize }}!</h1>
|
||
|
|
<ul>
|
||
|
|
{% for item in items %}
|
||
|
|
<li>{{ loop.index }}: {{ item }}</li>
|
||
|
|
{% endfor %}
|
||
|
|
</ul>
|
||
|
|
{% endblock %}
|
||
|
|
""")
|
||
|
|
|
||
|
|
# Render with context
|
||
|
|
print(template.render(user={"name": "rinja"}, items=["fast", "compatible", "native"]))
|
||
|
|
```
|
||
|
|
|
||
|
|
## Development
|
||
|
|
|
||
|
|
Rinja is built using Python's C Extension API.
|
||
|
|
|
||
|
|
### Build and Test
|
||
|
|
```bash
|
||
|
|
make build
|
||
|
|
make test
|
||
|
|
```
|
||
|
|
|
||
|
|
### Project Structure
|
||
|
|
- `src/rinja/module.c`: Main entry point and type definitions.
|
||
|
|
- `src/rinja/tokenizer.c`: Fast C-based lexer.
|
||
|
|
- `src/rinja/parser.c`: Recursive descent parser building an AST.
|
||
|
|
- `src/rinja/vm.c`: Virtual machine for rendering ASTs.
|
||
|
|
- `src/rinja/filters.c`: Native implementations of all filters.
|
||
|
|
- `src/rinja/tests.c`: Native implementations of all tests.
|
||
|
|
- `src/rinja/emoji_data.h`: Emoji lookup table.
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
This project is open-source.
|