aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askama_shared/src/generator.rs10
-rw-r--r--askama_shared/src/lib.rs43
-rw-r--r--askama_shared/src/parser.rs13
-rw-r--r--testing/templates/import.html2
-rw-r--r--testing/tests/macro.rs12
5 files changed, 76 insertions, 4 deletions
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index e92a2c6..e135c13 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -12,8 +12,8 @@ use std::collections::{HashMap, HashSet};
use syn;
-pub fn generate(input: &TemplateInput, nodes: &[Node]) -> String {
- Generator::default().build(&State::new(input, nodes))
+pub fn generate(input: &TemplateInput, nodes: &[Node], imported: &HashMap<&str, Macro>) -> String {
+ Generator::default().build(&State::new(input, nodes, imported))
}
struct State<'a> {
@@ -26,7 +26,7 @@ struct State<'a> {
}
impl<'a> State<'a> {
- fn new<'n>(input: &'n TemplateInput, nodes: &'n [Node]) -> State<'n> {
+ fn new<'n>(input: &'n TemplateInput, nodes: &'n [Node], imported: &'n HashMap<&'n str, Macro<'n>>) -> State<'n> {
let mut base: Option<&Expr> = None;
let mut blocks = Vec::new();
let mut macros = HashMap::new();
@@ -47,6 +47,9 @@ impl<'a> State<'a> {
_ => {},
}
}
+ for (name, ref m) in imported {
+ macros.insert(name, m);
+ }
State {
input,
nodes,
@@ -351,6 +354,7 @@ impl<'a> Generator<'a> {
},
Node::Call(ref ws, name, ref args) => self.write_call(state, ws, name, args),
Node::Macro(_, _) |
+ Node::Import(_, _) |
Node::Extends(_) => {
if let AstLevel::Nested = level {
panic!("macro or extend blocks only allowed at the top level");
diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs
index 066faca..a7deaff 100644
--- a/askama_shared/src/lib.rs
+++ b/askama_shared/src/lib.rs
@@ -21,7 +21,11 @@ mod input;
mod parser;
use input::Print;
+use parser::{Node, Macro};
+use std::borrow::Cow;
+use std::collections::HashMap;
+use std::path::Path;
/// Takes a `syn::DeriveInput` and generates source code for it
///
@@ -33,16 +37,53 @@ use input::Print;
pub fn build_template(ast: &syn::DeriveInput) -> String {
let data = input::TemplateInput::new(ast);
let nodes = parser::parse(data.source.as_ref());
+ let imports = Imports::new(&nodes, &data.path);
+ let imported = imports.parse();
if data.meta.print == Print::Ast || data.meta.print == Print::All {
println!("{:?}", nodes);
}
- let code = generator::generate(&data, &nodes);
+ let code = generator::generate(&data, &nodes, &imported);
if data.meta.print == Print::Code || data.meta.print == Print::All {
println!("{}", code);
}
code
}
+
+pub struct Imports<'a> {
+ pub sources: Vec<Cow<'a, str>>
+}
+
+impl <'a> Imports<'a> {
+ pub fn new(parent_nodes: &'a [Node], parent_path: &'a Path) -> Imports<'a> {
+ let sources = parent_nodes.iter().filter_map(|n| {
+ match *n {
+ Node::Import(_, ref import_path) => {
+ let path = path::find_template_from_path(import_path, Some(parent_path));
+ let src = path::get_template_source(&path);
+ Some(Cow::Owned(src))
+ },
+ _ => None,
+ }
+ }).collect();
+ Imports {
+ sources,
+ }
+ }
+
+ pub fn parse(&'a self) -> HashMap<&'a str, Macro<'a>> {
+ self.sources.iter()
+ .flat_map(|s| parser::parse(s.as_ref()))
+ .filter_map(|n| {
+ match n {
+ Node::Macro(name, m) => Some((name, m)),
+ _ => None,
+ }})
+ .collect()
+ }
+}
+
+
mod errors {
error_chain! {
foreign_links {
diff --git a/askama_shared/src/parser.rs b/askama_shared/src/parser.rs
index ab79a31..083e96b 100644
--- a/askama_shared/src/parser.rs
+++ b/askama_shared/src/parser.rs
@@ -42,6 +42,7 @@ pub enum Node<'a> {
Extends(Expr<'a>),
BlockDef(WS, &'a str, Vec<Node<'a>>, WS),
Include(WS, &'a str),
+ Import(WS, &'a str),
Macro(&'a str, Macro<'a>),
}
@@ -388,6 +389,17 @@ named!(block_include<Node>, do_parse!(
}))
));
+named!(block_import<Node>, do_parse!(
+ pws: opt!(tag_s!("-")) >>
+ ws!(tag_s!("import")) >>
+ name: ws!(expr_str_lit) >>
+ nws: opt!(tag_s!("-")) >>
+ (Node::Import(WS(pws.is_some(), nws.is_some()), match name {
+ Expr::StrLit(s) => s,
+ _ => panic!("import path must be a string literal"),
+ }))
+));
+
named!(block_macro<Node>, do_parse!(
pws1: opt!(tag_s!("-")) >>
ws!(tag_s!("macro")) >>
@@ -420,6 +432,7 @@ named!(block_node<Node>, do_parse!(
block_for |
block_extends |
block_include |
+ block_import |
block_block |
block_macro
) >>
diff --git a/testing/templates/import.html b/testing/templates/import.html
new file mode 100644
index 0000000..87d7969
--- /dev/null
+++ b/testing/templates/import.html
@@ -0,0 +1,2 @@
+{% import "macro.html" -%}
+{%- call thrice(s) %}
diff --git a/testing/tests/macro.rs b/testing/tests/macro.rs
index 72f578e..25d95d8 100644
--- a/testing/tests/macro.rs
+++ b/testing/tests/macro.rs
@@ -14,3 +14,15 @@ fn test_macro() {
let t = MacroTemplate { s: "foo" };
assert_eq!(t.render().unwrap(), "foo foo foo");
}
+
+#[derive(Template)]
+#[template(path = "import.html")]
+struct ImportTemplate<'a> {
+ s: &'a str,
+}
+
+#[test]
+fn test_import() {
+ let t = ImportTemplate { s: "foo" };
+ assert_eq!(t.render().unwrap(), "foo foo foo");
+}