From cb18e2cd0c0b1b9fba474d556e340afb978c42fc Mon Sep 17 00:00:00 2001 From: pantor Date: Mon, 14 May 2018 20:21:29 +0200 Subject: [PATCH 1/4] add in-memory includes via include_template --- README.md | 9 +++++++-- src/inja.hpp | 23 +++++++++++++++++------ test/src/unit-renderer.cpp | 23 +++++++++++++++++------ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9a59048..628c075 100644 --- a/README.md +++ b/README.md @@ -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 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 @@ class Parser { public: ElementNotation element_notation = ElementNotation::Pointer; + std::map> regex_map_callbacks; + + std::map 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> 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 T get_argument(const Parsed::Arguments& args, int index, const json& data) { return renderer.eval_expression(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("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") { From 394610b002ed88e293a7a5f3608479e3ac627f81 Mon Sep 17 00:00:00 2001 From: pantor Date: Tue, 15 May 2018 19:52:41 +0200 Subject: [PATCH 2/4] order includes --- src/inja.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/inja.hpp b/src/inja.hpp index 56f051b..1c6639d 100644 --- a/src/inja.hpp +++ b/src/inja.hpp @@ -38,15 +38,16 @@ SOFTWARE. #endif -#include -#include +#include #include #include #include +#include #include -#include -#include +#include +#include #include +#include namespace inja { From 0029a130abdf37138ae182480664382599a9e036 Mon Sep 17 00:00:00 2001 From: pantor Date: Tue, 15 May 2018 20:03:15 +0200 Subject: [PATCH 3/4] clean meson file --- meson.build | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 6446a20..3aff495 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,7 @@ project('inja', 'cpp', default_options : ['cpp_std=c++11']) -inja_inc = include_directories('src') - inja_dep = declare_dependency( - include_directories : inja_inc + include_directories : include_directories('src') ) subdir('test') From 71cfb21e618b6aca150cc9d4bf8bed4fd3076c0f Mon Sep 17 00:00:00 2001 From: pantor Date: Tue, 15 May 2018 20:23:09 +0200 Subject: [PATCH 4/4] include nlohmann/json in inja directly --- README.md | 6 +++--- src/inja.hpp | 6 +----- {test/thirdparty => src}/nlohmann/LICENSE.MIT | 0 {test/thirdparty => src}/nlohmann/json.hpp | 0 test/meson.build | 3 +-- test/{thirdparty => src}/catch/LICENSE.txt | 0 test/{thirdparty => src}/catch/catch.hpp | 0 test/src/unit-files.cpp | 2 +- test/src/unit-renderer.cpp | 2 +- test/src/unit-string-helper.cpp | 2 +- 10 files changed, 8 insertions(+), 13 deletions(-) rename {test/thirdparty => src}/nlohmann/LICENSE.MIT (100%) rename {test/thirdparty => src}/nlohmann/json.hpp (100%) rename test/{thirdparty => src}/catch/LICENSE.txt (100%) rename test/{thirdparty => src}/catch/catch.hpp (100%) diff --git a/README.md b/README.md index 628c075..4bb870c 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ inja::render("Hello {{ name }}!", data); // Returns "Hello world!" ## Integration -Inja is a headers only library, which can be downloaded from the [releases](https://github.com/pantor/inja/releases) or directly from the `src/` folder. Inja uses json by nlohmann as its single dependency, so make sure that it is included before inja. json can be found [here](https://github.com/nlohmann/json/releases). +Inja is a headers only library, which can be downloaded from the [releases](https://github.com/pantor/inja/releases) or directly from the `src/` folder. Inja uses `nlohmann/json.hpp` as its single dependency, so make sure it can be included from `inja.hpp`. json can be downloaded [here](https://github.com/nlohmann/json/releases). Then integration is as easy as: ```c++ -#include "json.hpp" -#include "inja.hpp" +#include +#include // For convenience using namespace inja; diff --git a/src/inja.hpp b/src/inja.hpp index 1c6639d..f2c27da 100644 --- a/src/inja.hpp +++ b/src/inja.hpp @@ -33,16 +33,12 @@ SOFTWARE. #define PANTOR_INJA_VERSION_PATCH 1 -#ifndef NLOHMANN_JSON_HPP - static_assert(false, "nlohmann/json not found."); -#endif - - #include #include #include #include #include +#include #include #include #include diff --git a/test/thirdparty/nlohmann/LICENSE.MIT b/src/nlohmann/LICENSE.MIT similarity index 100% rename from test/thirdparty/nlohmann/LICENSE.MIT rename to src/nlohmann/LICENSE.MIT diff --git a/test/thirdparty/nlohmann/json.hpp b/src/nlohmann/json.hpp similarity index 100% rename from test/thirdparty/nlohmann/json.hpp rename to src/nlohmann/json.hpp diff --git a/test/meson.build b/test/meson.build index ee6d295..5e364d8 100644 --- a/test/meson.build +++ b/test/meson.build @@ -4,8 +4,7 @@ unit_test = executable( 'src/unit-files.cpp', 'src/unit-renderer.cpp', 'src/unit-string-helper.cpp', - dependencies: inja_dep, - include_directories: include_directories('thirdparty') + dependencies: inja_dep ) test('Inja unit test', unit_test) diff --git a/test/thirdparty/catch/LICENSE.txt b/test/src/catch/LICENSE.txt similarity index 100% rename from test/thirdparty/catch/LICENSE.txt rename to test/src/catch/LICENSE.txt diff --git a/test/thirdparty/catch/catch.hpp b/test/src/catch/catch.hpp similarity index 100% rename from test/thirdparty/catch/catch.hpp rename to test/src/catch/catch.hpp diff --git a/test/src/unit-files.cpp b/test/src/unit-files.cpp index 60b1352..9d71a88 100644 --- a/test/src/unit-files.cpp +++ b/test/src/unit-files.cpp @@ -1,6 +1,6 @@ #include "catch/catch.hpp" -#include "nlohmann/json.hpp" #include "inja.hpp" +#include "nlohmann/json.hpp" using json = nlohmann::json; diff --git a/test/src/unit-renderer.cpp b/test/src/unit-renderer.cpp index d2f8a88..58c2d23 100644 --- a/test/src/unit-renderer.cpp +++ b/test/src/unit-renderer.cpp @@ -1,6 +1,6 @@ #include "catch/catch.hpp" -#include "nlohmann/json.hpp" #include "inja.hpp" +#include "nlohmann/json.hpp" diff --git a/test/src/unit-string-helper.cpp b/test/src/unit-string-helper.cpp index 87f4618..5e026dd 100644 --- a/test/src/unit-string-helper.cpp +++ b/test/src/unit-string-helper.cpp @@ -1,6 +1,6 @@ #include "catch/catch.hpp" -#include "nlohmann/json.hpp" #include "inja.hpp" +#include "nlohmann/json.hpp"