retain scope when including a template (#118)

* apply documentation changes to single_include

* retain scope when including a template

* Use data from current scope when rendering an included template.
  This allows included templates to access loop variables, which
  was not possible before.
* Add test
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 @@
           break;
         }
         case Bytecode::Op::Include:
-          Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, data);
+          Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->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 @@
   Pointer
 };
 
+/*!
+ * \brief Class for lexer configuration.
+ */
 struct LexerConfig {
   std::string statement_open {"{%"};
   std::string statement_close {"%}"};
@@ -1390,6 +1393,9 @@
   }
 };
 
+/*!
+ * \brief Class for parser configuration.
+ */
 struct ParserConfig {
   ElementNotation notation {ElementNotation::Dot};
 };
@@ -1547,6 +1553,9 @@
 using Arguments = std::vector<const json*>;
 using CallbackFunction = std::function<json(Arguments& args)>;
 
+/*!
+ * \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 @@
 
 namespace inja {
 
+/*!
+ * \brief Helper-class for the inja Parser.
+ */
 struct Token {
   enum class Kind {
     Text,
@@ -1748,6 +1760,9 @@
 
 namespace inja {
 
+/*!
+ * \brief Class for lexing an inja Template.
+ */
 class Lexer {
   enum class State {
     Text,
@@ -2052,6 +2067,9 @@
 
 namespace inja {
 
+/*!
+ * \brief The main inja Template.
+ */
 struct Template {
   std::vector<Bytecode> bytecodes;
   std::string content;
@@ -2115,6 +2133,9 @@
   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 @@
   return nonstd::string_view(out.data(), out.size());
 }
 
+/*!
+ * \brief Class for rendering a Template with data.
+ */
 class Renderer {
   std::vector<const json*>& get_args(const Bytecode& bc) {
     m_tmp_args.clear();
@@ -3118,7 +3142,7 @@
           break;
         }
         case Bytecode::Op::Include:
-          Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, data);
+          Renderer(m_included_templates, m_callbacks).render_to(os, m_included_templates.find(get_imm(bc)->get_ref<const std::string&>())->second, *m_data);
           break;
         case Bytecode::Op::Callback: {
           auto callback = m_callbacks.find_callback(bc.str, bc.args);
@@ -3251,6 +3275,9 @@
 
 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 @@
 		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;" );
+	}
 }