diff --git a/include/mstch/mstch.hpp b/include/mstch/mstch.hpp index faa9f57..0bd292a 100644 --- a/include/mstch/mstch.hpp +++ b/include/mstch/mstch.hpp @@ -4,12 +4,26 @@ #include #include #include +#include #include namespace mstch { + // booleans must be wrapped, because std::function is implicitly convertible + // to a bool. + class boolean { + private: + bool state; + public: + boolean(bool b): state(b) {} + operator bool() const { return state; } + }; + + using renderer = std::function; + using string_lambda = std::function; + using renderer_lambda = std::function()>; using node = boost::make_recursive_variant< - boost::blank, std::string, int, bool, + boost::blank, std::string, int, boolean, string_lambda, renderer_lambda, std::map, std::vector>::type; using object = std::map; diff --git a/src/visitor/is_node_empty.cpp b/src/visitor/is_node_empty.cpp index 2ee8c64..4a2313c 100644 --- a/src/visitor/is_node_empty.cpp +++ b/src/visitor/is_node_empty.cpp @@ -25,3 +25,11 @@ bool visitor::is_node_empty::operator()(const array& arr) const { bool visitor::is_node_empty::operator()(const object& obj) const { return false; } + +bool visitor::is_node_empty::operator()(const string_lambda& lambda) const { + return false; // TODO +} + +bool visitor::is_node_empty::operator()(const renderer_lambda& lambda) const { + return false; // TODO +} diff --git a/src/visitor/is_node_empty.hpp b/src/visitor/is_node_empty.hpp index 057b2db..6ff8c61 100644 --- a/src/visitor/is_node_empty.hpp +++ b/src/visitor/is_node_empty.hpp @@ -16,6 +16,8 @@ namespace mstch { bool operator()(const std::string& str) const; bool operator()(const array& arr) const; bool operator()(const object& obj) const; + bool operator()(const string_lambda& lambda) const; + bool operator()(const renderer_lambda& lambda) const; }; } } diff --git a/src/visitor/render_node.cpp b/src/visitor/render_node.cpp index 0ec94da..84d0cf0 100644 --- a/src/visitor/render_node.cpp +++ b/src/visitor/render_node.cpp @@ -31,3 +31,17 @@ std::string visitor::render_node::operator()(const array& arr) const { std::string visitor::render_node::operator()(const object& obj) const { return ""; } + +std::string visitor::render_node::operator()( + const string_lambda& lambda) const +{ + return this->operator()(lambda()); +} + +std::string visitor::render_node::operator()( + const renderer_lambda& lambda) const +{ + return this->operator()((lambda())("", [](const std::string& text) { + return std::string{""}; + })); +} diff --git a/src/visitor/render_node.hpp b/src/visitor/render_node.hpp index 449eb7a..e335979 100644 --- a/src/visitor/render_node.hpp +++ b/src/visitor/render_node.hpp @@ -22,6 +22,8 @@ namespace mstch { std::string operator()(const std::string& str) const; std::string operator()(const array& arr) const; std::string operator()(const object& obj) const; + std::string operator()(const string_lambda& lambda) const; + std::string operator()(const renderer_lambda& lambda) const; }; } } diff --git a/src/visitor/render_section.cpp b/src/visitor/render_section.cpp index 5fc0c82..7b8e7c2 100644 --- a/src/visitor/render_section.cpp +++ b/src/visitor/render_section.cpp @@ -46,3 +46,17 @@ std::string visitor::render_section::operator()(const array& a) const { render_section(context, section, {flag::keep_array}), item); return out.str(); } + +std::string visitor::render_section::operator()( + const string_lambda& lambda) const +{ + return lambda(); +} + +std::string visitor::render_section::operator()( + const renderer_lambda& lambda) const +{ + return (lambda())(section, [&](const std::string& text) { + return render_context(mstch::object{}, context).render(text); + }); +} diff --git a/src/visitor/render_section.hpp b/src/visitor/render_section.hpp index 729448d..3d831cc 100644 --- a/src/visitor/render_section.hpp +++ b/src/visitor/render_section.hpp @@ -28,6 +28,8 @@ namespace mstch { std::string operator()(const std::string& str) const; std::string operator()(const array& arr) const; std::string operator()(const object& obj) const; + std::string operator()(const string_lambda& lambda) const; + std::string operator()(const renderer_lambda& lambda) const; }; } } diff --git a/src/visitor/to_json.cpp b/src/visitor/to_json.cpp index 6ee3b27..f650d1b 100644 --- a/src/visitor/to_json.cpp +++ b/src/visitor/to_json.cpp @@ -41,3 +41,11 @@ std::string visitor::to_json::operator()(const object& obj) const { out << "}"; return out.str(); } + +std::string visitor::to_json::operator()(const string_lambda& lambda) const { + return ""; // TODO +} + +std::string visitor::to_json::operator()(const renderer_lambda& lambda) const { + return ""; // TODO +} diff --git a/src/visitor/to_json.hpp b/src/visitor/to_json.hpp index 2ece4a1..517b32e 100644 --- a/src/visitor/to_json.hpp +++ b/src/visitor/to_json.hpp @@ -17,6 +17,8 @@ namespace mstch { std::string operator()(const std::string& str) const; std::string operator()(const array& arr) const; std::string operator()(const object& obj) const; + std::string operator()(const string_lambda& lambda) const; + std::string operator()(const renderer_lambda& lambda) const; }; } } diff --git a/test/data/comments.data b/test/data/comments.data new file mode 100644 index 0000000..60ee923 --- /dev/null +++ b/test/data/comments.data @@ -0,0 +1,5 @@ +mstch::object{ + {"title", []() { + return std::string{"A Comedy of Errors"}; + }} +}; diff --git a/test/data/lambda/comments.mustache b/test/data/comments.mustache similarity index 100% rename from test/data/lambda/comments.mustache rename to test/data/comments.mustache diff --git a/test/data/lambda/comments.txt b/test/data/comments.txt similarity index 100% rename from test/data/lambda/comments.txt rename to test/data/comments.txt diff --git a/test/data/escaped.data b/test/data/escaped.data new file mode 100644 index 0000000..b9d881b --- /dev/null +++ b/test/data/escaped.data @@ -0,0 +1,6 @@ +mstch::object{ + {"title", []() { + return "Bear > Shark"; + }}, + {"entities", std::string{"" \"'<>/"}} +} diff --git a/test/data/lambda/escaped.mustache b/test/data/escaped.mustache similarity index 100% rename from test/data/lambda/escaped.mustache rename to test/data/escaped.mustache diff --git a/test/data/lambda/escaped.txt b/test/data/escaped.txt similarity index 100% rename from test/data/lambda/escaped.txt rename to test/data/escaped.txt diff --git a/test/data/lambda/comments.js b/test/data/lambda/comments.js deleted file mode 100644 index f20b8b1..0000000 --- a/test/data/lambda/comments.js +++ /dev/null @@ -1,5 +0,0 @@ -({ - title: function () { - return "A Comedy of Errors"; - } -}) diff --git a/test/data/lambda/escaped.js b/test/data/lambda/escaped.js deleted file mode 100644 index cd77c1f..0000000 --- a/test/data/lambda/escaped.js +++ /dev/null @@ -1,6 +0,0 @@ -({ - title: function () { - return "Bear > Shark"; - }, - entities: "" \"'<>/" -}) diff --git a/test/data/lambda/nested_higher_order_sections.js b/test/data/lambda/nested_higher_order_sections.js deleted file mode 100644 index 3ccf4d3..0000000 --- a/test/data/lambda/nested_higher_order_sections.js +++ /dev/null @@ -1,8 +0,0 @@ -({ - bold: function () { - return function (text, render) { - return '' + render(text) + ''; - }; - }, - person: { name: 'Jonas' } -}); diff --git a/test/data/lambda/partial_template.js b/test/data/lambda/partial_template.js deleted file mode 100644 index a913f87..0000000 --- a/test/data/lambda/partial_template.js +++ /dev/null @@ -1,6 +0,0 @@ -({ - title: function () { - return "Welcome"; - }, - again: "Goodbye" -}) diff --git a/test/data/lambda/section_functions_in_partials.js b/test/data/lambda/section_functions_in_partials.js deleted file mode 100644 index 4672778..0000000 --- a/test/data/lambda/section_functions_in_partials.js +++ /dev/null @@ -1,7 +0,0 @@ -({ - bold: function(){ - return function(text, render) { - return "" + render(text) + ""; - } - } -}) diff --git a/test/data/lambda/unescaped.js b/test/data/lambda/unescaped.js deleted file mode 100644 index b6d064f..0000000 --- a/test/data/lambda/unescaped.js +++ /dev/null @@ -1,5 +0,0 @@ -({ - title: function () { - return "Bear > Shark"; - } -}) diff --git a/test/data/nested_higher_order_sections.data b/test/data/nested_higher_order_sections.data new file mode 100644 index 0000000..80857ba --- /dev/null +++ b/test/data/nested_higher_order_sections.data @@ -0,0 +1,8 @@ +mstch::object{ + {"bold", []() { + return [](const std::string& text, mstch::renderer render) { + return std::string{""} + render(text) + std::string{""}; + }; + }}, + {"person", mstch::object{{"name", std::string{"Jonas"}}}} +} diff --git a/test/data/lambda/nested_higher_order_sections.mustache b/test/data/nested_higher_order_sections.mustache similarity index 100% rename from test/data/lambda/nested_higher_order_sections.mustache rename to test/data/nested_higher_order_sections.mustache diff --git a/test/data/lambda/nested_higher_order_sections.txt b/test/data/nested_higher_order_sections.txt similarity index 100% rename from test/data/lambda/nested_higher_order_sections.txt rename to test/data/nested_higher_order_sections.txt diff --git a/test/data/partial_template.data b/test/data/partial_template.data new file mode 100644 index 0000000..e650ead --- /dev/null +++ b/test/data/partial_template.data @@ -0,0 +1,6 @@ +mstch::object{ + {"title", []() { + return std::string{"Welcome"}; + }}, + {"again", std::string{"Goodbye"}} +} diff --git a/test/data/lambda/partial_template.mustache b/test/data/partial_template.mustache similarity index 100% rename from test/data/lambda/partial_template.mustache rename to test/data/partial_template.mustache diff --git a/test/data/lambda/partial_template.partial b/test/data/partial_template.partial similarity index 100% rename from test/data/lambda/partial_template.partial rename to test/data/partial_template.partial diff --git a/test/data/lambda/partial_template.txt b/test/data/partial_template.txt similarity index 100% rename from test/data/lambda/partial_template.txt rename to test/data/partial_template.txt diff --git a/test/data/section_functions_in_partials.data b/test/data/section_functions_in_partials.data new file mode 100644 index 0000000..723b053 --- /dev/null +++ b/test/data/section_functions_in_partials.data @@ -0,0 +1,7 @@ +mstch::object{ + {"bold", []() { + return [](const std::string& text, mstch::renderer render) { + return std::string{""} + render(text) + std::string{""}; + }; + }} +} diff --git a/test/data/lambda/section_functions_in_partials.mustache b/test/data/section_functions_in_partials.mustache similarity index 100% rename from test/data/lambda/section_functions_in_partials.mustache rename to test/data/section_functions_in_partials.mustache diff --git a/test/data/lambda/section_functions_in_partials.partial b/test/data/section_functions_in_partials.partial similarity index 100% rename from test/data/lambda/section_functions_in_partials.partial rename to test/data/section_functions_in_partials.partial diff --git a/test/data/lambda/section_functions_in_partials.txt b/test/data/section_functions_in_partials.txt similarity index 100% rename from test/data/lambda/section_functions_in_partials.txt rename to test/data/section_functions_in_partials.txt diff --git a/test/data/unescaped.data b/test/data/unescaped.data new file mode 100644 index 0000000..f953d1a --- /dev/null +++ b/test/data/unescaped.data @@ -0,0 +1,5 @@ +mstch::object{ + {"title", [](){ + return std::string{"Bear > Shark"}; + }} +} diff --git a/test/data/lambda/unescaped.mustache b/test/data/unescaped.mustache similarity index 100% rename from test/data/lambda/unescaped.mustache rename to test/data/unescaped.mustache diff --git a/test/data/lambda/unescaped.txt b/test/data/unescaped.txt similarity index 100% rename from test/data/lambda/unescaped.txt rename to test/data/unescaped.txt diff --git a/test/test_main.cpp b/test/test_main.cpp index 7bfdc95..af1def5 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -20,6 +20,7 @@ MSTCH_TEST(array_of_strings) MSTCH_TEST(backslashes) MSTCH_TEST(bug_11_eating_whitespace) MSTCH_TEST(bug_length_property) +MSTCH_TEST(comments) MSTCH_TEST(context_lookup) MSTCH_TEST(disappearing_whitespace) MSTCH_TEST(double_render) @@ -28,6 +29,7 @@ MSTCH_TEST(empty_sections) MSTCH_TEST(empty_string) MSTCH_TEST(empty_template) MSTCH_TEST(error_not_found) +MSTCH_TEST(escaped) MSTCH_TEST(falsy) MSTCH_TEST(falsy_array) MSTCH_TEST(grandparent_context) @@ -37,6 +39,7 @@ MSTCH_TEST(inverted_section) MSTCH_TEST(keys_with_questionmarks) MSTCH_TEST(multiline_comment) MSTCH_TEST(nested_dot) +MSTCH_TEST(nested_higher_order_sections) MSTCH_TEST(nested_iterating) MSTCH_TEST(nesting) MSTCH_TEST(nesting_same_name) @@ -47,11 +50,14 @@ MSTCH_PARTIAL_TEST(partial_array) MSTCH_PARTIAL_TEST(partial_array_of_partials) MSTCH_PARTIAL_TEST(partial_array_of_partials_implicit) MSTCH_PARTIAL_TEST(partial_empty) +MSTCH_PARTIAL_TEST(partial_template) MSTCH_TEST(recursion_with_same_names) MSTCH_TEST(reuse_of_enumerables) MSTCH_TEST(section_as_context) +MSTCH_PARTIAL_TEST(section_functions_in_partials) MSTCH_TEST(string_as_context) MSTCH_TEST(two_in_a_row) MSTCH_TEST(two_sections) +MSTCH_TEST(unescaped) MSTCH_TEST(whitespace) MSTCH_TEST(zero_view)