diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp index 4cd530d..d3ced6f 100644 --- a/include/inja/renderer.hpp +++ b/include/inja/renderer.hpp @@ -454,7 +454,7 @@ class Renderer { break; } case Bytecode::Op::Include: - Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref())->second, data); + Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref())->second, *m_data); break; case Bytecode::Op::Callback: { auto callback = m_callbacks.find_callback(bc.str, bc.args); diff --git a/single_include/inja/inja.hpp b/single_include/inja/inja.hpp index 80b3d68..a6ad38e 100644 --- a/single_include/inja/inja.hpp +++ b/single_include/inja/inja.hpp @@ -1360,6 +1360,9 @@ enum class ElementNotation { Pointer }; +/*! + * \brief Class for lexer configuration. + */ struct LexerConfig { std::string statement_open {"{%"}; std::string statement_close {"%}"}; @@ -1390,6 +1393,9 @@ struct LexerConfig { } }; +/*! + * \brief Class for parser configuration. + */ struct ParserConfig { ElementNotation notation {ElementNotation::Dot}; }; @@ -1547,6 +1553,9 @@ using namespace nlohmann; using Arguments = std::vector; using CallbackFunction = std::function; +/*! + * \brief Class for builtin functions and user-defined callbacks. + */ class FunctionStorage { public: void add_builtin(nonstd::string_view name, unsigned int num_args, Bytecode::Op op) { @@ -1637,6 +1646,9 @@ class FunctionStorage { namespace inja { +/*! + * \brief Helper-class for the inja Parser. + */ struct Token { enum class Kind { Text, @@ -1748,6 +1760,9 @@ namespace string_view { namespace inja { +/*! + * \brief Class for lexing an inja Template. + */ class Lexer { enum class State { Text, @@ -2052,6 +2067,9 @@ class Lexer { namespace inja { +/*! + * \brief The main inja Template. + */ struct Template { std::vector bytecodes; std::string content; @@ -2115,6 +2133,9 @@ class ParserStatic { FunctionStorage functions; }; +/*! + * \brief Class for parsing an inja Template. + */ class Parser { public: explicit Parser(const ParserConfig& parser_config, const LexerConfig& lexer_config, TemplateStorage& included_templates): m_config(parser_config), m_lexer(lexer_config), m_included_templates(included_templates), m_static(ParserStatic::get_instance()) { } @@ -2691,6 +2712,9 @@ inline nonstd::string_view convert_dot_to_json_pointer(nonstd::string_view dot, return nonstd::string_view(out.data(), out.size()); } +/*! + * \brief Class for rendering a Template with data. + */ class Renderer { std::vector& get_args(const Bytecode& bc) { m_tmp_args.clear(); @@ -3118,7 +3142,7 @@ class Renderer { break; } case Bytecode::Op::Include: - Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref())->second, data); + Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref())->second, *m_data); break; case Bytecode::Op::Callback: { auto callback = m_callbacks.find_callback(bc.str, bc.args); @@ -3251,6 +3275,9 @@ namespace inja { using namespace nlohmann; +/*! + * \brief Class for changing the configuration. + */ class Environment { class Impl { public: diff --git a/test/unit-renderer.cpp b/test/unit-renderer.cpp index 1243470..b56cc45 100644 --- a/test/unit-renderer.cpp +++ b/test/unit-renderer.cpp @@ -380,6 +380,16 @@ TEST_CASE("templates") { CHECK( env.render(t2, data) == "Hello Peter!" ); CHECK_THROWS_WITH( env.parse("{% include \"does-not-exist\" %}!"), "[inja.exception.file_error] failed accessing file at 'does-not-exist'" ); } + + SECTION("include-in-loop") { + json loop_data; + loop_data["cities"] = json::array({{{"name", "Munich"}}, {{"name", "New York"}}}); + + inja::Environment env; + env.include_template("city.tpl", env.parse("{{ loop.index }}:{{ city.name }};")); + + CHECK( env.render("{% for city in cities %}{% include \"city.tpl\" %}{% endfor %}", loop_data) == "0:Munich;1:New York;" ); + } }