@@ -4014,48 +4014,80 @@ at_fn(dom::Value range, dom::Value field, dom::Value options)
40144014 }
40154015}
40164016
4017- dom::Value
4018- concat_fn (
4019- dom::Value range1,
4020- dom::Value sep,
4021- dom::Value range2,
4022- dom::Value options)
4017+ Expected<dom::Value>
4018+ concat_fn (dom::Array const & arguments)
40234019{
4024- auto isBlock = options.isUndefined () && static_cast <bool >(range2.get (" fn" ));
4020+ dom::Value options = arguments.back ();
4021+ dom::Value fn = options.get (" fn" );
4022+ auto const isBlock = static_cast <bool >(fn);
40254023 if (isBlock)
40264024 {
4027- options = range2;
4028- range2 = sep;
4029- sep = range1;
4030- range1 = options.get (" fn" )();
4025+ // Block overload: concatenate the contents of the
4026+ // block with the contents of the arguments as strings.
4027+ std::string str = static_cast <std::string>(fn ());
4028+ for (std::size_t i = 0 ; i < arguments.size () - 1 ; ++i)
4029+ {
4030+ str += toString (arguments.get (i));
4031+ }
4032+ return str;
40314033 }
40324034
4033- if (range1.isString () || range2.isString ())
4035+ // Check if we have at least one argument besides the options
4036+ if (arguments.size () == 1 )
40344037 {
4035- return range1 + sep + range2 ;
4038+ return Unexpected ( Error ( " #concat requires at least one argument " )) ;
40364039 }
4037- else if (range1.isArray () && sep.isArray ())
4040+
4041+ dom::Value firstArg = arguments.get (0 );
4042+
4043+ // Array overload: concatenate all arguments a single array.
4044+ if (firstArg.isArray ())
40384045 {
4039- options = range2;
4040- range2 = sep;
40414046 dom::Array res;
4042- for (dom::Value item : range1. getArray () )
4047+ for (std:: size_t i = 0 ; i < arguments. size () - 1 ; ++i )
40434048 {
4044- res.emplace_back (item);
4049+ dom::Value arg = arguments.get (i);
4050+ if (arg.isArray ())
4051+ {
4052+ for (dom::Value item : arg.getArray ())
4053+ {
4054+ res.emplace_back (item);
4055+ }
4056+ }
4057+ else
4058+ {
4059+ res.emplace_back (arg);
4060+ }
40454061 }
4046- for (dom::Value item : range2.getArray ())
4062+ return res;
4063+ }
4064+
4065+ // Object overload: concatenate all arguments into a single object.
4066+ if (firstArg.isObject ())
4067+ {
4068+ dom::Object res = firstArg.getObject ();
4069+ for (std::size_t i = 1 ; i < arguments.size () - 1 ; ++i)
40474070 {
4048- res.emplace_back (item);
4071+ dom::Value arg = arguments.get (i);
4072+ if (arg.isObject ())
4073+ {
4074+ res = createFrame (arg.getObject (), res);
4075+ }
4076+ else
4077+ {
4078+ return Unexpected (Error (" All arguments to #concat must be objects" ));
4079+ }
40494080 }
40504081 return res;
40514082 }
4052- else if (range1.isObject () && sep.isObject ())
4083+
4084+ // String overload: concatenate all arguments as strings.
4085+ std::string str;
4086+ for (std::size_t i = 0 ; i < arguments.size () - 1 ; ++i)
40534087 {
4054- options = range2;
4055- range2 = sep;
4056- return createFrame (range1.getObject (), range2.getObject ());
4088+ str += toString (arguments.get (i));
40574089 }
4058- return range1 + range2 ;
4090+ return str ;
40594091}
40604092
40614093std::int64_t
@@ -5107,7 +5139,7 @@ registerStringHelpers(Handlebars& hbs)
51075139 hbs.registerHelper (" join" , join_fn);
51085140 hbs.registerHelper (" implode" , join_fn);
51095141
5110- hbs.registerHelper (" concat" , dom::makeInvocable (concat_fn));
5142+ hbs.registerHelper (" concat" , dom::makeVariadicInvocable (concat_fn));
51115143
51125144 static auto strip_fn = dom::makeVariadicInvocable ([](
51135145 dom::Array const & arguments)
@@ -6570,7 +6602,7 @@ registerContainerHelpers(Handlebars& hbs)
65706602 return res2;
65716603 }));
65726604
6573- hbs.registerHelper (" concat" , dom::makeInvocable (concat_fn));
6605+ hbs.registerHelper (" concat" , dom::makeVariadicInvocable (concat_fn));
65746606
65756607 static auto flatten_fn = dom::makeInvocable ([](dom::Value const & collection, dom::Value const & key) -> dom::Value
65766608 {
0 commit comments