Skip to content

Commit 60d79ff

Browse files
committed
feat: find helper supports strings, arrays, and objects
1 parent cc9e397 commit 60d79ff

File tree

1 file changed

+115
-82
lines changed

1 file changed

+115
-82
lines changed

src/lib/Support/Handlebars.cpp

+115-82
Original file line numberDiff line numberDiff line change
@@ -4192,6 +4192,105 @@ replace_fn(dom::Array const& arguments)
41924192
}
41934193
}
41944194

4195+
dom::Value
4196+
find_index_fn(
4197+
dom::Array const& arguments)
4198+
{
4199+
dom::Value range;
4200+
dom::Value val;
4201+
std::int64_t start = 0;
4202+
std::int64_t end = 0;
4203+
4204+
std::size_t const n = arguments.size();
4205+
dom::Value options = arguments.back();
4206+
dom::Value fn = options.get("fn");
4207+
dom::Value firstArg = arguments.get(0);
4208+
dom::Value secondArg = arguments.get(1);
4209+
4210+
bool const isBlock = static_cast<bool>(fn);
4211+
if (isBlock)
4212+
{
4213+
// val, start, end
4214+
range = static_cast<std::string>(fn());
4215+
val = firstArg.getString();
4216+
end = static_cast<std::int64_t>(range.size());
4217+
if (n > 2)
4218+
{
4219+
start = secondArg.getInteger();
4220+
if (n > 3)
4221+
{
4222+
end = arguments.get(2).getInteger();
4223+
}
4224+
}
4225+
}
4226+
else
4227+
{
4228+
// range, val, start, end
4229+
range = firstArg;
4230+
val = secondArg;
4231+
end = static_cast<std::int64_t>(range.size());
4232+
if (n > 3)
4233+
{
4234+
start = arguments.at(2).getInteger();
4235+
if (n > 4)
4236+
{
4237+
end = arguments.at(3).getInteger();
4238+
}
4239+
}
4240+
}
4241+
start = normalize_index(start, static_cast<std::int64_t>(range.size()));
4242+
end = normalize_index(end, static_cast<std::int64_t>(range.size()));
4243+
if (range.isString())
4244+
{
4245+
// Find position of substring val in range
4246+
std::size_t pos = range.getString().get().find(val.getString(), start);
4247+
if (pos == std::string::npos || static_cast<std::int64_t>(pos) >= end) {
4248+
return static_cast<std::int64_t>(-1);
4249+
}
4250+
return static_cast<std::int64_t>(pos);
4251+
}
4252+
if (range.isArray())
4253+
{
4254+
// Find position of item val in array
4255+
auto const& arr = range.getArray();
4256+
for (std::int64_t i = start; i < end; i++)
4257+
{
4258+
if (arr.get(i) == val)
4259+
{
4260+
return i;
4261+
}
4262+
}
4263+
return static_cast<std::int64_t>(-1);
4264+
}
4265+
else if (range.isObject())
4266+
{
4267+
// Find key of item val in object
4268+
auto const& obj = range.getObject();
4269+
dom::Value res(dom::Kind::Undefined);
4270+
auto i = 0;
4271+
obj.visit([&](dom::String const& k, dom::Value const& v) -> bool
4272+
{
4273+
if (i < start)
4274+
{
4275+
++i;
4276+
return true;
4277+
}
4278+
if (i >= end)
4279+
{
4280+
return false;
4281+
}
4282+
if (v == val)
4283+
{
4284+
res = k;
4285+
return false;
4286+
}
4287+
return true;
4288+
});
4289+
return res;
4290+
}
4291+
return range;
4292+
}
4293+
41954294
void
41964295
registerStringHelpers(Handlebars& hbs)
41974296
{
@@ -4508,63 +4607,26 @@ registerStringHelpers(Handlebars& hbs)
45084607
return res;
45094608
}));
45104609

4511-
static constexpr auto find_index_fn = [](
4512-
dom::Array const& arguments)
4610+
hbs.registerHelper("find", dom::makeVariadicInvocable(find_index_fn));
4611+
hbs.registerHelper("index_of", dom::makeVariadicInvocable(find_index_fn));
4612+
4613+
hbs.registerHelper("includes", dom::makeVariadicInvocable([](
4614+
dom::Array const& arguments) -> bool
45134615
{
4514-
std::string str;
4515-
std::string sub;
4516-
std::int64_t start = 0;
4517-
std::int64_t end = 0;
4518-
std::size_t const n = arguments.size();
4519-
dom::Value options = arguments.back();
4520-
dom::Value fn = options.get("fn");
4521-
dom::Value firstArg = arguments.get(0);
4522-
dom::Value secondArg = arguments.get(1);
4523-
bool const isBlock = static_cast<bool>(fn);
4524-
if (isBlock)
4616+
dom::Value res = find_index_fn(arguments);
4617+
if (res.isInteger())
45254618
{
4526-
str = static_cast<std::string>(fn());
4527-
sub = firstArg.getString();
4528-
end = static_cast<std::int64_t>(str.size());
4529-
if (n > 2)
4530-
{
4531-
start = secondArg.getInteger();
4532-
if (n > 3)
4533-
{
4534-
end = arguments.at(2).getInteger();
4535-
}
4536-
}
4619+
return res.getInteger() >= 0;
45374620
}
4538-
else
4621+
if (res.isUndefined())
45394622
{
4540-
str = firstArg.getString();
4541-
sub = secondArg.getString();
4542-
end = static_cast<std::int64_t>(str.size());
4543-
if (n > 3)
4544-
{
4545-
start = arguments.at(2).getInteger();
4546-
if (n > 4)
4547-
{
4548-
end = arguments.at(3).getInteger();
4549-
}
4550-
}
4623+
return false;
45514624
}
4552-
start = normalize_index(start, static_cast<std::int64_t>(str.size()));
4553-
end = normalize_index(end, static_cast<std::int64_t>(str.size()));
4554-
std::size_t pos = str.find(sub, start);
4555-
if (pos == std::string::npos || static_cast<std::int64_t>(pos) >= end) {
4556-
return static_cast<std::int64_t>(-1);
4625+
if (res.isString())
4626+
{
4627+
return true;
45574628
}
4558-
return static_cast<std::int64_t>(pos);
4559-
};
4560-
4561-
hbs.registerHelper("find", dom::makeVariadicInvocable(find_index_fn));
4562-
hbs.registerHelper("index_of", dom::makeVariadicInvocable(find_index_fn));
4563-
4564-
hbs.registerHelper("includes", dom::makeVariadicInvocable([](
4565-
dom::Array const& arguments)
4566-
{
4567-
return find_index_fn(arguments) != -1;
4629+
return res.isTruthy();
45684630
}));
45694631

45704632
auto rfind_index_fn = [](
@@ -5700,37 +5762,8 @@ registerContainerHelpers(Handlebars& hbs)
57005762
hbs.registerHelper("del", del_fn);
57015763
hbs.registerHelper("delete", del_fn);
57025764

5703-
static auto find_fn = dom::makeInvocable([](
5704-
dom::Value range, dom::Value const& val) -> dom::Value {
5705-
if (range.isArray())
5706-
{
5707-
auto const& arr = range.getArray();
5708-
auto const n = static_cast<std::int64_t>(arr.size());
5709-
for (std::int64_t i = 0; i < n; i++)
5710-
{
5711-
if (arr[i] == val)
5712-
return i;
5713-
}
5714-
return static_cast<std::int64_t>(-1);
5715-
}
5716-
else if (range.isObject())
5717-
{
5718-
auto const& obj = range.getObject();
5719-
for (auto const& [k, v]: obj)
5720-
{
5721-
if (v == val)
5722-
return k;
5723-
}
5724-
return nullptr;
5725-
}
5726-
else
5727-
{
5728-
return range;
5729-
}
5730-
});
5731-
5732-
hbs.registerHelper("find", find_fn);
5733-
hbs.registerHelper("index_of", find_fn);
5765+
hbs.registerHelper("find", dom::makeVariadicInvocable(find_index_fn));
5766+
hbs.registerHelper("index_of", dom::makeVariadicInvocable(find_index_fn));
57345767

57355768
static auto has_fn = dom::makeInvocable([](
57365769
dom::Value const& ctx, dom::Value const& prop)

0 commit comments

Comments
 (0)