Skip to content

Commit 4a6d5fe

Browse files
authored
Merge pull request #346 from CrowCpp/returnable_template
Returnable template
2 parents d43d680 + 4650b5e commit 4a6d5fe

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

docs/guides/templating.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ To return a mustache template, you need to load a page using `#!cpp auto page =
2626
You also need to set up the context by using `#!cpp crow::mustache::context ctx;`. Then you need to assign the keys and values, this can be done the same way you assign values to a json write value (`ctx["key"] = value;`).<br>
2727
With your context and page ready, just `#!cpp return page.render(ctx);`. This will use the context data to return a filled template.<br>
2828
Alternatively you could just render the page without a context using `#!cpp return page.render();`.
29+
30+
!!! note
31+
32+
`#!cpp page.render();` returns a crow::returnable class in order to set the `Content-Type` header. to get a simple string, use `#!cpp page.render_string()` instead.
33+

include/crow/mustache.h

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <functional>
77
#include "crow/json.h"
88
#include "crow/logging.h"
9+
#include "crow/returnable.h"
910
#include "crow/utility.h"
1011

1112
namespace crow
@@ -29,6 +30,22 @@ namespace crow
2930
std::string msg;
3031
};
3132

33+
struct rendered_template : returnable
34+
{
35+
rendered_template():
36+
returnable("text/html") {}
37+
38+
rendered_template(std::string& body):
39+
returnable("text/html"), body_(std::move(body)) {}
40+
41+
std::string body_;
42+
43+
std::string dump() const override
44+
{
45+
return body_;
46+
}
47+
};
48+
3249
enum class ActionType
3350
{
3451
Ignore,
@@ -231,7 +248,7 @@ namespace crow
231248
while (execute_result.find("{{") != std::string::npos)
232249
{
233250
template_t result_plug(execute_result);
234-
execute_result = result_plug.render(*(stack[0]));
251+
execute_result = result_plug.render_string(*(stack[0]));
235252
}
236253

237254
if (action.t == ActionType::Tag)
@@ -339,7 +356,31 @@ namespace crow
339356
}
340357

341358
public:
342-
std::string render() const
359+
/// Output a returnable template from this mustache template
360+
rendered_template render() const
361+
{
362+
context empty_ctx;
363+
std::vector<context*> stack;
364+
stack.emplace_back(&empty_ctx);
365+
366+
std::string ret;
367+
render_internal(0, fragments_.size() - 1, stack, ret, 0);
368+
return rendered_template(ret);
369+
}
370+
371+
/// Apply the values from the context provided and output a returnable template from this mustache template
372+
rendered_template render(context& ctx) const
373+
{
374+
std::vector<context*> stack;
375+
stack.emplace_back(&ctx);
376+
377+
std::string ret;
378+
render_internal(0, fragments_.size() - 1, stack, ret, 0);
379+
return rendered_template(ret);
380+
}
381+
382+
/// Output a returnable template from this mustache template
383+
std::string render_string() const
343384
{
344385
context empty_ctx;
345386
std::vector<context*> stack;
@@ -349,7 +390,9 @@ namespace crow
349390
render_internal(0, fragments_.size() - 1, stack, ret, 0);
350391
return ret;
351392
}
352-
std::string render(context& ctx) const
393+
394+
/// Apply the values from the context provided and output a returnable template from this mustache template
395+
std::string render_string(context& ctx) const
353396
{
354397
std::vector<context*> stack;
355398
stack.emplace_back(&ctx);

tests/template/mustachetest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ int main()
2929
return "";
3030
});
3131
context ctx(data);
32-
cout << templ.render(ctx);
32+
cout << templ.render_string(ctx);
3333
return 0;
3434
}

tests/unittest.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,7 +1136,7 @@ TEST_CASE("template_basic")
11361136
auto t = crow::mustache::compile(R"---(attack of {{name}})---");
11371137
crow::mustache::context ctx;
11381138
ctx["name"] = "killer tomatoes";
1139-
auto result = t.render(ctx);
1139+
auto result = t.render_string(ctx);
11401140
CHECK("attack of killer tomatoes" == result);
11411141
} // template_basic
11421142

@@ -1148,7 +1148,7 @@ TEST_CASE("template_function")
11481148
ctx["func"] = [&](std::string) {
11491149
return std::string("{{name}}, IN SPACE!");
11501150
};
1151-
auto result = t.render(ctx);
1151+
auto result = t.render_string(ctx);
11521152
CHECK("attack of killer tomatoes, IN SPACE!" == result);
11531153
}
11541154

@@ -1159,11 +1159,38 @@ TEST_CASE("template_load")
11591159
auto t = crow::mustache::load("test.mustache");
11601160
crow::mustache::context ctx;
11611161
ctx["name"] = "killer tomatoes";
1162-
auto result = t.render(ctx);
1162+
auto result = t.render_string(ctx);
11631163
CHECK("attack of killer tomatoes" == result);
11641164
unlink("test.mustache");
11651165
} // template_load
11661166

1167+
TEST_CASE("TemplateRouting")
1168+
{
1169+
SimpleApp app;
1170+
1171+
CROW_ROUTE(app, "/temp")
1172+
([] {
1173+
auto t = crow::mustache::compile(R"---(attack of {{name}})---");
1174+
crow::mustache::context ctx;
1175+
ctx["name"] = "killer tomatoes";
1176+
return crow::response(t.render(ctx));
1177+
});
1178+
1179+
app.validate();
1180+
1181+
{
1182+
request req;
1183+
response res;
1184+
1185+
req.url = "/temp";
1186+
1187+
app.handle(req, res);
1188+
1189+
CHECK("attack of killer tomatoes" == res.body);
1190+
CHECK("text/html" == crow::get_header_value(res.headers, "Content-Type"));
1191+
}
1192+
} // PathRouting
1193+
11671194
TEST_CASE("black_magic")
11681195
{
11691196
using namespace black_magic;

0 commit comments

Comments
 (0)