add in-memory includes via include_template
diff --git a/README.md b/README.md
index 9a59048..628c075 100644
--- a/README.md
+++ b/README.md
@@ -157,9 +157,14 @@
#### Includes
-This includes other template files, relative from the current file location.
+You can either include other template files or already parsed templates.
```
-{% include "footer.html" %}
+// Other template files are included relative from the current file location
+render({% include "footer.html" %}, data);
+
+// To include in-memory templates, add them to the environment first
+env.include_template("footer", temp);
+render({% include "footer" %}, data);
```
### Functions
diff --git a/src/inja.hpp b/src/inja.hpp
index b1d4c65..56f051b 100644
--- a/src/inja.hpp
+++ b/src/inja.hpp
@@ -614,6 +614,10 @@
public:
ElementNotation element_notation = ElementNotation::Pointer;
+ std::map<Parsed::CallbackSignature, Regex, std::greater<Parsed::CallbackSignature>> regex_map_callbacks;
+
+ std::map<const std::string, Template> included_templates;
+
/*!
@brief create a corresponding regex for a function name with a number of arguments seperated by ,
*/
@@ -704,8 +708,6 @@
{Parsed::Function::ReadJson, Regex{"\\s*([^\\(\\)]*\\S)\\s*"}}
};
- std::map<Parsed::CallbackSignature, Regex, std::greater<Parsed::CallbackSignature>> regex_map_callbacks;
-
Parser() { }
Parsed::ElementExpression parse_expression(const std::string& input) {
@@ -859,11 +861,16 @@
break;
}
case Parsed::Statement::Include: {
- std::string included_filename = path + match_statement.str(1);
- Template included_template = parse_template(included_filename);
- for (auto& element: included_template.parsed_template().children) {
- result.emplace_back(element);
+ std::string template_name = match_statement.str(1);
+ Template included_template;
+ if (included_templates.find( template_name ) != included_templates.end()) {
+ included_template = included_templates[template_name];
+ } else {
+ included_template = parse_template(path + template_name);
}
+
+ auto children = included_template.parsed_template().children;
+ result.insert(result.end(), children.begin(), children.end());
break;
}
}
@@ -1022,6 +1029,10 @@
renderer.map_callbacks[signature] = callback;
}
+ void include_template(std::string name, const Template& temp) {
+ parser.included_templates[name] = temp;
+ }
+
template<typename T = json>
T get_argument(const Parsed::Arguments& args, int index, const json& data) {
return renderer.eval_expression<T>(args[index], data);
diff --git a/test/src/unit-renderer.cpp b/test/src/unit-renderer.cpp
index 4acad8c..d2f8a88 100644
--- a/test/src/unit-renderer.cpp
+++ b/test/src/unit-renderer.cpp
@@ -288,19 +288,30 @@
}
TEST_CASE("templates") {
- inja::Environment env = inja::Environment();
- inja::Template temp = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
-
json data;
data["name"] = "Peter";
data["city"] = "Brunswick";
data["is_happy"] = true;
- CHECK( env.render_template(temp, data) == "Peter" );
+ SECTION("reuse") {
+ inja::Environment env = inja::Environment();
+ inja::Template temp = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
- data["is_happy"] = false;
+ CHECK( env.render_template(temp, data) == "Peter" );
- CHECK( env.render_template(temp, data) == "Brunswick" );
+ data["is_happy"] = false;
+
+ CHECK( env.render_template(temp, data) == "Brunswick" );
+ }
+
+ SECTION("include") {
+ inja::Environment env = inja::Environment();
+ inja::Template t1 = env.parse("Hello {{ name }}");
+ env.include_template("greeting", t1);
+
+ inja::Template t2 = env.parse("{% include \"greeting\" %}!");
+ CHECK( env.render_template(t2, data) == "Hello Peter!" );
+ }
}
TEST_CASE("other-syntax") {