* 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 authored and GitHub committed 2018-12-23 16:13:15 +01:00
1 parent d90f93fda0
commit 699c207c8c
77 files changed
+7420 -3522

No files matched your search

-92
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}
)
@@ -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"}};
File renamed without changes.
File renamed without changes.
+11
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
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>
+20
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>
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
-1
View File
@@ -1,6 +1,5 @@
## for x in xarray
## for y in yarray
{{x}}-{{y}}
## endfor
## endfor
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
View File
File mode changed.
Regular → Executable
View File
File mode changed.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-26
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)
-164
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*" );
}
@@ -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." );
}
}
@@ -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 " );
View File
File renamed without changes.