From f02ade3b94e0eb7f97498439142a2448ebdcdfcc Mon Sep 17 00:00:00 2001
From: Dirkjan Ochtman <dirkjan@ochtman.nl>
Date: Tue, 5 Sep 2017 20:34:18 +0200
Subject: Introduce attribute parameter to disable escaping

---
 askama_shared/src/generator.rs | 14 +++++++++-----
 askama_shared/src/input.rs     | 26 +++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index 7fbc5d9..d8b3a42 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -352,16 +352,20 @@ impl<'a> Generator<'a> {
         }
     }
 
-    fn write_expr(&mut self, ws: &WS, s: &Expr) {
+    fn write_expr(&mut self, state: &'a State, ws: &WS, s: &Expr) {
         self.handle_ws(ws);
         self.write("let askama_expr = &");
         let wrapped = self.visit_expr(s);
         self.writeln(";");
 
+        use self::DisplayWrap::*;
+        use super::input::EscapeMode::*;
         self.write("writer.write_fmt(format_args!(\"{}\", ");
-        self.write(match wrapped {
-            DisplayWrap::Wrapped => "askama_expr",
-            DisplayWrap::Unwrapped => "&::askama::MarkupDisplay::from(askama_expr)",
+        self.write(match (wrapped, &state.input.meta.escaping) {
+            (Wrapped, &Html) |
+            (Wrapped, &None) |
+            (Unwrapped, &None) => "askama_expr",
+            (Unwrapped, &Html) => "&::askama::MarkupDisplay::from(askama_expr)",
         });
         self.writeln("))?;");
     }
@@ -508,7 +512,7 @@ impl<'a> Generator<'a> {
             match *n {
                 Node::Lit(lws, val, rws) => { self.write_lit(lws, val, rws); }
                 Node::Comment() => {},
-                Node::Expr(ref ws, ref val) => { self.write_expr(ws, val); },
+                Node::Expr(ref ws, ref val) => { self.write_expr(state, ws, val); },
                 Node::LetDecl(ref ws, ref var) => { self.write_let_decl(ws, var); },
                 Node::Let(ref ws, ref var, ref val) => { self.write_let(ws, var, val); },
                 Node::Cond(ref conds, ref ws) => {
diff --git a/askama_shared/src/input.rs b/askama_shared/src/input.rs
index 73b9a60..40dc39f 100644
--- a/askama_shared/src/input.rs
+++ b/askama_shared/src/input.rs
@@ -32,6 +32,7 @@ impl<'a> TemplateInput<'a> {
 pub struct TemplateMeta<'a> {
     source: Source<'a>,
     pub print: Print,
+    pub escaping: EscapeMode,
 }
 
 impl<'a> TemplateMeta<'a> {
@@ -46,6 +47,7 @@ impl<'a> TemplateMeta<'a> {
         let attr = attr.unwrap();
         let mut source = None;
         let mut print = Print::None;
+        let mut escaping = EscapeMode::Html;
         if let syn::MetaItem::List(_, ref inner) = attr.value {
             for nm_item in inner {
                 if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
@@ -66,6 +68,11 @@ impl<'a> TemplateMeta<'a> {
                             } else {
                                 panic!("print value must be string literal");
                             },
+                            "escape" => if let syn::Lit::Str(ref s, _) = *val {
+                                escaping = s.into();
+                            } else {
+                                panic!("escape value must be string literal");
+                            },
                             _ => { panic!("unsupported annotation key found") }
                         }
                     }
@@ -74,7 +81,7 @@ impl<'a> TemplateMeta<'a> {
         }
 
         match source {
-            Some(s) => TemplateMeta { source: s, print },
+            Some(s) => TemplateMeta { source: s, print, escaping },
             None => panic!("template path or source not found in struct attributes"),
         }
     }
@@ -85,6 +92,23 @@ enum Source<'a> {
     Source(&'a str),
 }
 
+#[derive(PartialEq)]
+pub enum EscapeMode {
+    Html,
+    None,
+}
+
+impl<'a> From<&'a String> for EscapeMode {
+    fn from(s: &'a String) -> EscapeMode {
+        use self::EscapeMode::*;
+        match s.as_ref() {
+            "html" => Html,
+            "none" => None,
+            v => panic!("invalid value for escape option: {}", v),
+        }
+    }
+}
+
 #[derive(PartialEq)]
 pub enum Print {
     All,
-- 
cgit