Skip to content

Commit

Permalink
Added a self-referential context example
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Sep 16, 2023
1 parent ed9f6bc commit edbaf59
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ the `cargo run` command. Alternatively you can do `cargo run -p example-name`.
* [render-macro](render-macro): minimal Hello World example using the `render!` macro.
* [render-template](render-template): CLI app that renders templates from string.
* [render-value](render-value): Demonstrates how `Value` can be passed as `Serialize` as context.
* [self-referential-context](self-referential-context): Shows a helper that allows self-referential contexts.
* [stack-ref](stack-ref): Shows how the `minijinja-stack-ref` crate can be used to reference stack values.
* [value-tracking](value-tracking): Shows how you can track values that are referenced at runtime.
* [wasm-yew](wasm-yew): Shows how to use MiniJinja with WASM in the browser.
Expand Down
9 changes: 9 additions & 0 deletions examples/self-referential-context/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "self-referential-context"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
minijinja = { path = "../../minijinja" }
10 changes: 10 additions & 0 deletions examples/self-referential-context/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# self-referential-context

A context wrapper that acts self-referential. This allows variables passed to
`render` to be also reachable via a `CONTEXT` alias. In short: a template
can render a variable `name` via `{{ name }}` or also `{{ CONTEXT.name }}`.
This would permit things such as `{{ CONTEXT|tojson }}`.

```console
$ cargo run
```
49 changes: 49 additions & 0 deletions examples/self-referential-context/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::sync::Arc;

use minijinja::value::{StructObject, Value, ValueKind};
use minijinja::{context, Environment};

struct SelfReferentialContext {
ctx: Value,
}

impl StructObject for SelfReferentialContext {
fn get_field(&self, name: &str) -> Option<Value> {
if name == "CONTEXT" {
return Some(self.ctx.clone());
}
self.ctx.get_attr(name).ok().filter(|x| !x.is_undefined())
}

fn fields(&self) -> Vec<Arc<str>> {
if self.ctx.kind() == ValueKind::Map {
if let Ok(keys) = self.ctx.try_iter() {
return keys.filter_map(|x| Arc::<str>::try_from(x).ok()).collect();
}
}
Vec::new()
}
}

pub fn make_self_referential(ctx: Value) -> Value {
Value::from_struct_object(SelfReferentialContext { ctx })
}

static TEMPLATE: &str = r#"
name: {{ name }}
CONTEXT.name: {{ CONTEXT.name }}
CONTEXT.CONTEXT is undefined: {{ CONTEXT.CONTEXT is undefined }}
CONTEXT: {{ CONTEXT }}
"#;

fn main() {
let env = Environment::new();
let template = env.template_from_str(TEMPLATE).unwrap();

let ctx = make_self_referential(context! {
name => "John",
other_value => 42,
});

println!("{}", template.render(ctx).unwrap());
}

0 comments on commit edbaf59

Please sign in to comment.