From 975a286304aea5d5a4c2687b5b3d2a660e84f593 Mon Sep 17 00:00:00 2001 From: Luis Moreno Date: Sun, 31 May 2020 17:34:08 -0400 Subject: [PATCH] Add context --- src/expression_evaluator.rs | 4 +- src/lib.rs | 2 +- src/renderer.rs | 13 +++--- src/statement/mod.rs | 18 ++++---- src/template.rs | 9 ++-- tests/basic.rs | 6 ++- tests/expressions.rs | 84 ++++++++++++++++++------------------- tests/statement_if.rs | 4 ++ tests/utils.rs | 11 ++++- tests/whitespace_control.rs | 4 ++ 10 files changed, 88 insertions(+), 67 deletions(-) diff --git a/src/expression_evaluator.rs b/src/expression_evaluator.rs index 4b90743..c0b6aca 100644 --- a/src/expression_evaluator.rs +++ b/src/expression_evaluator.rs @@ -1,6 +1,6 @@ use crate::renderer::Render; use crate::value::visitors; -use crate::value::Value; +use crate::value::{Value, ValuesMap}; use std::io::Write; pub trait Evaluate { @@ -92,7 +92,7 @@ pub struct FullExpressionEvaluator<'a> { } impl<'a> Render for FullExpressionEvaluator<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { let value = self.evaluate(); out.write(value.to_string().as_bytes()); } diff --git a/src/lib.rs b/src/lib.rs index b54d19d..7daa48d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ pub mod error; -mod value; +pub mod value; mod expression_evaluator; mod expression_parser; diff --git a/src/renderer.rs b/src/renderer.rs index e8e6402..1eb86b6 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1,4 +1,5 @@ use crate::expression_evaluator::FullExpressionEvaluator; +use crate::value::ValuesMap; use std::fmt; use std::io::Write; use std::sync::RwLock; @@ -8,7 +9,7 @@ pub struct ComposedRenderer<'a> { } pub trait Render { - fn render(&self, out: &mut dyn Write); + fn render(&self, out: &mut dyn Write, params: &ValuesMap); } impl<'a> ComposedRenderer<'a> { @@ -22,9 +23,9 @@ impl<'a> ComposedRenderer<'a> { } impl<'a> Render for ComposedRenderer<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { for r in self.renderers.read().unwrap().iter() { - r.render(out) + r.render(out, params) } } } @@ -47,7 +48,7 @@ impl<'a> RawTextRenderer<'a> { } impl<'a> Render for RawTextRenderer<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { out.write(self.content.as_bytes()); } } @@ -57,8 +58,8 @@ pub struct ExpressionRenderer<'a> { } impl<'a> Render for ExpressionRenderer<'a> { - fn render(&self, out: &mut dyn Write) { - self.expression.render(out); + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { + self.expression.render(out, params); } } diff --git a/src/statement/mod.rs b/src/statement/mod.rs index 61c0d01..8ade345 100644 --- a/src/statement/mod.rs +++ b/src/statement/mod.rs @@ -4,7 +4,7 @@ use std::io::Write; use crate::expression_evaluator::Evaluate; use crate::renderer::ComposedRenderer; use crate::renderer::Render; -use crate::value::Value; +use crate::value::{Value, ValuesMap}; use std::rc::Rc; pub mod parser; pub struct IfStatement<'a> { @@ -29,15 +29,15 @@ impl<'a> IfStatement<'a> { } } impl<'a> Render for IfStatement<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { let value = self.expression.evaluate(); if let Value::Boolean(true) = value { - self.body.as_ref().unwrap().render(out) + self.body.as_ref().unwrap().render(out, params) } else { for branch in &self.else_branches { if let Statement::Else(else_branch) = branch { if else_branch.should_render() { - branch.render(out); + branch.render(out, params); break; } } else { @@ -74,8 +74,8 @@ impl<'a> ElseStatement<'a> { } } impl<'a> Render for ElseStatement<'a> { - fn render(&self, out: &mut dyn Write) { - self.body.as_ref().unwrap().render(out); + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { + self.body.as_ref().unwrap().render(out, params); } } @@ -98,10 +98,10 @@ impl<'a> Statement<'a> { } } impl<'a> Render for Statement<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { match self { - Statement::If(statement) => statement.render(out), - Statement::Else(statement) => statement.render(out), + Statement::If(statement) => statement.render(out, params), + Statement::Else(statement) => statement.render(out, params), } } } diff --git a/src/template.rs b/src/template.rs index 099c542..e16bbb5 100644 --- a/src/template.rs +++ b/src/template.rs @@ -2,6 +2,7 @@ use crate::error::Result; use crate::renderer::{ComposedRenderer, Render}; use crate::template_env::TemplateEnv; use crate::template_parser::TemplateParser; +use crate::value::ValuesMap; use std::io::Write; use std::rc::Rc; @@ -30,17 +31,17 @@ impl<'a> Template<'a> { Ok(()) } - pub fn render_as_string(&self) -> Result { + pub fn render_as_string(&self, params: &ValuesMap) -> Result { let mut b: Vec = Vec::new(); - self.render(&mut b); + self.render(&mut b, params); Ok(String::from_utf8(b).expect("Found invalid UTF-8")) } } impl<'a> Render for Template<'a> { - fn render(&self, out: &mut dyn Write) { + fn render(&self, out: &mut dyn Write, params: &ValuesMap) { if let Some(ref renderer) = self.renderer { - renderer.render(out) + renderer.render(out, params) } } } diff --git a/tests/basic.rs b/tests/basic.rs index c96ad26..d9e8b15 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -3,7 +3,7 @@ use temple::error::Result; #[test] fn render_plain_singe_line() -> Result<()> { - assert_render_template_eq("Hello, world!", "Hello, world!") + assert_render_template_eq("Hello, world!", "Hello, world!", None) } #[test] @@ -13,6 +13,7 @@ fn render_plain_multiline() -> Result<()> { Hello, world!", "Hello, world! Hello, world!", + None, ) } @@ -23,6 +24,7 @@ fn render_multiline_with_comment() -> Result<()> { {#Comment to skip #}Hello, world!", "Hello, world! Hello, world!", + None, ) } @@ -42,6 +44,7 @@ from Parser!)", from Parser!)", + None, ) } @@ -54,5 +57,6 @@ fn render_raw_test() -> Result<()> { " This is a raw text {{ 2 + 2 }} ", + None, ) } diff --git a/tests/expressions.rs b/tests/expressions.rs index 0c713d7..a5f0024 100644 --- a/tests/expressions.rs +++ b/tests/expressions.rs @@ -3,66 +3,66 @@ use temple::error::Result; #[test] fn basic_math_expression() -> Result<()> { - assert_render_template_eq("{{10 + 1}}", "11")?; - assert_render_template_eq("{{ -1 }}", "-1")?; - assert_render_template_eq("{{ 1 - 10}}", "-9")?; - assert_render_template_eq("{{ 2 ** 3 }}", "8")?; - assert_render_template_eq("{{ 0.1 + 1 }}", "1.1")?; - assert_render_template_eq("{{ 1 + 0.33 }}", "1.33")?; - assert_render_template_eq("{{ 0.1 - 10.5 }}", "-10.4")?; - assert_render_template_eq("{{ 2 * 10 }}", "20")?; - assert_render_template_eq("{{ 10 / 4 }}", "2.5")?; - assert_render_template_eq("{{ 10 // 4 }}", "2")?; - assert_render_template_eq("{{ 10 % 3 }}", "1")?; - assert_render_template_eq("{{ 10.5 % 3 }}", "1.5")?; - assert_render_template_eq("{{ 2 ** 3 }}", "8")?; - assert_render_template_eq("{{ 2.5 ** 2 }}", "6.25") + assert_render_template_eq("{{10 + 1}}", "11", None)?; + assert_render_template_eq("{{ -1 }}", "-1", None)?; + assert_render_template_eq("{{ 1 - 10}}", "-9", None)?; + assert_render_template_eq("{{ 2 ** 3 }}", "8", None)?; + assert_render_template_eq("{{ 0.1 + 1 }}", "1.1", None)?; + assert_render_template_eq("{{ 1 + 0.33 }}", "1.33", None)?; + assert_render_template_eq("{{ 0.1 - 10.5 }}", "-10.4", None)?; + assert_render_template_eq("{{ 2 * 10 }}", "20", None)?; + assert_render_template_eq("{{ 10 / 4 }}", "2.5", None)?; + assert_render_template_eq("{{ 10 // 4 }}", "2", None)?; + assert_render_template_eq("{{ 10 % 3 }}", "1", None)?; + assert_render_template_eq("{{ 10.5 % 3 }}", "1.5", None)?; + assert_render_template_eq("{{ 2 ** 3 }}", "8", None)?; + assert_render_template_eq("{{ 2.5 ** 2 }}", "6.25", None) } #[test] fn basic_string_expression() -> Result<()> { - assert_render_template_eq("{{ \"hello, world!\" }}", "hello, world!")?; - assert_render_template_eq("{{ \"123\" * 3 }}", "123123123")?; - assert_render_template_eq("{{ \"abc\" * 0 }}", "")?; - assert_render_template_eq("{{ \"hello\" + \" \" + \"world\"}}", "hello world")?; - assert_render_template_eq("{{ \"hello \" ~ 123 }}", "hello 123")?; - assert_render_template_eq("{{ \"hello\" ~ \" \" ~ false }}", "hello false") + assert_render_template_eq("{{ \"hello, world!\" }}", "hello, world!", None)?; + assert_render_template_eq("{{ \"123\" * 3 }}", "123123123", None)?; + assert_render_template_eq("{{ \"abc\" * 0 }}", "", None)?; + assert_render_template_eq("{{ \"hello\" + \" \" + \"world\"}}", "hello world", None)?; + assert_render_template_eq("{{ \"hello \" ~ 123 }}", "hello 123", None)?; + assert_render_template_eq("{{ \"hello\" ~ \" \" ~ false }}", "hello false", None) } #[test] fn math_order_expression() -> Result<()> { - assert_render_template_eq("{{ ( 1 + 4 ) * 3 - 1 }}", "14")?; - assert_render_template_eq("{{ ( 1 + 4 ) * (3 - 1) }}", "10")?; - assert_render_template_eq("{{ 1 + 4 * 3 - 1 }}", "12")?; - assert_render_template_eq("{{ -(-1) }}", "1") - // assert_render_template_eq("{{ 5 - 2 - 2 }}", "1") TODO: solve left associative operations. + assert_render_template_eq("{{ ( 1 + 4 ) * 3 - 1 }}", "14", None)?; + assert_render_template_eq("{{ ( 1 + 4 ) * (3 - 1) }}", "10", None)?; + assert_render_template_eq("{{ 1 + 4 * 3 - 1 }}", "12", None)?; + assert_render_template_eq("{{ -(-1) }}", "1", None) + // assert_render_template_eq("{{ 5 - 2 - 2 }}", "1", None) TODO: solve left associative operations. } #[test] fn logical_compare() -> Result<()> { - assert_render_template_eq("{{ 1 == 1 }}", "true")?; - assert_render_template_eq("{{ 1 == 1.0 }}", "true")?; - assert_render_template_eq("{{ 2 > 1.0 }}", "true")?; - assert_render_template_eq("{{ 2.7 < 3.14 }}", "true")?; - assert_render_template_eq("{{ 10 >= -5.0 }}", "true")?; - assert_render_template_eq("{{ 5.0 <= 5 }}", "true")?; - assert_render_template_eq("{{ true != true }}", "false")?; - assert_render_template_eq("{{ false == false }}", "true")?; - assert_render_template_eq("{{ not false == false }}", "false")?; - assert_render_template_eq("{{ \"foo\" == \"bar\" }}", "false")?; - assert_render_template_eq("{{ \"foo\" == \"foo\" }}", "true")?; - assert_render_template_eq("{{ \"bar\" != \"bara\" }}", "true") + assert_render_template_eq("{{ 1 == 1 }}", "true", None)?; + assert_render_template_eq("{{ 1 == 1.0 }}", "true", None)?; + assert_render_template_eq("{{ 2 > 1.0 }}", "true", None)?; + assert_render_template_eq("{{ 2.7 < 3.14 }}", "true", None)?; + assert_render_template_eq("{{ 10 >= -5.0 }}", "true", None)?; + assert_render_template_eq("{{ 5.0 <= 5 }}", "true", None)?; + assert_render_template_eq("{{ true != true }}", "false", None)?; + assert_render_template_eq("{{ false == false }}", "true", None)?; + assert_render_template_eq("{{ not false == false }}", "false", None)?; + assert_render_template_eq("{{ \"foo\" == \"bar\" }}", "false", None)?; + assert_render_template_eq("{{ \"foo\" == \"foo\" }}", "true", None)?; + assert_render_template_eq("{{ \"bar\" != \"bara\" }}", "true", None) } #[test] fn logical_operators() -> Result<()> { - assert_render_template_eq("{{ true and false }}", "false")?; - assert_render_template_eq("{{ true and true }}", "true")?; - assert_render_template_eq("{{ false or false }}", "false")?; - assert_render_template_eq("{{ false or true }}", "true") + assert_render_template_eq("{{ true and false }}", "false", None)?; + assert_render_template_eq("{{ true and true }}", "true", None)?; + assert_render_template_eq("{{ false or false }}", "false", None)?; + assert_render_template_eq("{{ false or true }}", "true", None) } #[test] fn accessors() -> Result<()> { - assert_render_template_eq("{{ \"hola\"[2] }}", "l") + assert_render_template_eq("{{ \"hola\"[2] }}", "l", None) } diff --git a/tests/statement_if.rs b/tests/statement_if.rs index 063a5fd..1418c29 100644 --- a/tests/statement_if.rs +++ b/tests/statement_if.rs @@ -10,6 +10,7 @@ Hello, world! " Hello, world! ", + None, ) } @@ -20,6 +21,7 @@ fn dont_render_if_body() -> Result<()> { this not {% endif %}", "Only render this.", + None, ) } @@ -30,6 +32,7 @@ fn render_else() -> Result<()> { This should not be rendered {% else %}Rendered from else branch{% endif %}", "Rendered from else branch", + None, ) } @@ -42,5 +45,6 @@ fn render_elif() -> Result<()> { {% elif 5 == 5 %}Rendered from elif branch{% else %} Ignored{% endif %}", "Rendered from elif branch", + None, ) } diff --git a/tests/utils.rs b/tests/utils.rs index b1005a8..a698fa5 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -1,13 +1,20 @@ use std::rc::Rc; use temple::error::Result; +use temple::value::ValuesMap; use temple::{Template, TemplateEnv}; -pub fn assert_render_template_eq(input: &str, expected: &str) -> Result<()> { +pub fn assert_render_template_eq( + input: &str, + expected: &str, + params: Option<&ValuesMap>, +) -> Result<()> { let temp_env = TemplateEnv::default(); let template_env = Rc::new(&temp_env); let mut template = Template::new(&template_env)?; template.load(input)?; - let result = template.render_as_string()?; + let default_context = &ValuesMap::default(); + let context = params.unwrap_or(&default_context); + let result = template.render_as_string(&context)?; assert_eq!(result, expected.to_string()); Ok(()) } diff --git a/tests/whitespace_control.rs b/tests/whitespace_control.rs index c8d7f58..7a02981 100644 --- a/tests/whitespace_control.rs +++ b/tests/whitespace_control.rs @@ -7,17 +7,20 @@ fn render_raw_with_whitespace_control() -> Result<()> { "{% raw -%} Some text {%- endraw %}", "Some text", + None, )?; assert_render_template_eq( " {%- raw %} Some text {% endraw -%} ", " Some text\n ", + None, )?; assert_render_template_eq( " {%- raw -%} Some text {%- endraw -%}", "Some text", + None, ) } @@ -27,5 +30,6 @@ fn render_statement_with_whitespace_control() -> Result<()> { " {%- if true -%} Text striped {%- endif %}", "Text striped", + None, ) }