diff --git a/docs/guides/templating.md b/docs/guides/templating.md index cdf1952b3..47e54be3a 100644 --- a/docs/guides/templating.md +++ b/docs/guides/templating.md @@ -26,3 +26,8 @@ To return a mustache template, you need to load a page using `#!cpp auto page = 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;`).
With your context and page ready, just `#!cpp return page.render(ctx);`. This will use the context data to return a filled template.
Alternatively you could just render the page without a context using `#!cpp return page.render();`. + +!!! note + + `#!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. + diff --git a/include/crow/mustache.h b/include/crow/mustache.h index 866d8dc6c..e69be72e6 100644 --- a/include/crow/mustache.h +++ b/include/crow/mustache.h @@ -6,6 +6,7 @@ #include #include "crow/json.h" #include "crow/logging.h" +#include "crow/returnable.h" #include "crow/utility.h" namespace crow @@ -29,6 +30,22 @@ namespace crow std::string msg; }; + struct rendered_template : returnable + { + rendered_template(): + returnable("text/html") {} + + rendered_template(std::string& body): + returnable("text/html"), body_(std::move(body)) {} + + std::string body_; + + std::string dump() const override + { + return body_; + } + }; + enum class ActionType { Ignore, @@ -231,7 +248,7 @@ namespace crow while (execute_result.find("{{") != std::string::npos) { template_t result_plug(execute_result); - execute_result = result_plug.render(*(stack[0])); + execute_result = result_plug.render_string(*(stack[0])); } if (action.t == ActionType::Tag) @@ -339,7 +356,31 @@ namespace crow } public: - std::string render() const + /// Output a returnable template from this mustache template + rendered_template render() const + { + context empty_ctx; + std::vector stack; + stack.emplace_back(&empty_ctx); + + std::string ret; + render_internal(0, fragments_.size() - 1, stack, ret, 0); + return rendered_template(ret); + } + + /// Apply the values from the context provided and output a returnable template from this mustache template + rendered_template render(context& ctx) const + { + std::vector stack; + stack.emplace_back(&ctx); + + std::string ret; + render_internal(0, fragments_.size() - 1, stack, ret, 0); + return rendered_template(ret); + } + + /// Output a returnable template from this mustache template + std::string render_string() const { context empty_ctx; std::vector stack; @@ -349,7 +390,9 @@ namespace crow render_internal(0, fragments_.size() - 1, stack, ret, 0); return ret; } - std::string render(context& ctx) const + + /// Apply the values from the context provided and output a returnable template from this mustache template + std::string render_string(context& ctx) const { std::vector stack; stack.emplace_back(&ctx); diff --git a/tests/template/mustachetest.cpp b/tests/template/mustachetest.cpp index 5a347a712..2701be2c9 100644 --- a/tests/template/mustachetest.cpp +++ b/tests/template/mustachetest.cpp @@ -29,6 +29,6 @@ int main() return ""; }); context ctx(data); - cout << templ.render(ctx); + cout << templ.render_string(ctx); return 0; } diff --git a/tests/unittest.cpp b/tests/unittest.cpp index e74761c78..e8d6c1b3c 100644 --- a/tests/unittest.cpp +++ b/tests/unittest.cpp @@ -1136,7 +1136,7 @@ TEST_CASE("template_basic") auto t = crow::mustache::compile(R"---(attack of {{name}})---"); crow::mustache::context ctx; ctx["name"] = "killer tomatoes"; - auto result = t.render(ctx); + auto result = t.render_string(ctx); CHECK("attack of killer tomatoes" == result); } // template_basic @@ -1148,7 +1148,7 @@ TEST_CASE("template_function") ctx["func"] = [&](std::string) { return std::string("{{name}}, IN SPACE!"); }; - auto result = t.render(ctx); + auto result = t.render_string(ctx); CHECK("attack of killer tomatoes, IN SPACE!" == result); } @@ -1159,11 +1159,38 @@ TEST_CASE("template_load") auto t = crow::mustache::load("test.mustache"); crow::mustache::context ctx; ctx["name"] = "killer tomatoes"; - auto result = t.render(ctx); + auto result = t.render_string(ctx); CHECK("attack of killer tomatoes" == result); unlink("test.mustache"); } // template_load +TEST_CASE("TemplateRouting") +{ + SimpleApp app; + + CROW_ROUTE(app, "/temp") + ([] { + auto t = crow::mustache::compile(R"---(attack of {{name}})---"); + crow::mustache::context ctx; + ctx["name"] = "killer tomatoes"; + return crow::response(t.render(ctx)); + }); + + app.validate(); + + { + request req; + response res; + + req.url = "/temp"; + + app.handle(req, res); + + CHECK("attack of killer tomatoes" == res.body); + CHECK("text/html" == crow::get_header_value(res.headers, "Content-Type")); + } +} // PathRouting + TEST_CASE("black_magic") { using namespace black_magic;