Repository: djc/askama
Pull request #231 (2019-04-15 12:37:02)

WIP: Add raw block
I'm trying to implement `raw` block like the one in the _Jinja_.

```
{% raw %}
  <h1>Hello, {{ name}}</h1> 
{% endraw %}
```

But I think I did it totally not how it supposed to be added, would be great to have an advice how to make it more idiomatic.

djc: This looks pretty good! I'd prefer to not to have the `Input` type in the AST node type like this. Also, can you please add a test in `testing/tests` that exercises? Can go in `simple.rs` and should be pretty simple to write if you look at the other tests.

Thanks for working on this!

Patch:
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index 4a6eb89..aa91de0 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -345,6 +345,11 @@ impl<'a> Generator<'a> {
                     self.flush_ws(m.ws1);
                     self.prepare_ws(m.ws2);
                 }
+                Node::Raw(ws1, contents, ws2) => {
+                    self.handle_ws(ws1);
+                    self.buf_writable.push(Writable::Lit(contents));
+                    self.handle_ws(ws2);
+                }
                 Node::Import(ws, _, _) => {
                     if level != AstLevel::Top {
                         panic!("import blocks only allowed at the top level");
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index 2a342fc..c880202 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -72,6 +72,7 @@ pub enum Node<'a> {
     Include(WS, &'a str),
     Import(WS, &'a str, &'a str),
     Macro(&'a str, Macro<'a>),
+    Raw(WS, &'a str, WS),
 }
 
 pub type Cond<'a> = (WS, Option<Expr<'a>>, Vec<Node<'a>>);
@@ -126,6 +127,7 @@ fn split_ws_parts(s: &[u8]) -> Node {
     )
 }
 
+#[derive(Debug)]
 enum ContentState {
     Any,
     Brace(usize),
@@ -836,6 +838,24 @@ named_args!(block_macro<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
     })
 ));
 
+named_args!(block_raw<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
+    pws1: opt!(tag!("-")) >>
+    ws!(tag!("raw")) >>
+    nws1: opt!(tag!("-")) >>
+    call!(tag_block_end, s) >>
+    contents: take_until!("{% endraw %}") >>
+    call!(tag_block_start, s) >>
+    pws2: opt!(tag!("-")) >>
+    ws!(tag!("endraw")) >>
+    nws2: opt!(tag!("-")) >>
+    ({
+        let str_contents = str::from_utf8(&contents).unwrap();
+        (Node::Raw(WS(pws1.is_some(), nws1.is_some()),
+                   str_contents,
+                   WS(pws2.is_some(), nws2.is_some())))
+    })
+));
+
 named_args!(block_node<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
     call!(tag_block_start, s) >>
     contents: alt!(
@@ -848,7 +868,8 @@ named_args!(block_node<'a>(s: &'a Syntax<'a>) <Input<'a>, Node<'a>>, do_parse!(
         block_include |
         block_import |
         call!(block_block, s) |
-        call!(block_macro, s)
+        call!(block_macro, s) |
+        call!(block_raw, s)
     ) >>
     call!(tag_block_end, s) >>
     (contents)


Test patch:
diff --git a/testing/templates/raw-complex.html b/testing/templates/raw-complex.html
new file mode 100644
index 0000000..c3e5a7a
--- /dev/null
+++ b/testing/templates/raw-complex.html
@@ -0,0 +1,5 @@
+{% raw %}
+{% block name %}
+  <span>{{ name }}</span>
+{% endblock %}
+{% endraw %}
diff --git a/testing/templates/raw-simple.html b/testing/templates/raw-simple.html
new file mode 100644
index 0000000..125a0b5
--- /dev/null
+++ b/testing/templates/raw-simple.html
@@ -0,0 +1,3 @@
+{% raw %}
+<span>{{ name }}</span>
+{% endraw %}
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index f192609..e4239ce 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -300,6 +300,29 @@ fn test_empty() {
     assert_eq!(Empty.render().unwrap(), "foo");
 }
 
+#[derive(Template)]
+#[template(path = "raw-simple.html")]
+struct RawTemplate;
+
+#[test]
+fn test_raw_simple() {
+    let template = RawTemplate;
+    assert_eq!(template.render().unwrap(), "\n<span>{{ name }}</span>\n");
+}
+
+#[derive(Template)]
+#[template(path = "raw-complex.html")]
+struct RawTemplateComplex;
+
+#[test]
+fn test_raw_complex() {
+    let template = RawTemplateComplex;
+    assert_eq!(
+        template.render().unwrap(),
+        "\n{% block name %}\n  <span>{{ name }}</span>\n{% endblock %}\n"
+    );
+}
+
 mod without_import_on_derive {
     #[derive(askama::Template)]
     #[template(source = "foo", ext = "txt")]