add in-memory includes via include_template

This commit is contained in:
pantor
2018-05-14 20:21:29 +02:00
parent 95e3712aaf
commit cb18e2cd0c
3 changed files with 41 additions and 14 deletions

View File

@@ -157,9 +157,14 @@ render("{% if not guest_count %}…{% endif %}", data); // True
#### 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

View File

@@ -614,6 +614,10 @@ class Parser {
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 @@ public:
{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 @@ public:
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 @@ public:
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);

View File

@@ -288,19 +288,30 @@ TEST_CASE("combinations") {
}
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") {