Skip to content

Commit 7510558

Browse files
committed
feat: builtin specs
1 parent f3e6861 commit 7510558

File tree

5 files changed

+704
-44
lines changed

5 files changed

+704
-44
lines changed

include/mrdox/Dom/Function.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class InvocableImpl : public FunctionImpl
255255
template<class F>
256256
Function makeInvocable(F&& f)
257257
{
258-
return newFunction<InvocableImpl<F>>(
258+
return newFunction<InvocableImpl<std::decay_t<F>>>(
259259
std::forward<F>(f));
260260
}
261261

include/mrdox/Dom/Function.ipp

+2
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ call_impl(
149149
Array const& args,
150150
std::index_sequence<I...>) const
151151
{
152+
if (args.size() < sizeof...(I))
153+
return Error("too few arguments");
152154
return f_(arg_type<std::decay_t<
153155
std::tuple_element_t<I, args_type> >
154156
>::get(args[I])...);

include/mrdox/Support/Handlebars.hpp

+15
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ class MRDOX_DECL OutputRef
281281
}
282282
};
283283

284+
class HandlebarsCallback;
285+
286+
namespace helpers {
287+
void
288+
unless_fn(
289+
dom::Array const& args,
290+
HandlebarsCallback const& options);
291+
}
292+
284293
/** Callback information for handlebars helpers
285294
286295
This class is used to pass information about the current
@@ -309,6 +318,12 @@ class MRDOX_DECL HandlebarsCallback
309318
detail::RenderState* renderState_;
310319
friend class Handlebars;
311320

321+
friend
322+
void
323+
helpers::unless_fn(
324+
dom::Array const& args,
325+
HandlebarsCallback const& options);
326+
312327
public:
313328
/** Render the block content with the specified context
314329

src/lib/Support/Handlebars.cpp

+30-43
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ isTruthy(dom::Value const& arg)
7979
return !arg.getString().empty();
8080
case dom::Kind::Array:
8181
case dom::Kind::Object:
82+
case dom::Kind::Function:
8283
return true;
8384
case dom::Kind::Null:
8485
return false;
@@ -1206,7 +1207,6 @@ render_to(
12061207
if (options.data.isNull())
12071208
{
12081209
state.data.set("root", context);
1209-
state.data.set("level", "warn");
12101210
}
12111211
else if (options.data.isObject())
12121212
{
@@ -1348,6 +1348,8 @@ JSON_stringify(
13481348
s += "}";
13491349
return s;
13501350
}
1351+
case dom::Kind::Function:
1352+
return "[Function]";
13511353
default:
13521354
MRDOX_UNREACHABLE();
13531355
}
@@ -2927,8 +2929,13 @@ if_fn(
29272929
return;
29282930
}
29292931

2930-
dom::Value const& conditional = args[0];
2931-
if (conditional.kind() == dom::Kind::Integer) {
2932+
dom::Value conditional = args[0];
2933+
if (conditional.isFunction())
2934+
{
2935+
conditional = conditional.getFunction()(options.context());
2936+
}
2937+
2938+
if (conditional.isInteger()) {
29322939
// Treat the zero path separately
29332940
std::int64_t v = conditional.getInteger();
29342941
if (v == 0) {
@@ -2947,7 +2954,7 @@ if_fn(
29472954
return;
29482955
}
29492956
}
2950-
if (isTruthy(conditional)) {
2957+
if (!isEmpty(conditional)) {
29512958
options.fn(out);
29522959
return;
29532960
}
@@ -2958,38 +2965,9 @@ void
29582965
unless_fn(
29592966
dom::Array const& args,
29602967
HandlebarsCallback const& options) {
2961-
OutputRef out = options.output();
2962-
auto r = validateArgs(options.name(), 1, args);
2963-
if (!r.empty()) {
2964-
out << r;
2965-
return;
2966-
}
2967-
2968-
dom::Value const& conditional = args[0];
2969-
if (conditional.kind() == dom::Kind::Integer) {
2970-
// Treat the zero path separately
2971-
std::int64_t v = conditional.getInteger();
2972-
if (v == 0) {
2973-
bool includeZero = false;
2974-
if (options.hashes().exists("includeZero")) {
2975-
auto zeroV = options.hashes().find("includeZero");
2976-
if (zeroV.isBoolean()) {
2977-
includeZero = zeroV.getBool();
2978-
}
2979-
}
2980-
if (includeZero) {
2981-
options.inverse(out);
2982-
} else {
2983-
options.fn(out);
2984-
}
2985-
return;
2986-
}
2987-
}
2988-
if (isTruthy(conditional)) {
2989-
options.inverse(out);
2990-
return;
2991-
}
2992-
options.fn(out);
2968+
HandlebarsCallback options2 = options;
2969+
std::swap(options2.fn_, options2.inverse_);
2970+
return if_fn(args, options2);
29932971
}
29942972

29952973
void
@@ -3003,6 +2981,10 @@ with_fn(
30032981
return;
30042982
}
30052983
dom::Value newContext = args[0];
2984+
if (newContext.isFunction()) {
2985+
newContext = newContext.getFunction()(options.context());
2986+
}
2987+
30062988
if (!isEmpty(newContext)) {
30072989
dom::Object data = createFrame(options.data());
30082990
std::string contextPath = appendContextPath(
@@ -3023,13 +3005,11 @@ void
30233005
each_fn(
30243006
dom::Array const& args,
30253007
HandlebarsCallback const& options) {
3026-
OutputRef out = options.output();
3027-
auto r = validateArgs(options.name(), 1, args);
3028-
if (!r.empty()) {
3029-
out << r;
3030-
return;
3008+
if (args.empty()) {
3009+
throw HandlebarsError("Must pass iterator to #each");
30313010
}
30323011

3012+
OutputRef out = options.output();
30333013
MRDOX_ASSERT(!options.ids().empty());
30343014
std::string contextPath = appendContextPath(
30353015
options.data().find("contextPath"), options.ids()[0]) + '.';
@@ -3038,6 +3018,10 @@ each_fn(
30383018
dom::Object blockValues;
30393019

30403020
dom::Value context = args[0];
3021+
if (context.isFunction()) {
3022+
context = context.getFunction()(options.context());
3023+
}
3024+
30413025
std::size_t index = 0;
30423026
if (context.isArray()) {
30433027
dom::Array const& items = context.getArray();
@@ -3101,9 +3085,12 @@ log_fn(
31013085
dom::Array const& args,
31023086
HandlebarsCallback const& options) {
31033087
dom::Value level = 1;
3104-
if (auto hl = options.hashes().find("level"); !hl.isNull()) {
3088+
if (auto hl = options.hashes().find("level"); !hl.isNull())
3089+
{
31053090
level = hl;
3106-
} else if (auto ol = options.hashes().find("level"); !ol.isNull()) {
3091+
}
3092+
else if (auto ol = options.data().find("level"); !ol.isNull())
3093+
{
31073094
level = ol;
31083095
}
31093096
options.log(level, args);

0 commit comments

Comments
 (0)