diff --git a/README.md b/README.md index 9c2cecc..bb1d158 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,9 @@ render("Hello {{ upper(neighbour) }}!", data); // "Hello PETER!" render("Hello {{ lower(neighbour) }}!", data); // "Hello peter!" render("Hello {{ capitalize(neighbour) }}!", data); // "Hello Peter!" +// Replace characters in a string +render("{{ replace(neighbour, \"e\", \"3\")}}", data); // "P3t3r" + // Range function, useful for loops render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data); // "1234" render("{% for i in range(3) %}{{ at(guests, i) }} {% endfor %}", data); // "Jeff Tom Patrick " diff --git a/include/inja/function_storage.hpp b/include/inja/function_storage.hpp index 2a265e0..f3653ee 100644 --- a/include/inja/function_storage.hpp +++ b/include/inja/function_storage.hpp @@ -63,6 +63,7 @@ class FunctionStorage { Min, Odd, Range, + Replace, Round, Sort, Upper, @@ -106,6 +107,7 @@ class FunctionStorage { {std::make_pair("min", 1), FunctionData {Operation::Min}}, {std::make_pair("odd", 1), FunctionData {Operation::Odd}}, {std::make_pair("range", 1), FunctionData {Operation::Range}}, + {std::make_pair("replace", 3), FunctionData {Operation::Replace}}, {std::make_pair("round", 2), FunctionData {Operation::Round}}, {std::make_pair("sort", 1), FunctionData {Operation::Sort}}, {std::make_pair("upper", 1), FunctionData {Operation::Upper}}, diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp index 069855b..654f51f 100644 --- a/include/inja/renderer.hpp +++ b/include/inja/renderer.hpp @@ -414,6 +414,12 @@ class Renderer : public NodeVisitor { std::iota(result.begin(), result.end(), 0); make_result(std::move(result)); } break; + case Op::Replace: { + const auto args = get_arguments<3>(node); + auto result = args[0]->get(); + replace_substring(result, args[1]->get(), args[2]->get()); + make_result(std::move(result)); + } break; case Op::Round: { const auto args = get_arguments<2>(node); const auto precision = args[1]->get(); diff --git a/single_include/inja/inja.hpp b/single_include/inja/inja.hpp index 27bf401..f01a203 100644 --- a/single_include/inja/inja.hpp +++ b/single_include/inja/inja.hpp @@ -170,6 +170,7 @@ class FunctionStorage { Min, Odd, Range, + Replace, Round, Sort, Upper, @@ -213,6 +214,7 @@ class FunctionStorage { {std::make_pair("min", 1), FunctionData {Operation::Min}}, {std::make_pair("odd", 1), FunctionData {Operation::Odd}}, {std::make_pair("range", 1), FunctionData {Operation::Range}}, + {std::make_pair("replace", 3), FunctionData {Operation::Replace}}, {std::make_pair("round", 2), FunctionData {Operation::Round}}, {std::make_pair("sort", 1), FunctionData {Operation::Sort}}, {std::make_pair("upper", 1), FunctionData {Operation::Upper}}, @@ -2521,6 +2523,12 @@ class Renderer : public NodeVisitor { std::iota(result.begin(), result.end(), 0); make_result(std::move(result)); } break; + case Op::Replace: { + const auto args = get_arguments<3>(node); + auto result = args[0]->get(); + replace_substring(result, args[1]->get(), args[2]->get()); + make_result(std::move(result)); + } break; case Op::Round: { const auto args = get_arguments<2>(node); const auto precision = args[1]->get(); diff --git a/test/test-functions.cpp b/test/test-functions.cpp index 50ee974..6ed2df0 100644 --- a/test/test-functions.cpp +++ b/test/test-functions.cpp @@ -108,6 +108,11 @@ TEST_CASE("functions") { // [json.exception.type_error.302] type must be array, but is number" ); } + SUBCASE("replace") { + CHECK(env.render("{{ replace(name, \"e\", \"3\") }}", data) == "P3t3r"); + CHECK(env.render("{{ replace(city, \" \", \"_\") }}", data) == "New_York"); + } + SUBCASE("round") { CHECK(env.render("{{ round(4, 0) }}", data) == "4"); CHECK(env.render("{{ round(temperature, 2) }}", data) == "25.68");