clang-tidy applied and CMake installation of the single header added (#287)

* Fixed headers and linter marks applied

Headers were wrong.
Applied some linter suggestions. There are still many left.

* CMake adjusted for single header

CMake can now install the single header.
Removed an unneeded header.

---------

Co-authored-by: Berscheid <1885260+pantor@users.noreply.github.com>
This commit is contained in:
Matheus Werny
2024-10-05 09:36:11 +02:00
committed by GitHub
parent 1281271fda
commit 92994bec0a
17 changed files with 163 additions and 71 deletions

View File

@@ -10,6 +10,7 @@ project(inja LANGUAGES CXX VERSION 3.4.0)
option(INJA_USE_EMBEDDED_JSON "Use the shipped json header if not available on the system" ON)
option(INJA_INSTALL "Generate install targets for inja" ON)
option(INJA_INSTALL_SINGLE_HEADER "Install the single header instead" OFF)
option(INJA_EXPORT "Export the current build tree to the package registry" ON)
option(BUILD_TESTING "Build unit tests" ON)
option(INJA_BUILD_TESTS "Build unit tests when BUILD_TESTING is enabled." ON)
@@ -166,11 +167,20 @@ if(INJA_INSTALL)
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
if(INJA_INSTALL_SINGLE_HEADER)
install(
DIRECTORY single_include/inja
DESTINATION ${INJA_INSTALL_INCLUDE_DIR}
FILES_MATCHING PATTERN "*.hpp"
)
else()
install(
DIRECTORY include/inja
DESTINATION ${INJA_INSTALL_INCLUDE_DIR}
FILES_MATCHING PATTERN "*.hpp"
)
endif()
if(INJA_USE_EMBEDDED_JSON)
install(
DIRECTORY third_party/include/nlohmann
@@ -178,6 +188,7 @@ if(INJA_INSTALL)
FILES_MATCHING PATTERN "*.hpp"
)
endif()
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/${INJA_CONFIG_PATH}/injaConfig.cmake"

View File

@@ -3,17 +3,16 @@
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
#include "config.hpp"
#include "function_storage.hpp"
#include "inja.hpp"
#include "parser.hpp"
#include "renderer.hpp"
#include "template.hpp"
#include "utils.hpp"
namespace inja {

View File

@@ -1,6 +1,7 @@
#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
#define INCLUDE_INJA_EXCEPTIONS_HPP_
#include <cstddef>
#include <stdexcept>
#include <string>

View File

@@ -1,9 +1,15 @@
#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
#include <functional>
#include <map>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "inja.hpp"
namespace inja {
using Arguments = std::vector<const json*>;

View File

@@ -2,9 +2,11 @@
#define INCLUDE_INJA_LEXER_HPP_
#include <cctype>
#include <locale>
#include <cstddef>
#include <string_view>
#include "config.hpp"
#include "exceptions.hpp"
#include "token.hpp"
#include "utils.hpp"
@@ -311,7 +313,7 @@ public:
pos += open_start;
// try to match one of the opening sequences, and get the close
std::string_view open_str = m_in.substr(pos);
const std::string_view open_str = m_in.substr(pos);
bool must_lstrip = false;
if (inja::string_view::starts_with(open_str, config.expression_open)) {
if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) {

View File

@@ -1,11 +1,15 @@
#ifndef INCLUDE_INJA_NODE_HPP_
#define INCLUDE_INJA_NODE_HPP_
#include <cstddef>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <tuple>
#include <vector>
#include "function_storage.hpp"
#include "inja.hpp"
#include "utils.hpp"
namespace inja {

View File

@@ -1,20 +1,24 @@
#ifndef INCLUDE_INJA_PARSER_HPP_
#define INCLUDE_INJA_PARSER_HPP_
#include <limits>
#include <cstddef>
#include <fstream>
#include <iterator>
#include <memory>
#include <stack>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "config.hpp"
#include "exceptions.hpp"
#include "function_storage.hpp"
#include "inja.hpp"
#include "lexer.hpp"
#include "node.hpp"
#include "template.hpp"
#include "token.hpp"
#include "utils.hpp"
namespace inja {
@@ -64,7 +68,7 @@ class Parser {
}
inline void add_literal(Arguments &arguments, const char* content_ptr) {
std::string_view data_text(literal_start.data(), tok.text.data() - literal_start.data() + tok.text.size());
const std::string_view data_text(literal_start.data(), tok.text.data() - literal_start.data() + tok.text.size());
arguments.emplace_back(std::make_shared<LiteralNode>(data_text, data_text.data() - content_ptr));
}
@@ -88,8 +92,8 @@ class Parser {
return;
}
std::string original_path = static_cast<std::string>(path);
std::string original_name = template_name;
const std::string original_path = static_cast<std::string>(path);
const std::string original_name = template_name;
if (config.search_included_templates_in_files) {
// Build the relative path
@@ -103,7 +107,7 @@ class Parser {
std::ifstream file;
file.open(template_name);
if (!file.fail()) {
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
const std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
auto include_template = Template(text);
template_storage.emplace(template_name, include_template);
@@ -472,7 +476,7 @@ class Parser {
throw_parser_error("expected id, got '" + tok.describe() + "'");
}
Token key_token = std::move(value_token);
const Token key_token = std::move(value_token);
value_token = tok;
get_next_token();
@@ -533,7 +537,7 @@ class Parser {
throw_parser_error("expected variable name, got '" + tok.describe() + "'");
}
std::string key = static_cast<std::string>(tok.text);
const std::string key = static_cast<std::string>(tok.text);
get_next_token();
auto set_statement_node = std::make_shared<SetStatementNode>(key, tok.text.data() - tmpl.content.c_str());
@@ -627,7 +631,7 @@ public:
}
void parse_into_template(Template& tmpl, std::string_view filename) {
std::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
const std::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
// StringRef path = sys::path::parent_path(filename);
auto sub_parser = Parser(config, lexer.get_config(), template_storage, function_storage);

View File

@@ -2,13 +2,23 @@
#define INCLUDE_INJA_RENDERER_HPP_
#include <algorithm>
#include <array>
#include <cctype>
#include <cmath>
#include <cstddef>
#include <memory>
#include <numeric>
#include <ostream>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include "config.hpp"
#include "exceptions.hpp"
#include "function_storage.hpp"
#include "inja.hpp"
#include "node.hpp"
#include "template.hpp"
#include "utils.hpp"
@@ -69,7 +79,7 @@ class Renderer : public NodeVisitor {
return buffer;
}
void print_data(const std::shared_ptr<json> value) {
void print_data(const std::shared_ptr<json>& value) {
if (value->is_string()) {
if (config.html_autoescape) {
*output_stream << htmlescape(value->get_ref<const json::string_t&>());
@@ -107,7 +117,7 @@ class Renderer : public NodeVisitor {
throw_renderer_error("expression could not be evaluated", expression_list);
}
auto node = not_found_stack.top();
const auto node = not_found_stack.top();
not_found_stack.pop();
throw_renderer_error("variable '" + static_cast<std::string>(node->name) + "' not found", *node);
@@ -116,7 +126,7 @@ class Renderer : public NodeVisitor {
}
void throw_renderer_error(const std::string& message, const AstNode& node) {
SourceLocation loc = get_source_location(current_template->content, node.pos);
const SourceLocation loc = get_source_location(current_template->content, node.pos);
INJA_THROW(RenderError(message, loc));
}
@@ -158,7 +168,7 @@ class Renderer : public NodeVisitor {
template <bool throw_not_found = true> Arguments get_argument_vector(const FunctionNode& node) {
const size_t N = node.arguments.size();
for (auto a : node.arguments) {
for (const auto& a : node.arguments) {
a->accept(*this);
}
@@ -184,7 +194,7 @@ class Renderer : public NodeVisitor {
}
void visit(const BlockNode& node) {
for (auto& n : node.nodes) {
for (const auto& n : node.nodes) {
n->accept(*this);
if (break_rendering) {

View File

@@ -10,7 +10,7 @@ namespace inja {
*/
class StatisticsVisitor : public NodeVisitor {
void visit(const BlockNode& node) {
for (auto& n : node.nodes) {
for (const auto& n : node.nodes) {
n->accept(*this);
}
}
@@ -24,7 +24,7 @@ class StatisticsVisitor : public NodeVisitor {
}
void visit(const FunctionNode& node) {
for (auto& n : node.arguments) {
for (const auto& n : node.arguments) {
n->accept(*this);
}
}

View File

@@ -4,7 +4,6 @@
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "node.hpp"
#include "statistics.hpp"
@@ -23,7 +22,7 @@ struct Template {
explicit Template(const std::string& content): content(content) {}
/// Return number of variables (total number, not distinct ones) in the template
int count_variables() {
int count_variables() const {
auto statistic_visitor = StatisticsVisitor();
root.accept(statistic_visitor);
return statistic_visitor.variable_counter;

View File

@@ -2,7 +2,7 @@
#define INCLUDE_INJA_UTILS_HPP_
#include <algorithm>
#include <fstream>
#include <cstddef>
#include <string>
#include <string_view>
#include <utility>
@@ -19,7 +19,7 @@ inline std::string_view slice(std::string_view view, size_t start, size_t end) {
}
inline std::pair<std::string_view, std::string_view> split(std::string_view view, char Separator) {
size_t idx = view.find(Separator);
const size_t idx = view.find(Separator);
if (idx == std::string_view::npos) {
return std::make_pair(view, std::string_view());
}
@@ -34,7 +34,7 @@ inline bool starts_with(std::string_view view, std::string_view prefix) {
inline SourceLocation get_source_location(std::string_view content, size_t pos) {
// Get line and offset position (starts at 1:1)
auto sliced = string_view::slice(content, 0, pos);
std::size_t last_newline = sliced.rfind("\n");
const std::size_t last_newline = sliced.rfind('\n');
if (last_newline == std::string_view::npos) {
return {1, sliced.length() + 1};
@@ -44,7 +44,7 @@ inline SourceLocation get_source_location(std::string_view content, size_t pos)
size_t count_lines = 0;
size_t search_start = 0;
while (search_start <= sliced.size()) {
search_start = sliced.find("\n", search_start) + 1;
search_start = sliced.find('\n', search_start) + 1;
if (search_start == 0) {
break;
}

View File

@@ -57,7 +57,6 @@ using json = INJA_DATA_TYPE;
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
@@ -76,23 +75,32 @@ using json = INJA_DATA_TYPE;
#include <map>
#include <memory>
#include <string>
#include <vector>
// #include "node.hpp"
#ifndef INCLUDE_INJA_NODE_HPP_
#define INCLUDE_INJA_NODE_HPP_
#include <cstddef>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <tuple>
#include <vector>
// #include "function_storage.hpp"
#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
#include <functional>
#include <map>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
// #include "inja.hpp"
namespace inja {
using Arguments = std::vector<const json*>;
@@ -227,12 +235,14 @@ public:
#endif // INCLUDE_INJA_FUNCTION_STORAGE_HPP_
// #include "inja.hpp"
// #include "utils.hpp"
#ifndef INCLUDE_INJA_UTILS_HPP_
#define INCLUDE_INJA_UTILS_HPP_
#include <algorithm>
#include <fstream>
#include <cstddef>
#include <string>
#include <string_view>
#include <utility>
@@ -241,6 +251,7 @@ public:
#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
#define INCLUDE_INJA_EXCEPTIONS_HPP_
#include <cstddef>
#include <stdexcept>
#include <string>
@@ -297,7 +308,7 @@ inline std::string_view slice(std::string_view view, size_t start, size_t end) {
}
inline std::pair<std::string_view, std::string_view> split(std::string_view view, char Separator) {
size_t idx = view.find(Separator);
const size_t idx = view.find(Separator);
if (idx == std::string_view::npos) {
return std::make_pair(view, std::string_view());
}
@@ -312,7 +323,7 @@ inline bool starts_with(std::string_view view, std::string_view prefix) {
inline SourceLocation get_source_location(std::string_view content, size_t pos) {
// Get line and offset position (starts at 1:1)
auto sliced = string_view::slice(content, 0, pos);
std::size_t last_newline = sliced.rfind("\n");
const std::size_t last_newline = sliced.rfind('\n');
if (last_newline == std::string_view::npos) {
return {1, sliced.length() + 1};
@@ -322,7 +333,7 @@ inline SourceLocation get_source_location(std::string_view content, size_t pos)
size_t count_lines = 0;
size_t search_start = 0;
while (search_start <= sliced.size()) {
search_start = sliced.find("\n", search_start) + 1;
search_start = sliced.find('\n', search_start) + 1;
if (search_start == 0) {
break;
}
@@ -725,7 +736,7 @@ namespace inja {
*/
class StatisticsVisitor : public NodeVisitor {
void visit(const BlockNode& node) {
for (auto& n : node.nodes) {
for (const auto& n : node.nodes) {
n->accept(*this);
}
}
@@ -739,7 +750,7 @@ class StatisticsVisitor : public NodeVisitor {
}
void visit(const FunctionNode& node) {
for (auto& n : node.arguments) {
for (const auto& n : node.arguments) {
n->accept(*this);
}
}
@@ -802,7 +813,7 @@ struct Template {
explicit Template(const std::string& content): content(content) {}
/// Return number of variables (total number, not distinct ones) in the template
int count_variables() {
int count_variables() const {
auto statistic_visitor = StatisticsVisitor();
root.accept(statistic_visitor);
return statistic_visitor.variable_counter;
@@ -893,13 +904,19 @@ struct RenderConfig {
// #include "function_storage.hpp"
// #include "inja.hpp"
// #include "parser.hpp"
#ifndef INCLUDE_INJA_PARSER_HPP_
#define INCLUDE_INJA_PARSER_HPP_
#include <limits>
#include <cstddef>
#include <fstream>
#include <iterator>
#include <memory>
#include <stack>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
@@ -909,15 +926,20 @@ struct RenderConfig {
// #include "function_storage.hpp"
// #include "inja.hpp"
// #include "lexer.hpp"
#ifndef INCLUDE_INJA_LEXER_HPP_
#define INCLUDE_INJA_LEXER_HPP_
#include <cctype>
#include <locale>
#include <cstddef>
#include <string_view>
// #include "config.hpp"
// #include "exceptions.hpp"
// #include "token.hpp"
#ifndef INCLUDE_INJA_TOKEN_HPP_
#define INCLUDE_INJA_TOKEN_HPP_
@@ -1299,7 +1321,7 @@ public:
pos += open_start;
// try to match one of the opening sequences, and get the close
std::string_view open_str = m_in.substr(pos);
const std::string_view open_str = m_in.substr(pos);
bool must_lstrip = false;
if (inja::string_view::starts_with(open_str, config.expression_open)) {
if (inja::string_view::starts_with(open_str, config.expression_open_force_lstrip)) {
@@ -1428,8 +1450,6 @@ public:
// #include "token.hpp"
// #include "utils.hpp"
namespace inja {
@@ -1479,7 +1499,7 @@ class Parser {
}
inline void add_literal(Arguments &arguments, const char* content_ptr) {
std::string_view data_text(literal_start.data(), tok.text.data() - literal_start.data() + tok.text.size());
const std::string_view data_text(literal_start.data(), tok.text.data() - literal_start.data() + tok.text.size());
arguments.emplace_back(std::make_shared<LiteralNode>(data_text, data_text.data() - content_ptr));
}
@@ -1503,8 +1523,8 @@ class Parser {
return;
}
std::string original_path = static_cast<std::string>(path);
std::string original_name = template_name;
const std::string original_path = static_cast<std::string>(path);
const std::string original_name = template_name;
if (config.search_included_templates_in_files) {
// Build the relative path
@@ -1518,7 +1538,7 @@ class Parser {
std::ifstream file;
file.open(template_name);
if (!file.fail()) {
std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
const std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
auto include_template = Template(text);
template_storage.emplace(template_name, include_template);
@@ -1887,7 +1907,7 @@ class Parser {
throw_parser_error("expected id, got '" + tok.describe() + "'");
}
Token key_token = std::move(value_token);
const Token key_token = std::move(value_token);
value_token = tok;
get_next_token();
@@ -1948,7 +1968,7 @@ class Parser {
throw_parser_error("expected variable name, got '" + tok.describe() + "'");
}
std::string key = static_cast<std::string>(tok.text);
const std::string key = static_cast<std::string>(tok.text);
get_next_token();
auto set_statement_node = std::make_shared<SetStatementNode>(key, tok.text.data() - tmpl.content.c_str());
@@ -2042,7 +2062,7 @@ public:
}
void parse_into_template(Template& tmpl, std::string_view filename) {
std::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
const std::string_view path = filename.substr(0, filename.find_last_of("/\\") + 1);
// StringRef path = sys::path::parent_path(filename);
auto sub_parser = Parser(config, lexer.get_config(), template_storage, function_storage);
@@ -2069,7 +2089,15 @@ public:
#define INCLUDE_INJA_RENDERER_HPP_
#include <algorithm>
#include <array>
#include <cctype>
#include <cmath>
#include <cstddef>
#include <memory>
#include <numeric>
#include <ostream>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
@@ -2078,6 +2106,10 @@ public:
// #include "exceptions.hpp"
// #include "function_storage.hpp"
// #include "inja.hpp"
// #include "node.hpp"
// #include "template.hpp"
@@ -2141,7 +2173,7 @@ class Renderer : public NodeVisitor {
return buffer;
}
void print_data(const std::shared_ptr<json> value) {
void print_data(const std::shared_ptr<json>& value) {
if (value->is_string()) {
if (config.html_autoescape) {
*output_stream << htmlescape(value->get_ref<const json::string_t&>());
@@ -2179,7 +2211,7 @@ class Renderer : public NodeVisitor {
throw_renderer_error("expression could not be evaluated", expression_list);
}
auto node = not_found_stack.top();
const auto node = not_found_stack.top();
not_found_stack.pop();
throw_renderer_error("variable '" + static_cast<std::string>(node->name) + "' not found", *node);
@@ -2188,7 +2220,7 @@ class Renderer : public NodeVisitor {
}
void throw_renderer_error(const std::string& message, const AstNode& node) {
SourceLocation loc = get_source_location(current_template->content, node.pos);
const SourceLocation loc = get_source_location(current_template->content, node.pos);
INJA_THROW(RenderError(message, loc));
}
@@ -2230,7 +2262,7 @@ class Renderer : public NodeVisitor {
template <bool throw_not_found = true> Arguments get_argument_vector(const FunctionNode& node) {
const size_t N = node.arguments.size();
for (auto a : node.arguments) {
for (const auto& a : node.arguments) {
a->accept(*this);
}
@@ -2256,7 +2288,7 @@ class Renderer : public NodeVisitor {
}
void visit(const BlockNode& node) {
for (auto& n : node.nodes) {
for (const auto& n : node.nodes) {
n->accept(*this);
if (break_rendering) {
@@ -2732,8 +2764,6 @@ public:
// #include "template.hpp"
// #include "utils.hpp"
namespace inja {

View File

@@ -1,5 +1,10 @@
// Copyright (c) 2020 Pantor. All rights reserved.
#include <doctest/doctest.h>
#include "inja/environment.hpp"
#include "inja/inja.hpp"
TEST_CASE("loading") {
inja::Environment env;
inja::json data;

View File

@@ -1,5 +1,11 @@
// Copyright (c) 2020 Pantor. All rights reserved.
#include <doctest/doctest.h>
#include <string>
#include "inja/environment.hpp"
#include "inja/inja.hpp"
TEST_CASE("functions") {
inja::Environment env;

View File

@@ -1,5 +1,12 @@
// Copyright (c) 2020 Pantor. All rights reserved.
#include <doctest/doctest.h>
#include <string>
#include "inja/environment.hpp"
#include "inja/inja.hpp"
#include "inja/template.hpp"
TEST_CASE("types") {
inja::Environment env;
inja::json data;
@@ -160,7 +167,7 @@ TEST_CASE("templates") {
SUBCASE("reuse") {
inja::Environment env;
inja::Template temp = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
const inja::Template temp = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
CHECK(env.render(temp, data) == "Peter");
@@ -171,10 +178,10 @@ TEST_CASE("templates") {
SUBCASE("include") {
inja::Environment env;
inja::Template t1 = env.parse("Hello {{ name }}");
const inja::Template t1 = env.parse("Hello {{ name }}");
env.include_template("greeting", t1);
inja::Template t2 = env.parse("{% include \"greeting\" %}!");
const inja::Template t2 = env.parse("{% include \"greeting\" %}!");
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'");
@@ -189,13 +196,13 @@ TEST_CASE("templates") {
env.set_search_included_templates_in_files(false);
env.set_include_callback([&env](const std::string&, const std::string&) { return env.parse("Hello {{ name }}"); });
inja::Template t1 = env.parse("{% include \"greeting\" %}!");
const inja::Template t1 = env.parse("{% include \"greeting\" %}!");
CHECK(env.render(t1, data) == "Hello Peter!");
env.set_search_included_templates_in_files(true);
env.set_include_callback([&env](const std::string&, const std::string& name) { return env.parse("Bye " + name); });
inja::Template t2 = env.parse("{% include \"Jeff\" %}!");
const inja::Template t2 = env.parse("{% include \"Jeff\" %}!");
CHECK(env.render(t2, data) == "Bye Jeff!");
}
@@ -211,9 +218,9 @@ TEST_CASE("templates") {
SUBCASE("count variables") {
inja::Environment env;
inja::Template t1 = env.parse("Hello {{ name }}");
inja::Template t2 = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
inja::Template t3 = env.parse("{% if at(name, test) %}{{ name }}{% else %}{{ city }}{{ upper(city) }}{% endif %}");
const inja::Template t1 = env.parse("Hello {{ name }}");
const inja::Template t2 = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
const inja::Template t3 = env.parse("{% if at(name, test) %}{{ name }}{% else %}{{ city }}{{ upper(city) }}{% endif %}");
CHECK(t1.count_variables() == 1);
CHECK(t2.count_variables() == 3);

View File

@@ -1,5 +1,13 @@
// Copyright (c) 2020 Pantor. All rights reserved.
#include <doctest/doctest.h>
#include <string>
#include "inja/environment.hpp"
#include "inja/function_storage.hpp"
#include "inja/inja.hpp"
#include "inja/utils.hpp"
TEST_CASE("source location") {
std::string content = R""""(Lorem Ipsum
Dolor
@@ -42,7 +50,7 @@ TEST_CASE("copy environment") {
CHECK(copy.render(test_tpl, inja::json()) == "4");
// overwrite template in source env
inja::Template t2 = env.parse("{{ double(4) }}");
const inja::Template t2 = env.parse("{{ double(4) }}");
env.include_template("tpl", t2);
REQUIRE(env.render(test_tpl, inja::json()) == "8");

View File

@@ -2,7 +2,7 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest/doctest.h"
#include <doctest/doctest.h>
#define JSON_USE_IMPLICIT_CONVERSIONS 0
#define JSON_NO_IO 1