* inja2

* header only

* reduce dependencies

* code cleaning

* c++17

* use stdc++

* code cleaning

* infrastructure

* header only

* add infrastructure

* fix tests

* use minimum clang 6

* code cleaning, polyfill for c++11

* fix some file tests

* fix readme

* update appveyor

* fix polyfill and ci

* fix polyfill

* fix ci?

* test msvc __cplusplus

* add doxygen

* activate all tests

* code cleaning

* add coveralls, set default to dot notation

* add html test

* add doxygen comments

* test single_include file

* change build folder in appveyor

* correct make arguments in appveyor

* fix appveyor arguments
This commit is contained in:
pantor
2018-12-23 16:13:15 +01:00
committed by GitHub
parent d90f93fda0
commit 699c207c8c
77 changed files with 7420 additions and 3522 deletions

View File

@@ -1,92 +0,0 @@
##
## HUNTER
##
option(HUNTER_ENABLED "Use hunter to manage dependencies" OFF)
if(HUNTER_ENABLED)
include("../cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.19.156.tar.gz"
SHA1 "8d5e4635b137365e0d1ade4d60accf4e2bb41f0d"
)
endif()
##
## TESTS
##
add_executable(inja_test
src/unit-files.cpp
src/unit-renderer.cpp
src/unit-string-helper.cpp
src/unit.cpp
)
add_executable(inja_single_test
src/unit-files.cpp
src/unit-renderer.cpp
src/unit-string-helper.cpp
src/unit.cpp
)
if(HUNTER_ENABLED) # Use Hunter to manage dependencies
# Add Catch framework
hunter_add_package(Catch)
find_package(Catch CONFIG REQUIRED)
# Add JSON package
hunter_add_package(nlohmann_json)
find_package(nlohmann_json CONFIG REQUIRED)
# Add dependencies to target
target_link_libraries(inja_test Catch::Catch nlohmann_json inja)
else() # Manage dependencies manually
# Prepare "Catch" library for other executables
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE "src/catch")
# Prepare "hayai" library for other executables
add_library(hayai INTERFACE)
target_include_directories(hayai INTERFACE "src/hayai")
# Add dependencies to targets
target_link_libraries(inja_test Catch inja)
target_link_libraries(inja_single_test Catch inja_single)
endif()
##
## BENCHMARK
##
if(BUILD_BENCHMARK)
add_executable(inja_benchmark
src/benchmark.cpp
)
target_link_libraries(inja_benchmark hayai inja)
endif()
##
## Copy test files to build directory
##
add_custom_command(
TARGET inja_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/data
${CMAKE_CURRENT_BINARY_DIR}/data
)
##
## Add tests to make
##
add_test(NAME inja_test
COMMAND inja_test
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_test(NAME inja_single_test
COMMAND inja_single_test
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@@ -1,11 +1,11 @@
#include "hayai/hayai.hpp"
#include "inja.hpp"
#include <inja/inja.hpp>
using json = nlohmann::json;
inja::Environment env = inja::Environment();
inja::Environment env;
json data = {{"name", "Peter"}};

11
test/data/html/data.json Normal file
View File

@@ -0,0 +1,11 @@
{
"author": "Pantor",
"date": "23/12/2018",
"tags": [
"test",
"templates"
],
"views": 123,
"title": "Inja works.",
"content": "Inja is the best and fastest template engine for C++. Period."
}

19
test/data/html/result.txt Normal file
View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Inja works.</title>
</head>
<body>
<h1>Inja works.</h1>
<small>Written by Pantor</small>
<p>Inja is the best and fastest template engine for C++. Period.</p>
<small>123 views</small>
<h5>Tags</h5>
<ul>
<li>test</li>
<li>templates</li>
</ul>
</body>
</html>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
<small>Written by {{ author }}</small>
<p>{{ content }}</p>
<small>{{ views }} views</small>
<h5>Tags</h5>
<ul>
## for tag in tags
<li>{{ tag }}</li>
## endfor
</ul>
</body>
</html>

0
test/data/include.txt Normal file → Executable file
View File

0
test/data/nested-line/data.json Normal file → Executable file
View File

0
test/data/nested-line/result.txt Normal file → Executable file
View File

1
test/data/nested-line/template.txt Normal file → Executable file
View File

@@ -1,6 +1,5 @@
## for x in xarray
## for y in yarray
{{x}}-{{y}}
## endfor
## endfor

0
test/data/nested/data.json Normal file → Executable file
View File

0
test/data/nested/result.txt Normal file → Executable file
View File

0
test/data/nested/template.txt Normal file → Executable file
View File

0
test/data/simple-file/data.json Normal file → Executable file
View File

0
test/data/simple-file/result.txt Normal file → Executable file
View File

0
test/data/simple-file/template.txt Normal file → Executable file
View File

0
test/data/simple.txt Normal file → Executable file
View File

View File

@@ -256,7 +256,7 @@ namespace hayai
# elif defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &result);
# else
clock_gettime((clockid_t)-1, &result);
clock_gettime((clocId_t)-1, &result);
# endif
return result;
}

View File

@@ -1,26 +0,0 @@
unit_test = executable(
'inja-test',
'src/unit.cpp',
'src/unit-files.cpp',
'src/unit-renderer.cpp',
'src/unit-string-helper.cpp',
dependencies: inja_dep
)
unit_single_test = executable(
'inja-single-test',
'src/unit.cpp',
'src/unit-files.cpp',
'src/unit-renderer.cpp',
'src/unit-string-helper.cpp',
dependencies: inja_single_dep
)
inja_benchmark = executable(
'inja_benchmark',
'src/benchmark.cpp',
dependencies: inja_dep
)
test('Inja unit test', unit_test)
test('Inja single unit test', unit_single_test)

View File

@@ -1,164 +0,0 @@
#include "catch/catch.hpp"
#include "inja.hpp"
TEST_CASE("dot to pointer") {
CHECK( inja::Parser::dot_to_json_pointer_notation("person.names.surname") == "/person/names/surname" );
CHECK( inja::Parser::dot_to_json_pointer_notation("guests.2") == "/guests/2" );
}
TEST_CASE("basic-search") {
std::string input = "lorem ipsum dolor it";
inja::Regex regex("i(.*)m");
SECTION("from start") {
inja::Match match = inja::search(input, regex, 0);
CHECK( match.found() == true );
CHECK( match.position() == 6 );
CHECK( match.length() == 5 );
CHECK( match.end_position() == 11 );
CHECK( match.str() == "ipsum" );
CHECK( match.str(1) == "psu" );
}
SECTION("from position") {
inja::Match match = inja::search(input, regex, 8);
CHECK( match.found() == false );
CHECK( match.length() == 0 );
}
}
TEST_CASE("search-multiple-regexes") {
std::string input = "lorem ipsum dolor amit estas tronum.";
SECTION("basic 1") {
std::map<int, inja::Regex> regex_patterns = {
{0, inja::Regex("tras")},
{1, inja::Regex("do(\\w*)or")},
{2, inja::Regex("es(\\w*)as")},
{3, inja::Regex("ip(\\w*)um")}
};
inja::MatchType<int> match = inja::search(input, regex_patterns, 0);
CHECK( match.type() == 3 );
CHECK( match.str() == "ipsum" );
CHECK( match.str(1) == "s" );
}
SECTION("basic 2") {
std::map<int, inja::Regex> regex_patterns = {
{11, inja::Regex("tras")},
{21, inja::Regex("ip(\\w*)um")},
{31, inja::Regex("do(\\w*)or")},
{41, inja::Regex("es(\\w*)as")}
};
inja::MatchType<int> match = inja::search(input, regex_patterns, 0);
CHECK( match.type() == 21 );
CHECK( match.str() == "ipsum" );
CHECK( match.str(1) == "s" );
}
SECTION("basic 3") {
auto map_functions = inja::Parser().regex_map_functions;
std::map<int, inja::Regex> regex_patterns = {
{0, map_functions.at(inja::Parsed::Function::Upper)},
{1, map_functions.at(inja::Parsed::Function::Lower)},
{2, map_functions.at(inja::Parsed::Function::ReadJson)}
};
const std::string input_1 = "upper(name)";
inja::MatchType<int> match = inja::search(input_1, regex_patterns, 0);
CHECK( match.type() == 0 );
CHECK( match.str(0) == "upper(name)" );
CHECK( match.str(1) == "name" );
const std::string input_2 = "upper(lower(name))";
inja::MatchType<int> match2 = inja::search(input_2, regex_patterns, 0);
CHECK( match2.type() == 0 );
CHECK( match2.str(0) == "upper(lower(name))" );
CHECK( match2.str(1) == "lower(name)" );
}
}
TEST_CASE("match-multiple-regexes") {
std::string input = "ipsum";
SECTION("basic 1") {
std::map<int, inja::Regex> regex_patterns = {
{1, inja::Regex("tras")},
{2, inja::Regex("ip(\\w*)um")},
{3, inja::Regex("do(\\w*)or")},
{4, inja::Regex("es(\\w*)as")}
};
inja::MatchType<int> match = inja::match(input, regex_patterns);
CHECK( match.type() == 2 );
CHECK( match.str() == "ipsum" );
CHECK( match.str(1) == "s" );
}
}
TEST_CASE("search-on-level") {
std::string input = "(% up %)(% up %)Test(% N1 %)(% down %)...(% up %)(% N2 %)(% up %)(% N3 %)(% down %)(% N4 %)(% down %)(% N5 %)(% down %)";
inja::Regex regex_statement("\\(\\% (.*?) \\%\\)");
inja::Regex regex_level_up("up");
inja::Regex regex_level_down("down");
inja::Regex regex_search("N(\\d+)");
SECTION("first instance") {
inja::Match open_match = inja::search(input, regex_statement, 0);
CHECK( open_match.position() == 0 );
CHECK( open_match.end_position() == 8 );
CHECK( open_match.str(1) == "up" );
inja::MatchClosed match = inja::search_closed_on_level(input, regex_statement, regex_level_up, regex_level_down, regex_search, open_match);
CHECK( match.position() == 0 );
CHECK( match.end_position() == 109 );
}
SECTION("second instance") {
inja::Match open_match = inja::search(input, regex_statement, 4);
CHECK( open_match.position() == 8 );
CHECK( open_match.end_position() == 16 );
CHECK( open_match.str(1) == "up" );
inja::MatchClosed match = inja::search_closed_on_level(input, regex_statement, regex_level_up, regex_level_down, regex_search, open_match);
CHECK( match.open_match.position() == 8 );
CHECK( match.open_match.end_position() == 16 );
CHECK( match.close_match.position() == 20 );
CHECK( match.close_match.end_position() == 28 );
CHECK( match.position() == 8 );
CHECK( match.end_position() == 28 );
CHECK( match.outer() == "(% up %)Test(% N1 %)" );
CHECK( match.inner() == "Test" );
}
}
TEST_CASE("match-functions") {
auto map_regex = inja::Parser().regex_map_functions;
CHECK( inja::match("not test", map_regex).type() == inja::Parsed::Function::Not );
CHECK( inja::match("not test", map_regex).type() != inja::Parsed::Function::And );
CHECK( inja::match("2 == 3", map_regex).type() == inja::Parsed::Function::Equal );
CHECK( inja::match("test and test", map_regex).type() == inja::Parsed::Function::And );
CHECK( inja::match("test and test", map_regex).type() != inja::Parsed::Function::ReadJson );
CHECK( inja::match("test", map_regex).type() == inja::Parsed::Function::ReadJson );
CHECK( inja::match("upper", map_regex).type() == inja::Parsed::Function::ReadJson );
CHECK( inja::match("upper()", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match("upper(var)", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match("upper( var )", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match("upper(lower())", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match("upper( lower() )", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match(" upper(lower()) ", map_regex).type() == inja::Parsed::Function::Upper );
CHECK( inja::match("lower(upper(test))", map_regex).type() == inja::Parsed::Function::Lower );
CHECK( inja::match("round(2, 3)", map_regex).type() == inja::Parsed::Function::Round );
CHECK( inja::match("exists(\"var\")", map_regex).type() == inja::Parsed::Function::Exists );
CHECK( inja::match("existsIn(var, \"othervar\")", map_regex).type() == inja::Parsed::Function::ExistsInObject );
}
TEST_CASE("create-regex-functions") {
CHECK( inja::Parser::function_regex("upper", 1).pattern() == "\\s*upper(?:\\((.*)\\))\\s*" );
CHECK( inja::Parser::function_regex("upper", 0).pattern() == "\\s*upper(?:\\(\\))?\\s*" );
CHECK( inja::Parser::function_regex("lower", 2).pattern() == "\\s*lower(?:\\((.*),(.*)\\))\\s*" );
}

View File

@@ -1,5 +1,5 @@
#include "catch/catch.hpp"
#include "inja.hpp"
#include "inja/inja.hpp"
using json = nlohmann::json;
@@ -11,7 +11,7 @@ TEST_CASE("loading") {
data["name"] = "Jeff";
SECTION("Files should be loaded") {
CHECK( env.load_global_file("../test/data/simple.txt") == "Hello {{ name }}." );
CHECK( env.load_file("../test/data/simple.txt") == "Hello {{ name }}." );
}
SECTION("Files should be rendered") {
@@ -26,9 +26,9 @@ TEST_CASE("loading") {
TEST_CASE("complete-files") {
inja::Environment env = inja::Environment("../test/data/");
for (std::string test_name : {"simple-file", "nested", "nested-line"}) {
for (std::string test_name : {"simple-file", "nested", "nested-line", "html"}) {
SECTION(test_name) {
CHECK( env.render_file_with_json_file(test_name + "/template.txt", test_name + "/data.json") == env.load_global_file(test_name + "/result.txt") );
CHECK( env.render_file_with_json_file(test_name + "/template.txt", test_name + "/data.json") == env.load_file(test_name + "/result.txt") );
}
}
}
@@ -41,6 +41,6 @@ TEST_CASE("global-path") {
SECTION("Files should be written") {
env.write("simple.txt", data, "global-path-result.txt");
CHECK( env_result.load_global_file("global-path-result.txt") == "Hello Jeff." );
CHECK( env_result.load_file("global-path-result.txt") == "Hello Jeff." );
}
}

View File

@@ -1,12 +1,18 @@
#include "catch/catch.hpp"
#include "inja.hpp"
#include "inja/inja.hpp"
using json = nlohmann::json;
TEST_CASE("dot-to-pointer") {
std::string buffer;
CHECK( inja::convert_dot_to_json_pointer("person.names.surname", buffer) == "/person/names/surname" );
CHECK( inja::convert_dot_to_json_pointer("guests.2", buffer) == "/guests/2" );
}
TEST_CASE("types") {
inja::Environment env = inja::Environment();
inja::Environment env;
json data;
data["name"] = "Peter";
data["city"] = "Brunswick";
@@ -34,11 +40,11 @@ TEST_CASE("types") {
CHECK( env.render("{{name}}", data) == "Peter" );
CHECK( env.render("{{ name }} is {{ age }} years old.", data) == "Peter is 29 years old." );
CHECK( env.render("Hello {{ name }}! I come from {{ city }}.", data) == "Hello Peter! I come from Brunswick." );
CHECK( env.render("Hello {{ names/1 }}!", data) == "Hello Seb!" );
CHECK( env.render("Hello {{ brother/name }}!", data) == "Hello Chris!" );
CHECK( env.render("Hello {{ brother/daughter0/name }}!", data) == "Hello Maria!" );
CHECK( env.render("Hello {{ names.1 }}!", data) == "Hello Seb!" );
CHECK( env.render("Hello {{ brother.name }}!", data) == "Hello Chris!" );
CHECK( env.render("Hello {{ brother.daughter0.name }}!", data) == "Hello Maria!" );
CHECK_THROWS_WITH( env.render("{{unknown}}", data), "[inja.exception.render_error] variable '/unknown' not found" );
CHECK_THROWS_WITH( env.render("{{unknown}}", data), "[inja.exception.render_error] variable 'unknown' not found" );
}
SECTION("comments") {
@@ -49,17 +55,17 @@ TEST_CASE("types") {
SECTION("loops") {
CHECK( env.render("{% for name in names %}a{% endfor %}", data) == "aa" );
CHECK( env.render("Hello {% for name in names %}{{ name }} {% endfor %}!", data) == "Hello Jeff Seb !" );
CHECK( env.render("Hello {% for name in names %}{{ loop/index }}: {{ name }}, {% endfor %}!", data) == "Hello 0: Jeff, 1: Seb, !" );
CHECK( env.render("Hello {% for name in names %}{{ loop.index }}: {{ name }}, {% endfor %}!", data) == "Hello 0: Jeff, 1: Seb, !" );
CHECK( env.render("{% for type, name in relatives %}{{ type }}: {{ name }}, {% endfor %}", data) == "brother: Chris, mother: Maria, sister: Jenny, " );
CHECK( env.render("{% for v in vars %}{% if v > 0 %}+{% endif %}{% endfor %}", data) == "+++" );
CHECK( env.render("{% for name in names %}{{ loop/index }}: {{ name }}{% if not loop/is_last %}, {% endif %}{% endfor %}!", data) == "0: Jeff, 1: Seb!" );
CHECK( env.render("{% for name in names %}{{ loop/index }}: {{ name }}{% if loop/is_last == false %}, {% endif %}{% endfor %}!", data) == "0: Jeff, 1: Seb!" );
CHECK( env.render("{% for name in names %}{{ loop.index }}: {{ name }}{% if not loop.is_last %}, {% endif %}{% endfor %}!", data) == "0: Jeff, 1: Seb!" );
CHECK( env.render("{% for name in names %}{{ loop.index }}: {{ name }}{% if loop.is_last == false %}, {% endif %}{% endfor %}!", data) == "0: Jeff, 1: Seb!" );
data["empty_loop"] = {};
CHECK( env.render("{% for name in empty_loop %}a{% endfor %}", data) == "" );
CHECK( env.render("{% for name in {} %}a{% endfor %}", data) == "" );
CHECK_THROWS_WITH( env.render("{% for name ins names %}a{% endfor %}", data), "[inja.exception.parser_error] unknown loop statement: for name ins names" );
CHECK_THROWS_WITH( env.render("{% for name ins names %}a{% endfor %}", data), "[inja.exception.parser_error] expected 'in', got 'ins'" );
// CHECK_THROWS_WITH( env.render("{% for name in relatives %}{{ name }}{% endfor %}", data), "[inja.exception.json_error] [json.exception.type_error.302] type must be array, but is object" );
}
@@ -77,25 +83,28 @@ TEST_CASE("types") {
CHECK( env.render("{% if age == 26 %}26{% else if age == 27 %}27{% else if age == 28 %}28{% else %}29{% endif %}", data) == "29" );
CHECK( env.render("{% if age == 25 %}+{% endif %}{% if age == 29 %}+{% else %}-{% endif %}", data) == "+" );
CHECK_THROWS_WITH( env.render("{% if is_happy %}{% if is_happy %}{% endif %}", data), "[inja.exception.parser_error] misordered if statement" );
CHECK_THROWS_WITH( env.render("{% if is_happy %}{% else if is_happy %}{% end if %}", data), "[inja.exception.parser_error] misordered if statement" );
CHECK_THROWS_WITH( env.render("{% if is_happy %}{% if is_happy %}{% endif %}", data), "[inja.exception.parser_error] unmatched if" );
CHECK_THROWS_WITH( env.render("{% if is_happy %}{% else if is_happy %}{% end if %}", data), "[inja.exception.parser_error] expected statement, got 'end'" );
}
SECTION("line statements") {
CHECK( env.render(R"(## if is_happy
Yeah!
## endif)", data) == "Yeah!" );
## endif)", data) == R"(Yeah!
)" );
CHECK( env.render(R"(## if is_happy
## if is_happy
Yeah!
## endif
## endif )", data) == "Yeah!" );
}
## endif )", data) == R"(Yeah!
)" );
}
}
TEST_CASE("functions") {
inja::Environment env = inja::Environment();
inja::Environment env;
json data;
data["name"] = "Peter";
@@ -206,7 +215,7 @@ TEST_CASE("functions") {
CHECK( env.render("{{ default(nothing, 0) }}", data) == "0" );
CHECK( env.render("{{ default(name, \"nobody\") }}", data) == "Peter" );
CHECK( env.render("{{ default(surname, \"nobody\") }}", data) == "nobody" );
CHECK_THROWS_WITH( env.render("{{ default(surname, lastname) }}", data), "[inja.exception.render_error] variable '/lastname' not found" );
CHECK_THROWS_WITH( env.render("{{ default(surname, lastname) }}", data), "[inja.exception.render_error] variable 'lastname' not found" );
}
SECTION("exists") {
@@ -221,8 +230,8 @@ TEST_CASE("functions") {
CHECK( env.render("{{ existsIn(brother, \"parents\") }}", data) == "false" );
CHECK( env.render("{{ existsIn(brother, property) }}", data) == "true" );
CHECK( env.render("{{ existsIn(brother, name) }}", data) == "false" );
CHECK_THROWS_WITH( env.render("{{ existsIn(sister, \"lastname\") }}", data), "[inja.exception.render_error] variable '/sister' not found" );
CHECK_THROWS_WITH( env.render("{{ existsIn(brother, sister) }}", data), "[inja.exception.render_error] variable '/sister' not found" );
CHECK_THROWS_WITH( env.render("{{ existsIn(sister, \"lastname\") }}", data), "[inja.exception.render_error] variable 'sister' not found" );
CHECK_THROWS_WITH( env.render("{{ existsIn(brother, sister) }}", data), "[inja.exception.render_error] variable 'sister' not found" );
}
SECTION("isType") {
@@ -243,40 +252,41 @@ TEST_CASE("functions") {
}
}
TEST_CASE("callbacks") {
inja::Environment env = inja::Environment();
inja::Environment env;
json data;
data["age"] = 28;
env.add_callback("double", 1, [&env](inja::Parsed::Arguments args, json data) {
int number = env.get_argument<double>(args, 0, data);
env.add_callback("double", 1, [](inja::Arguments& args) {
int number = args.at(0)->get<double>();
return 2 * number;
});
env.add_callback("half", 1, [&env](inja::Parsed::Arguments args, json data) {
int number = env.get_argument<double>(args, 0, data);
env.add_callback("half", 1, [](inja::Arguments args) {
int number = args.at(0)->get<double>();
return number / 2;
});
std::string greet = "Hello";
env.add_callback("double-greetings", 0, [greet](inja::Parsed::Arguments args, json data) {
env.add_callback("double-greetings", 0, [greet](inja::Arguments args) {
return greet + " " + greet + "!";
});
env.add_callback("multiply", 2, [&env](inja::Parsed::Arguments args, json data) {
double number1 = env.get_argument(args, 0, data);
auto number2 = env.get_argument<double>(args, 1, data);
env.add_callback("multiply", 2, [](inja::Arguments args) {
double number1 = args.at(0)->get<double>();
auto number2 = args.at(1)->get<double>();
return number1 * number2;
});
env.add_callback("multiply", 3, [&env](inja::Parsed::Arguments args, json data) {
double number1 = env.get_argument(args, 0, data);
double number2 = env.get_argument(args, 1, data);
double number3 = env.get_argument(args, 2, data);
env.add_callback("multiply", 3, [](inja::Arguments args) {
double number1 = args.at(0)->get<double>();
double number2 = args.at(1)->get<double>();
double number3 = args.at(2)->get<double>();
return number1 * number2 * number3;
});
env.add_callback("multiply", 0, [](inja::Parsed::Arguments args, json data) {
env.add_callback("multiply", 0, [](inja::Arguments args) {
return 1.0;
});
@@ -289,8 +299,9 @@ TEST_CASE("callbacks") {
CHECK( env.render("{{ multiply }}", data) == "1.0" );
}
TEST_CASE("combinations") {
inja::Environment env = inja::Environment();
inja::Environment env;
json data;
data["name"] = "Peter";
data["city"] = "Brunswick";
@@ -303,7 +314,7 @@ TEST_CASE("combinations") {
CHECK( env.render("{% if upper(\"Peter\") == \"PETER\" %}TRUE{% endif %}", data) == "TRUE" );
CHECK( env.render("{% if lower(upper(name)) == \"peter\" %}TRUE{% endif %}", data) == "TRUE" );
CHECK( env.render("{% for i in range(4) %}{{ loop/index1 }}{% endfor %}", data) == "1234" );
CHECK( env.render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data) == "1234" );
}
TEST_CASE("templates") {
@@ -313,26 +324,27 @@ TEST_CASE("templates") {
data["is_happy"] = true;
SECTION("reuse") {
inja::Environment env = inja::Environment();
inja::Environment env;
inja::Template temp = env.parse("{% if is_happy %}{{ name }}{% else %}{{ city }}{% endif %}");
CHECK( env.render_template(temp, data) == "Peter" );
CHECK( env.render(temp, data) == "Peter" );
data["is_happy"] = false;
CHECK( env.render_template(temp, data) == "Brunswick" );
CHECK( env.render(temp, data) == "Brunswick" );
}
SECTION("include") {
inja::Environment env = inja::Environment();
inja::Environment env;
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!" );
CHECK( env.render(t2, data) == "Hello Peter!" );
}
}
TEST_CASE("other-syntax") {
json data;
data["name"] = "Peter";
@@ -345,31 +357,31 @@ TEST_CASE("other-syntax") {
data["is_happy"] = true;
SECTION("variables") {
inja::Environment env = inja::Environment();
env.set_element_notation(inja::ElementNotation::Dot);
inja::Environment env;
env.set_element_notation(inja::ElementNotation::Pointer);
CHECK( env.render("{{ name }}", data) == "Peter" );
CHECK( env.render("Hello {{ names.1 }}!", data) == "Hello Seb!" );
CHECK( env.render("Hello {{ brother.name }}!", data) == "Hello Chris!" );
CHECK( env.render("Hello {{ brother.daughter0.name }}!", data) == "Hello Maria!" );
CHECK( env.render("Hello {{ names/1 }}!", data) == "Hello Seb!" );
CHECK( env.render("Hello {{ brother/name }}!", data) == "Hello Chris!" );
CHECK( env.render("Hello {{ brother/daughter0/name }}!", data) == "Hello Maria!" );
CHECK_THROWS_WITH( env.render("{{unknown.name}}", data), "[inja.exception.render_error] variable '/unknown/name' not found" );
CHECK_THROWS_WITH( env.render("{{unknown/name}}", data), "[inja.exception.render_error] variable 'unknown/name' not found" );
}
SECTION("other expression syntax") {
inja::Environment env = inja::Environment();
inja::Environment env;
CHECK( env.render("Hello {{ name }}!", data) == "Hello Peter!" );
env.set_expression("\\(&", "&\\)");
env.set_expression("(&", "&)");
CHECK( env.render("Hello {{ name }}!", data) == "Hello {{ name }}!" );
CHECK( env.render("Hello (& name &)!", data) == "Hello Peter!" );
}
SECTION("other comment syntax") {
inja::Environment env = inja::Environment();
env.set_comment("\\(&", "&\\)");
inja::Environment env;
env.set_comment("(&", "&)");
CHECK( env.render("Hello {# Test #}", data) == "Hello {# Test #}" );
CHECK( env.render("Hello (& Test &)", data) == "Hello " );