Skip to content

yonasBSD/jinja.rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

jinja.rs

A powerful, configuration-driven template rendering engine combining MiniJinja templates with Rhai scripting and shell command execution.

Rust License

✨ Features

  • 🎨 MiniJinja Templates - Full-featured Jinja2-compatible templating for Rust.
  • πŸ¦€ Rhai Scripting - Embedded scripting engine for complex, dynamic variable generation.
  • 🐚 Embedded Fish Shell - Includes a portable fish shell runtime embedded in the binary.
    • Zero Dependencies: No need to have fish, bash, or zsh installed on the host system.
    • Consistency: Ensures shell commands (cmd/cmds) run identically across Linux, FreeBSD, and OpenBSD.
    • Auto-Provisioning: Automatically extracts to ~/.cache/jinja-rs/ and manages permissions on first run.
  • βš™οΈ Declarative Configuration - Define your entire data pipeline in a clean j2.yaml file.
  • 🎯 Custom Filters - Turn any Rhai function into a reusable MiniJinja filter.
  • πŸ”§ Flexible Execution - Per-variable shell overrides, custom environment variables, and specific working directories.
  • πŸš€ High Performance - Parallel variable resolution and efficient binary extraction.

πŸš€ Quick Start

Installation

cargo install jinja-rs

Or build from source:

git clone https://github.com/yonasBSD/jinja.rs
cd jinja.rs
cargo build --release

Basic Usage

  1. Create a configuration file j2.yaml:
default_shell: bash

vars:
  # Script-based variable
  - name: timestamp
    script: "1234567890"
  
  # Shell command variable
  - name: username
    cmd: "whoami"
  
  # Custom filter function
  - function: upper
    arguments:
      - name: text
    script: "text.to_upper()"
  1. Create a template template.j2:
Hello {{ username }}!
Timestamp: {{ timestamp }}
Shouting: {{ username | upper }}
  1. Render the template:
jinja-rs --template template.j2

Output:

Hello alice!
Timestamp: 1234567890
Shouting: ALICE

πŸ“– Documentation

Configuration File (j2.yaml)

The configuration file drives all behavior. It supports:

Global Settings

default_shell: bash  # Default shell for command execution (optional)

Variable Types

1. Rhai Script Variables

Execute Rhai scripts to generate values:

vars:
  - name: calculation
    script: "2 + 2 * 10"
  
  - name: greeting
    script: "\"Hello, \" + \"World!\""

2. Single Command Variables

Execute a shell command and capture output:

vars:
  - name: hostname
    cmd: "hostname"
  
  - name: current_date
    cmd: "date +%Y-%m-%d"
    shell: sh  # Override default shell

3. Multi-Command Variables

Execute multiple commands and join results:

vars:
  - name: system_info
    cmds:
      - "uname -s"
      - "uname -r"
      - "uname -m"

4. Custom Filters

Define Rhai functions that become MiniJinja filters:

vars:
  - function: reverse
    arguments:
      - name: text
    script: |
      let chars = text.split("");
      chars.reverse();
      chars.join("")
  
  - function: multiply
    arguments:
      - name: value
      - name: factor
    script: "parse_int(value) * parse_int(factor)"

Use in templates:

{{ "hello" | reverse }}
{{ "5" | multiply(3) }}

Advanced Configuration

Environment Variables

vars:
  - name: custom_path
    cmd: "echo $MY_VAR"
    env:
      MY_VAR: "/custom/path"
      ANOTHER: "value"

Working Directory

vars:
  - name: files
    cmd: "ls -la"
    cwd: "/tmp"

Shell Selection Precedence

  1. Per-variable shell (highest priority)
  2. Global default_shell
  3. fish (hardcoded fallback)
default_shell: bash

vars:
  - name: uses_bash
    cmd: "echo $SHELL"
  
  - name: uses_sh
    cmd: "echo $SHELL"
    shell: sh  # Overrides default

Template Syntax

jinja.rs uses MiniJinja, which is compatible with Jinja2:

{# Comments #}

{{ variable }}  {# Variable substitution #}

{{ variable | filter }}  {# Apply filter #}

{% if condition %}
  ...
{% endif %}

{% for item in items %}
  {{ item }}
{% endfor %}

🎯 Use Cases

Configuration File Generation

Generate Nginx configs, systemd units, or any configuration files:

# j2.yaml
vars:
  - name: server_name
    cmd: "hostname -f"
  
  - name: worker_processes
    script: "4"
# nginx.conf.j2
server {
    server_name {{ server_name }};
    worker_processes {{ worker_processes }};
}

Dynamic Documentation

Create documentation with live system information:

vars:
  - name: version
    cmd: "git describe --tags"
  
  - name: build_date
    cmd: "date -u +%Y-%m-%d"
  
  - name: contributors
    cmds:
      - "git log --format='%an' | sort -u | head -5"

DevOps Automation

Generate deployment manifests with environment-specific values:

vars:
  - name: environment
    cmd: "echo $DEPLOY_ENV"
  
  - name: replicas
    script: |
      if environment == "prod" { 5 } else { 2 }

πŸ—οΈ Architecture

graph TD
    A[j2.yaml<br/>Configuration] --> B{Variable Type}
    B -->|script| C[Rhai Engine]
    B -->|cmd/cmds| D[Shell Executor]
    B -->|function| E[Rhai Functions]
    
    C --> F[Variables]
    D --> F
    E --> G[Custom Filters]
    
    H[Template .j2] --> I[MiniJinja Engine]
    F --> I
    G --> I
    
    I --> J[Rendered Output]
    
    style A fill:#e1f5ff,stroke:#0288d1,stroke-width:2px
    style H fill:#e1f5ff,stroke:#0288d1,stroke-width:2px
    style I fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    style J fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
    style C fill:#ffe0b2,stroke:#e64a19,stroke-width:2px
    style D fill:#ffe0b2,stroke:#e64a19,stroke-width:2px
    style E fill:#ffe0b2,stroke:#e64a19,stroke-width:2px
Loading

Design Principles

  1. Configuration over Code - All logic defined in YAML, no code changes needed
  2. Separation of Concerns - Variables, filters, and templates are independent
  3. Composability - Mix Rhai scripts, shell commands, and template logic freely
  4. Fail-Safe - Errors are captured and reported, not silently ignored

πŸ§ͺ Testing

Comprehensive test suite with 60+ tests covering:

  • Configuration deserialization
  • Command execution with various shells
  • Rhai script evaluation
  • MiniJinja template rendering
  • Integration scenarios
  • Edge cases and error handling

Run tests:

cargo test

Run tests with output:

cargo test -- --nocapture

See TESTING.md for detailed test documentation.

πŸ›£οΈ Roadmap

  • CLI argument for config file path (currently hardcoded to j2.yaml)
  • Template auto-discovery
  • Multi-template rendering in one invocation
  • JSON/TOML config format support
  • Watch mode for live reloading
  • Built-in filter library
  • Plugin system for custom functions
  • Performance optimizations for large-scale rendering

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Setup

# Clone the repository
git clone https://github.com/yonasBSD/jinja.rs
cd jinja.rs

# Run tests
cargo test

# Run with example
cargo run -- --template examples/demo.j2

# Build release
cargo build --release

πŸ“ License

This project is licensed under either of:

at your option.

πŸ™ Acknowledgments

  • MiniJinja - Jinja2 template engine for Rust
  • Rhai - Embedded scripting language
  • clap - Command-line argument parsing

πŸ“§ Contact


Made with ❀️ and πŸ¦€

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •