@@ -5695,6 +5695,39 @@ registerStringHelpers(Handlebars& hbs)
56955695 }));
56965696}
56975697
5698+ std::vector<std::string>
5699+ parseKeyPath (std::string const & keyPath)
5700+ {
5701+ std::vector<std::string> keys;
5702+ std::istringstream iss (keyPath);
5703+ std::string token;
5704+
5705+ while (std::getline (iss, token, ' .' ))
5706+ {
5707+ keys.push_back (token);
5708+ }
5709+
5710+ return keys;
5711+ }
5712+
5713+ dom::Value
5714+ getNestedValue (dom::Value const & obj, std::vector<std::string> const & keys)
5715+ {
5716+ dom::Value current = obj;
5717+ for (auto const & key : keys)
5718+ {
5719+ if (current.isObject () && current.getObject ().exists (key))
5720+ {
5721+ current = current.getObject ().get (key);
5722+ }
5723+ else
5724+ {
5725+ return dom::Value ();
5726+ }
5727+ }
5728+ return current;
5729+ }
5730+
56985731void
56995732registerContainerHelpers (Handlebars& hbs)
57005733{
@@ -6405,6 +6438,90 @@ registerContainerHelpers(Handlebars& hbs)
64056438 }));
64066439
64076440 hbs.registerHelper (" concat" , dom::makeInvocable (concat_fn));
6441+
6442+ static auto flatten_fn = dom::makeInvocable ([](dom::Value const & collection, dom::Value const & key) -> dom::Value
6443+ {
6444+ dom::Array result;
6445+
6446+ if (!collection.isArray ())
6447+ {
6448+ return result;
6449+ }
6450+
6451+ std::string const keyPath (key.getString ());
6452+ auto const keys = parseKeyPath (keyPath);
6453+
6454+ auto const & arr = collection.getArray ();
6455+ for (auto const & item : arr)
6456+ {
6457+ dom::Value const innerCollection = getNestedValue (item, keys);
6458+ if (innerCollection.isArray ())
6459+ {
6460+ auto const & innerArray = innerCollection.getArray ();
6461+ for (auto const & innerItem : innerArray)
6462+ {
6463+ result.emplace_back (innerItem);
6464+ }
6465+ }
6466+ }
6467+
6468+ return result;
6469+ });
6470+
6471+ hbs.registerHelper (" flatten" , flatten_fn);
6472+
6473+ static auto flattenUnique_fn = dom::makeInvocable ([](dom::Value const & collection, dom::Value const & key, dom::Value const & uniqueKey) -> dom::Value
6474+ {
6475+ dom::Array result;
6476+ std::unordered_set<std::string> seen;
6477+
6478+ if (!collection.isArray ())
6479+ {
6480+ return result;
6481+ }
6482+
6483+ if (key.empty () || uniqueKey.empty ())
6484+ {
6485+ return result;
6486+ }
6487+
6488+ if (!key.isString () || !uniqueKey.isString ())
6489+ {
6490+ return result;
6491+ }
6492+
6493+ std::string const keyPath (key.getString ());
6494+ auto const keys = parseKeyPath (keyPath);
6495+ std::string const uniqueKeyPath (uniqueKey.getString ());
6496+ auto const uniqueKeys = parseKeyPath (uniqueKeyPath);
6497+
6498+ auto const & arr = collection.getArray ();
6499+ for (auto const & item : arr)
6500+ {
6501+ dom::Value const innerCollection = getNestedValue (item, keys);
6502+ if (innerCollection.isArray ())
6503+ {
6504+ auto const & innerArray = innerCollection.getArray ();
6505+ for (auto const & innerItem : innerArray)
6506+ {
6507+ dom::Value const uniqueValue = getNestedValue (innerItem, uniqueKeys);
6508+ if (uniqueValue.isString ())
6509+ {
6510+ std::string uniqueStr (uniqueValue.getString ());
6511+ if (seen.find (uniqueStr) == seen.end ())
6512+ {
6513+ seen.insert (uniqueStr);
6514+ result.emplace_back (innerItem);
6515+ }
6516+ }
6517+ }
6518+ }
6519+ }
6520+
6521+ return result;
6522+ });
6523+
6524+ hbs.registerHelper (" flattenUnique" , flattenUnique_fn);
64086525}
64096526
64106527} // helpers
0 commit comments