minja: allow none input to selectattr, and add safe passthrough filter

This commit is contained in:
ochafik 2024-09-26 05:53:12 +01:00
parent 5f5be9cde7
commit 8e4a9bad8a
2 changed files with 7 additions and 0 deletions

View file

@ -2329,6 +2329,9 @@ inline std::shared_ptr<Context> Context::builtins() {
auto & items = args.at("items"); auto & items = args.at("items");
return (int64_t) items.size(); return (int64_t) items.size();
})); }));
globals.set("safe", simple_function("safe", { "value" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
return args.at("value");
}));
globals.set("list", simple_function("list", { "items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value { globals.set("list", simple_function("list", { "items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
auto & items = args.at("items"); auto & items = args.at("items");
if (!items.is_array()) throw std::runtime_error("object is not iterable"); if (!items.is_array()) throw std::runtime_error("object is not iterable");
@ -2415,6 +2418,8 @@ inline std::shared_ptr<Context> Context::builtins() {
globals.set("selectattr", Value::callable([=](const std::shared_ptr<Context> & context, Value::Arguments & args) { globals.set("selectattr", Value::callable([=](const std::shared_ptr<Context> & context, Value::Arguments & args) {
args.expectArgs("selectattr", {2, std::numeric_limits<size_t>::max()}, {0, 0}); args.expectArgs("selectattr", {2, std::numeric_limits<size_t>::max()}, {0, 0});
auto & items = args.args[0]; auto & items = args.args[0];
if (items.is_null())
return Value::array();
auto attr_name = args.args[1].get<std::string>(); auto attr_name = args.args[1].get<std::string>();
bool has_test = false; bool has_test = false;

View file

@ -149,7 +149,9 @@ static void test_error_contains(const std::string & template_str, const json & b
} }
static void test_template_features() { static void test_template_features() {
test_render(R"({{ 1 | safe }})", {}, {}, "1");
test_render(R"({{ 'abc'.endswith('bc') }},{{ ''.endswith('a') }})", {}, {}, "True,False"); test_render(R"({{ 'abc'.endswith('bc') }},{{ ''.endswith('a') }})", {}, {}, "True,False");
test_render(R"({{ none | selectattr("foo", "equalto", "bar") | list }})", {}, {}, "[]");
test_render(R"({{ 'a' in {"a": 1} }},{{ 'a' in {} }})", {}, {}, "True,False"); test_render(R"({{ 'a' in {"a": 1} }},{{ 'a' in {} }})", {}, {}, "True,False");
test_render(R"({{ 'a' in ["a"] }},{{ 'a' in [] }})", {}, {}, "True,False"); test_render(R"({{ 'a' in ["a"] }},{{ 'a' in [] }})", {}, {}, "True,False");
test_render(R"({{ [{"a": 1}, {"a": 2}, {}] | selectattr("a", "equalto", 1) }})", {}, {}, R"([{'a': 1}])"); test_render(R"({{ [{"a": 1}, {"a": 2}, {}] | selectattr("a", "equalto", 1) }})", {}, {}, R"([{'a': 1}])");