pax_global_header00006660000000000000000000000064126537355160014527gustar00rootroot0000000000000052 comment=ff459067bd02e80dc399006bb610238223d41c50 mstch-1.0.2/000077500000000000000000000000001265373551600126455ustar00rootroot00000000000000mstch-1.0.2/.appveyor.yml000066400000000000000000000026331265373551600153170ustar00rootroot00000000000000environment: matrix: - GENERATOR: "Visual Studio 12 2013" CONFIG: Release BOOST_ROOT: "C:\\Libraries\\boost" BOOST_LIBRARYDIR: "C:\\Libraries\\boost\\lib32-msvc-12.0" - GENERATOR: "Visual Studio 14 2015" CONFIG: Release BOOST_ROOT: "C:\\Libraries\\boost_1_59_0" BOOST_LIBRARYDIR: "C:\\Libraries\\boost_1_59_0\\lib32-msvc-14.0" - GENERATOR: "Visual Studio 14 2015 Win64" CONFIG: Release BOOST_ROOT: "C:\\Libraries\\boost_1_59_0" BOOST_LIBRARYDIR: "C:\\Libraries\\boost_1_59_0\\lib64-msvc-14.0" - GENERATOR: "Visual Studio 12 2013" CONFIG: Debug BOOST_ROOT: "C:\\Libraries\\boost" BOOST_LIBRARYDIR: "C:\\Libraries\\boost\\lib32-msvc-12.0" - GENERATOR: "Visual Studio 14 2015" CONFIG: Debug BOOST_ROOT: "C:\\Libraries\\boost_1_59_0" BOOST_LIBRARYDIR: "C:\\Libraries\\boost_1_59_0\\lib32-msvc-14.0" - GENERATOR: "Visual Studio 14 2015 Win64" CONFIG: Debug BOOST_ROOT: "C:\\Libraries\\boost_1_59_0" BOOST_LIBRARYDIR: "C:\\Libraries\\boost_1_59_0\\lib64-msvc-14.0" install: - git submodule init - git submodule update build_script: - mkdir build - cd build - cmake "-G%GENERATOR%" -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" -DBoost_USE_STATIC_LIBS=ON -DWITH_UNIT_TESTS=ON .. - cmake --build . --config "%CONFIG%" test_script: - ctest --build-config "%CONFIG%" mstch-1.0.2/.gitignore000066400000000000000000000000151265373551600146310ustar00rootroot00000000000000.idea build* mstch-1.0.2/.gitmodules000066400000000000000000000007601265373551600150250ustar00rootroot00000000000000[submodule "vendor/Catch"] path = vendor/Catch url = https://github.com/philsquared/Catch.git [submodule "vendor/spec"] path = vendor/spec url = https://github.com/mustache/spec.git [submodule "vendor/benchmark"] path = vendor/benchmark url = https://github.com/google/benchmark.git [submodule "vendor/headerize"] path = vendor/headerize url = https://github.com/no1msd/headerize.git [submodule "vendor/rapidjson"] path = vendor/rapidjson url = https://github.com/miloyip/rapidjson.git mstch-1.0.2/.travis.yml000066400000000000000000000067421265373551600147670ustar00rootroot00000000000000language: cpp sudo: false matrix: include: - env: - COMPILER=g++-5 - WITH_UNIT_TESTS=ON addons: apt: sources: - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - g++-5 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=g++-4.9 - WITH_UNIT_TESTS=ON addons: apt: sources: - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - g++-4.9 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=g++-4.8 - WITH_UNIT_TESTS=ON addons: apt: sources: - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - g++-4.8 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=g++-4.7 - WITH_UNIT_TESTS=ON addons: apt: sources: - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - g++-4.7 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=clang++-3.5 - WITH_UNIT_TESTS=ON addons: apt: sources: - llvm-toolchain-precise-3.5 - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - clang-3.5 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=clang++-3.6 - WITH_UNIT_TESTS=ON addons: apt: sources: - llvm-toolchain-precise-3.6 - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - clang-3.6 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=clang++-3.7 - WITH_UNIT_TESTS=ON addons: apt: sources: - llvm-toolchain-precise-3.7 - ubuntu-toolchain-r-test - boost-latest - george-edison55-precise-backports packages: - clang-3.7 - cmake - cmake-data - libboost1.55-dev - libboost-regex1.55-dev - libboost-program-options1.55-dev os: linux - env: - COMPILER=clang++ - WITH_UNIT_TESTS=ON os: osx before_script: - export CXX=${COMPILER} - ${COMPILER} --version - mkdir build - cd build - cmake -DWITH_UNIT_TESTS=${WITH_UNIT_TESTS} .. script: make after_script: make test mstch-1.0.2/CMakeLists.txt000066400000000000000000000012101265373551600153770ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(mstch) option(WITH_UNIT_TESTS "enable building unit test executable" OFF) option(WITH_BENCHMARK "enable building benchmark executable" OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) set(CMAKE_BUILD_TYPE Release) set(mstch_VERSION 1.0.1) if(NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -O3") endif() add_subdirectory(src) if(WITH_UNIT_TESTS) enable_testing() add_subdirectory(vendor/headerize) add_subdirectory(test) endif() if(WITH_BENCHMARK) add_subdirectory(vendor/benchmark) add_subdirectory(benchmark) endif() mstch-1.0.2/LICENSE000066400000000000000000000020701265373551600136510ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Daniel Sipka Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mstch-1.0.2/README.md000066400000000000000000000164341265373551600141340ustar00rootroot00000000000000# mstch - {{mustache}} templates in C++11 ![mstch logo](http://i.imgur.com/MRyStO5.png) mstch is a complete implementation of [{{mustache}}](http://mustache.github.io/) templates using modern C++. It's compliant with [specifications](https://github.com/mustache/spec) v1.1.3, including the lambda module. [![GitHub version](https://badge.fury.io/gh/no1msd%2Fmstch.svg)](http://badge.fury.io/gh/no1msd%2Fmstch) [![Build Status](https://travis-ci.org/no1msd/mstch.svg?branch=master)](https://travis-ci.org/no1msd/mstch) [![Build status](https://ci.appveyor.com/api/projects/status/d6mxp0uba5646x16?svg=true)](https://ci.appveyor.com/project/no1msd/mstch) ## Supported features mstch supports the complete feature set described in the `mustache(5)` [manpage](http://mustache.github.com/mustache.5.html): - JSON-like data structure using [Boost.Variant](http://www.boost.org/libs/variant) - variables, sections, inverted sections - partials - changing the delimiter - C++11 lambdas - C++ objects as view models ## Basic usage ```c++ #include #include int main() { std::string view{"{{#names}}Hi {{name}}!\n{{/names}}"}; mstch::map context{ {"names", mstch::array{ mstch::map{{"name", std::string{"Chris"}}}, mstch::map{{"name", std::string{"Mark"}}}, mstch::map{{"name", std::string{"Scott"}}}, }} }; std::cout << mstch::render(view, context) << std::endl; return 0; } ``` The output of this example will be: ```html Hi Chris! Hi Mark! Hi Scott! ``` ### Data structure The types in the example above, `mstch::array` and `mstch::map` are actually aliases for standard types: ```c++ using map = std::map; using array = std::vector; ``` `mstch::node` is a `boost::variant` that can hold a `std::string`, `int`, `double`, `bool`, `mstch::lambda` or a `std::shared_ptr` (see below), also a map or an array recursively. Essentially it works just like a JSON object. Note that when using a `std::string` as value you must explicitly specify the type, since a `const char*` literal like `"foobar"` would be implicitly converted to `bool`. Alternatively you can use [C++14 string_literals](http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s) if your compiler supports it. ## Advanced usage ### Partials Partials can be passed in a `std::map` as the third parameter of the `mstch::render` function: ```c++ std::string view{"{{#names}}{{> user}}{{/names}}"}; std::string user_view{"{{name}}\n"}; mstch::map context{ {"names", mstch::array{ mstch::map{{"name", std::string{"Chris"}}}, mstch::map{{"name", std::string{"Mark"}}}, mstch::map{{"name", std::string{"Scott"}}}, }} }; std::cout << mstch::render(view, context, {{"user", user_view}}) << std::endl; ``` Output: ```html Chris Mark Scott ``` ### Lambdas C++11 lambda expressions can be used to add logic to your templates. Like a `const char*` literal, lambdas can be implicitly converted to `bool`, so they must be wrapped in a `mstch::lambda` object when used in a `mstch::node`. The lambda expression passed to `mstch::lambda` must itself return a `mstch::node`. The returned node will be rendered to a string, then it will be parsed as a template. The lambda expression accepts either no parameters: ```c++ std::string view{"Hello {{lambda}}!"}; mstch::map context{ {"lambda", mstch::lambda{[]() -> mstch::node { return std::string{"World"}; }}} }; std::cout << mstch::render(view, context) << std::endl; ``` Output: ```html Hello World! ``` Or it accepts a `const std::string&` that gets the unrendered literal block: ```c++ std::string view{"{{#bold}}{{yay}} :){{/bold}}"}; mstch::map context{ {"yay", std::string{"Yay!"}}, {"bold", mstch::lambda{[](const std::string& text) -> mstch::node { return "" + text + ""; }}} }; std::cout << mstch::render(view, context) << std::endl; ``` Output: ```html Yay! :) ``` ### Objects Custom objects can also be used as context for rendering templates. The class must inherit from `mstch::object`, and register it's exported methods with `register_methods`. Exported methods must have the return type of `mstch::node`. Objects must be created as a `std::shared_ptr`. ```c++ class example: public mstch::object { public: example(): m_value(1) { register_methods(this, { {"count", &example::count}, {"names", &example::names} }); } mstch::node count() { return m_value++; } mstch::node names() { return mstch::array{ std::string{"Chris"}, std::string{"Mark"}, std::string{"Scott"}}; } private: int m_value; }; std::string view{"{{#names}}{{count}}: {{.}}\n{{/names}}"}; const auto context = std::make_shared(); std::cout << mstch::render(view, context) << std::endl; ``` Output: ```html 1: Chris 2: Mark 3: Scott ``` ### Custom escape function By default, mstch uses HTML escaping on the output, as per specification. This is not useful if your output is not HTML, so mstch provides a way to supply your own escape implementation. Just assign any callable object to the static `mstch::config::escape`, which is an initially empty `std::function`. For example you can turn off escaping entirely with a lambda: ```c++ mstch::config::escape = [](const std::string& str) -> std::string { return str; }; ``` ## Requirements - A C++ compiler with decent C++11 support. Currently tested with: - GCC 4.7, 4.8, 4.9, 5.1 - clang 3.5, 3.6, 3.7 (both libstdc++ and libc++ are supported) - MSVC 2013, 2015 - Boost 1.54+ for [Boost.Variant](http://www.boost.org/libs/variant) - CMake 3.0+ for building ## Using mstch in your project If you are using CMake, the easiest way to include mstch in your project is to copy the whole directory to your source tree, and use `add_subdirectory` in your CMakeLists.txt. This will set a variable named `mstch_INCLUDE_DIR` that contains its include path, and add a static library target named `mstch`. For example: ```cmake add_subdirectory(external/mstch) include_directories(${mstch_INCLUDE_DIR}) target_link_libraries(your_project mstch) ``` If you prefer to install the library globally, you can simply do the following from the root of the source tree: ```bash $ mkdir build $ cd build $ cmake .. $ make $ make install ``` The install command may require root privileges. This will also install CMake config files, so you can use use `find_package` in your CMakeLists.txt: ```cmake find_package(mstch) target_link_libraries(your_project mstch::mstch) ``` ## Running the unit tests Unit tests are using the [Catch](https://github.com/philsquared/Catch) framework and [rapidjson](http://rapidjson.org/) to parse the [Mustache specifications](https://github.com/mustache/spec), all of which are included in the repository as git submodules. Various [Boost](http://www.boost.org/) libraries are also required to build them. Don't forget to initialize submodules: ```bash $ git submodule init $ git submodule update ``` To build and run the unit tests: ```bash $ mkdir build $ cd build $ cmake -DWITH_UNIT_TESTS=ON .. $ make $ make test ``` ## License mstch is licensed under the [MIT license](https://github.com/no1msd/mstch/blob/master/LICENSE). mstch-1.0.2/benchmark/000077500000000000000000000000001265373551600145775ustar00rootroot00000000000000mstch-1.0.2/benchmark/CMakeLists.txt000066400000000000000000000003161265373551600173370ustar00rootroot00000000000000include_directories( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/vendor/benchmark/include) add_executable(mstch_benchmark benchmark_main.cpp) target_link_libraries(mstch_benchmark mstch benchmark) mstch-1.0.2/benchmark/benchmark_main.cpp000066400000000000000000000021401265373551600202360ustar00rootroot00000000000000#include #include "mstch/mstch.hpp" static void basic_usage(benchmark::State& state) { std::string comment_tmp{ "

{{header}}

    " "{{#comments}}
  • {{name}}
    " "

    {{body}}

  • {{/comments}}
"}; auto comment_view = mstch::map{ {"header", std::string{"My Post Comments"}}, {"comments", mstch::array{ mstch::map{{"name", std::string{"Joe"}}, {"body", std::string{"Thanks for this post!"}}}, mstch::map{{"name", std::string{"Sam"}}, {"body", std::string{"Thanks for this post!"}}}, mstch::map{{"name", std::string{"Heather"}}, {"body", std::string{"Thanks for this post!"}}}, mstch::map{{"name", std::string{"Kathy"}}, {"body", std::string{"Thanks for this post!"}}}, mstch::map{{"name", std::string{"George"}}, {"body", std::string{"Thanks for this post!"}}}}}}; while (state.KeepRunning()) mstch::render(comment_tmp, comment_view); } BENCHMARK(basic_usage); BENCHMARK_MAIN(); mstch-1.0.2/cmake/000077500000000000000000000000001265373551600137255ustar00rootroot00000000000000mstch-1.0.2/cmake/mstch-config.cmake000066400000000000000000000000701265373551600173050ustar00rootroot00000000000000include("${CMAKE_CURRENT_LIST_DIR}/mstch-targets.cmake")mstch-1.0.2/include/000077500000000000000000000000001265373551600142705ustar00rootroot00000000000000mstch-1.0.2/include/mstch/000077500000000000000000000000001265373551600154065ustar00rootroot00000000000000mstch-1.0.2/include/mstch/mstch.hpp000066400000000000000000000055441265373551600172450ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include namespace mstch { struct config { static std::function escape; }; namespace internal { template class object_t { public: const N& at(const std::string& name) const { cache[name] = (methods.at(name))(); return cache[name]; } bool has(const std::string name) const { return methods.count(name) != 0; } protected: template void register_methods(S* s, std::map methods) { for(auto& item: methods) this->methods.insert({item.first, std::bind(item.second, s)}); } private: std::map> methods; mutable std::map cache; }; template class is_fun { private: using not_fun = char; using fun_without_args = char[2]; using fun_with_args = char[3]; template struct really_has; template static fun_without_args& test( really_has*); template static fun_with_args& test( really_has*); template static not_fun& test(...); public: static bool const no_args = sizeof(test(0)) == sizeof(fun_without_args); static bool const has_args = sizeof(test(0)) == sizeof(fun_with_args); }; template using node_renderer = std::function; template class lambda_t { public: template lambda_t(F f, typename std::enable_if::no_args>::type* = 0): fun([f](node_renderer renderer, const std::string&) { return renderer(f()); }) { } template lambda_t(F f, typename std::enable_if::has_args>::type* = 0): fun([f](node_renderer renderer, const std::string& text) { return renderer(f(text)); }) { } std::string operator()(node_renderer renderer, const std::string& text = "") const { return fun(renderer, text); } private: std::function renderer, const std::string&)> fun; }; } using node = boost::make_recursive_variant< std::nullptr_t, std::string, int, double, bool, internal::lambda_t, std::shared_ptr>, std::map, std::vector>::type; using object = internal::object_t; using lambda = internal::lambda_t; using map = std::map; using array = std::vector; std::string render( const std::string& tmplt, const node& root, const std::map& partials = std::map()); } mstch-1.0.2/src/000077500000000000000000000000001265373551600134345ustar00rootroot00000000000000mstch-1.0.2/src/CMakeLists.txt000066400000000000000000000031021265373551600161700ustar00rootroot00000000000000find_package(Boost 1.54 REQUIRED) set(mstch_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include CACHE STRING "mstch include directory") include_directories( ${mstch_INCLUDE_DIR} ${Boost_INCLUDE_DIR}) set(SRC state/in_section.cpp state/outside_section.cpp state/render_state.hpp visitor/get_token.hpp visitor/has_token.hpp visitor/is_node_empty.hpp visitor/render_node.hpp visitor/render_section.hpp mstch.cpp render_context.cpp template_type.cpp token.cpp utils.cpp) add_library(mstch STATIC ${SRC}) set_property(TARGET mstch PROPERTY VERSION ${mstch_VERSION}) install( TARGETS mstch EXPORT mstchTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) install( FILES "${PROJECT_SOURCE_DIR}/include/mstch/mstch.hpp" DESTINATION include/mstch COMPONENT Devel) include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/mstch/mstch-config-version.cmake" VERSION ${mstch_VERSION} COMPATIBILITY AnyNewerVersion) export( EXPORT mstchTargets FILE "${CMAKE_CURRENT_BINARY_DIR}/mstch/mstch-targets.cmake" NAMESPACE mstch::) configure_file( "${PROJECT_SOURCE_DIR}/cmake/mstch-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/mstch/mstch-config.cmake") install( EXPORT mstchTargets FILE mstch-targets.cmake NAMESPACE mstch:: DESTINATION lib/cmake/mstch) install(FILES "${PROJECT_SOURCE_DIR}/cmake/mstch-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/mstch/mstch-config-version.cmake" DESTINATION lib/cmake/mstch COMPONENT Devel) mstch-1.0.2/src/mstch.cpp000066400000000000000000000010241265373551600152530ustar00rootroot00000000000000#include #include "mstch/mstch.hpp" #include "render_context.hpp" using namespace mstch; std::function mstch::config::escape; std::string mstch::render( const std::string& tmplt, const node& root, const std::map& partials) { std::map partial_templates; for (auto& partial: partials) partial_templates.insert({partial.first, {partial.second}}); return render_context(root, partial_templates).render(tmplt); } mstch-1.0.2/src/render_context.cpp000066400000000000000000000040771265373551600171730ustar00rootroot00000000000000#include "render_context.hpp" #include "state/outside_section.hpp" #include "visitor/get_token.hpp" using namespace mstch; const mstch::node render_context::null_node; render_context::push::push(render_context& context, const mstch::node& node): m_context(context) { context.m_nodes.emplace_front(node); context.m_node_ptrs.emplace_front(&node); context.m_state.push(std::unique_ptr(new outside_section)); } render_context::push::~push() { m_context.m_nodes.pop_front(); m_context.m_node_ptrs.pop_front(); m_context.m_state.pop(); } std::string render_context::push::render(const template_type& templt) { return m_context.render(templt); } render_context::render_context( const mstch::node& node, const std::map& partials): m_partials(partials), m_nodes(1, node), m_node_ptrs(1, &node) { m_state.push(std::unique_ptr(new outside_section)); } const mstch::node& render_context::find_node( const std::string& token, std::list current_nodes) { if (token != "." && token.find('.') != std::string::npos) return find_node(token.substr(token.rfind('.') + 1), {&find_node(token.substr(0, token.rfind('.')), current_nodes)}); else for (auto& node: current_nodes) if (visit(has_token(token), *node)) return visit(get_token(token, *node), *node); return null_node; } const mstch::node& render_context::get_node(const std::string& token) { return find_node(token, m_node_ptrs); } std::string render_context::render( const template_type& templt, const std::string& prefix) { std::string output; bool prev_eol = true; for (auto& token: templt) { if (prev_eol && prefix.length() != 0) output += m_state.top()->render(*this, {prefix}); output += m_state.top()->render(*this, token); prev_eol = token.eol(); } return output; } std::string render_context::render_partial( const std::string& partial_name, const std::string& prefix) { return m_partials.count(partial_name) ? render(m_partials.at(partial_name), prefix) : ""; } mstch-1.0.2/src/render_context.hpp000066400000000000000000000024531265373551600171740ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include "mstch/mstch.hpp" #include "state/render_state.hpp" #include "template_type.hpp" namespace mstch { class render_context { public: class push { public: push(render_context& context, const mstch::node& node = {}); ~push(); std::string render(const template_type& templt); private: render_context& m_context; }; render_context( const mstch::node& node, const std::map& partials); const mstch::node& get_node(const std::string& token); std::string render( const template_type& templt, const std::string& prefix = ""); std::string render_partial( const std::string& partial_name, const std::string& prefix); template void set_state(Args&& ... args) { m_state.top() = std::unique_ptr( new T(std::forward(args)...)); } private: static const mstch::node null_node; const mstch::node& find_node( const std::string& token, std::list current_nodes); std::map m_partials; std::deque m_nodes; std::list m_node_ptrs; std::stack> m_state; }; } mstch-1.0.2/src/state/000077500000000000000000000000001265373551600145545ustar00rootroot00000000000000mstch-1.0.2/src/state/in_section.cpp000066400000000000000000000021711265373551600174130ustar00rootroot00000000000000#include "in_section.hpp" #include "outside_section.hpp" #include "visitor/is_node_empty.hpp" #include "visitor/render_section.hpp" using namespace mstch; in_section::in_section(type type, const token& start_token): m_type(type), m_start_token(start_token), m_skipped_openings(0) { } std::string in_section::render(render_context& ctx, const token& token) { if (token.token_type() == token::type::section_close) if (token.name() == m_start_token.name() && m_skipped_openings == 0) { auto& node = ctx.get_node(m_start_token.name()); std::string out; if (m_type == type::normal && !visit(is_node_empty(), node)) out = visit(render_section(ctx, m_section, m_start_token.delims()), node); else if (m_type == type::inverted && visit(is_node_empty(), node)) out = render_context::push(ctx).render(m_section); ctx.set_state(); return out; } else m_skipped_openings--; else if (token.token_type() == token::type::inverted_section_open || token.token_type() == token::type::section_open) m_skipped_openings++; m_section << token; return ""; } mstch-1.0.2/src/state/in_section.hpp000066400000000000000000000007221265373551600174200ustar00rootroot00000000000000#pragma once #include #include #include "render_state.hpp" #include "template_type.hpp" namespace mstch { class in_section: public render_state { public: enum class type { inverted, normal }; in_section(type type, const token& start_token); std::string render(render_context& context, const token& token) override; private: const type m_type; const token& m_start_token; template_type m_section; int m_skipped_openings; }; } mstch-1.0.2/src/state/outside_section.cpp000066400000000000000000000017211265373551600204610ustar00rootroot00000000000000#include "outside_section.hpp" #include "visitor/render_node.hpp" #include "in_section.hpp" #include "render_context.hpp" using namespace mstch; std::string outside_section::render( render_context& ctx, const token& token) { using flag = render_node::flag; switch (token.token_type()) { case token::type::section_open: ctx.set_state(in_section::type::normal, token); break; case token::type::inverted_section_open: ctx.set_state(in_section::type::inverted, token); break; case token::type::variable: return visit(render_node(ctx, flag::escape_html), ctx.get_node(token.name())); case token::type::unescaped_variable: return visit(render_node(ctx, flag::none), ctx.get_node(token.name())); case token::type::text: return token.raw(); case token::type::partial: return ctx.render_partial(token.name(), token.partial_prefix()); default: break; } return ""; } mstch-1.0.2/src/state/outside_section.hpp000066400000000000000000000003061265373551600204640ustar00rootroot00000000000000#pragma once #include "render_state.hpp" namespace mstch { class outside_section: public render_state { public: std::string render(render_context& context, const token& token) override; }; } mstch-1.0.2/src/state/render_state.hpp000066400000000000000000000003611265373551600177440ustar00rootroot00000000000000#pragma once #include #include "token.hpp" namespace mstch { class render_context; class render_state { public: virtual ~render_state() {} virtual std::string render(render_context& context, const token& token) = 0; }; } mstch-1.0.2/src/template_type.cpp000066400000000000000000000060141265373551600170150ustar00rootroot00000000000000#include "template_type.hpp" using namespace mstch; template_type::template_type(const std::string& str, const delim_type& delims): m_open(delims.first), m_close(delims.second) { tokenize(str); strip_whitespace(); } template_type::template_type(const std::string& str): m_open("{{"), m_close("}}") { tokenize(str); strip_whitespace(); } void template_type::process_text(citer begin, citer end) { if (begin == end) return; auto start = begin; for (auto it = begin; it != end; ++it) if (*it == '\n' || it == end - 1) { m_tokens.push_back({{start, it + 1}}); start = it + 1; } } void template_type::tokenize(const std::string& tmp) { citer beg = tmp.begin(); auto npos = std::string::npos; for (std::size_t cur_pos = 0; cur_pos < tmp.size();) { auto open_pos = tmp.find(m_open, cur_pos); auto close_pos = tmp.find( m_close, open_pos == npos ? open_pos : open_pos + 1); if (close_pos != npos && open_pos != npos) { if (*(beg + open_pos + m_open.size()) == '{' && *(beg + close_pos + m_close.size()) == '}') ++close_pos; process_text(beg + cur_pos, beg + open_pos); cur_pos = close_pos + m_close.size(); m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()}, m_open.size(), m_close.size()}); if (cur_pos == tmp.size()) { m_tokens.push_back({{""}}); m_tokens.back().eol(true); } if (*(beg + open_pos + m_open.size()) == '=' && *(beg + close_pos - 1) == '=') { auto tok_beg = beg + open_pos + m_open.size() + 1; auto tok_end = beg + close_pos - 1; auto front_skip = first_not_ws(tok_beg, tok_end); auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg)); m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)}; m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1}; } } else { process_text(beg + cur_pos, tmp.end()); cur_pos = close_pos; } } } void template_type::strip_whitespace() { auto line_begin = m_tokens.begin(); bool has_tag = false, non_space = false; for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) { auto type = (*it).token_type(); if (type != token::type::text && type != token::type::variable && type != token::type::unescaped_variable) has_tag = true; else if (!(*it).ws_only()) non_space = true; if ((*it).eol()) { if (has_tag && !non_space) { store_prefixes(line_begin); auto c = line_begin; for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c) if ((end = (*c).eol())) it = c - 1; } non_space = has_tag = false; line_begin = it + 1; } } } void template_type::store_prefixes(std::vector::iterator beg) { for (auto cur = beg; !(*cur).eol(); ++cur) if ((*cur).token_type() == token::type::partial && cur != beg && (*(cur - 1)).ws_only()) (*cur).partial_prefix((*(cur - 1)).raw()); } mstch-1.0.2/src/template_type.hpp000066400000000000000000000013771265373551600170310ustar00rootroot00000000000000#pragma once #include #include #include "token.hpp" #include "utils.hpp" namespace mstch { class template_type { public: template_type() = default; template_type(const std::string& str); template_type(const std::string& str, const delim_type& delims); std::vector::const_iterator begin() const { return m_tokens.begin(); } std::vector::const_iterator end() const { return m_tokens.end(); } void operator<<(const token& token) { m_tokens.push_back(token); } private: std::vector m_tokens; std::string m_open; std::string m_close; void strip_whitespace(); void process_text(citer beg, citer end); void tokenize(const std::string& tmp); void store_prefixes(std::vector::iterator beg); }; } mstch-1.0.2/src/token.cpp000066400000000000000000000027311265373551600152630ustar00rootroot00000000000000#include "token.hpp" #include "utils.hpp" using namespace mstch; token::type token::token_info(char c) { switch (c) { case '>': return type::partial; case '^': return type::inverted_section_open; case '/': return type::section_close; case '&': return type::unescaped_variable; case '#': return type::section_open; case '!': return type::comment; default: return type::variable; } } token::token(const std::string& str, std::size_t left, std::size_t right): m_raw(str), m_eol(false), m_ws_only(false) { if (left != 0 && right != 0) { if (str[left] == '=' && str[str.size() - right - 1] == '=') { m_type = type::delimiter_change; } else if (str[left] == '{' && str[str.size() - right - 1] == '}') { m_type = type::unescaped_variable; m_name = {first_not_ws(str.begin() + left + 1, str.end() - right), first_not_ws(str.rbegin() + 1 + right, str.rend() - left) + 1}; } else { auto c = first_not_ws(str.begin() + left, str.end() - right); m_type = token_info(*c); if (m_type != type::variable) c = first_not_ws(c + 1, str.end() - right); m_name = {c, first_not_ws(str.rbegin() + right, str.rend() - left) + 1}; m_delims = {{str.begin(), str.begin() + left}, {str.end() - right, str.end()}}; } } else { m_type = type::text; m_eol = (str.size() > 0 && str[str.size() - 1] == '\n'); m_ws_only = (str.find_first_not_of(" \r\n\t") == std::string::npos); } } mstch-1.0.2/src/token.hpp000066400000000000000000000020511265373551600152630ustar00rootroot00000000000000#pragma once #include namespace mstch { using delim_type = std::pair; class token { public: enum class type { text, variable, section_open, section_close, inverted_section_open, unescaped_variable, comment, partial, delimiter_change }; token(const std::string& str, std::size_t left = 0, std::size_t right = 0); type token_type() const { return m_type; }; const std::string& raw() const { return m_raw; }; const std::string& name() const { return m_name; }; const std::string& partial_prefix() const { return m_partial_prefix; }; const delim_type& delims() const { return m_delims; }; void partial_prefix(const std::string& p_partial_prefix) { m_partial_prefix = p_partial_prefix; }; bool eol() const { return m_eol; } void eol(bool eol) { m_eol = eol; } bool ws_only() const { return m_ws_only; } private: type m_type; std::string m_name; std::string m_raw; std::string m_partial_prefix; delim_type m_delims; bool m_eol; bool m_ws_only; type token_info(char c); }; } mstch-1.0.2/src/utils.cpp000066400000000000000000000023611265373551600153020ustar00rootroot00000000000000#include "utils.hpp" #include "mstch/mstch.hpp" mstch::citer mstch::first_not_ws(mstch::citer begin, mstch::citer end) { for (auto it = begin; it != end; ++it) if (*it != ' ') return it; return end; } mstch::citer mstch::first_not_ws(mstch::criter begin, mstch::criter end) { for (auto rit = begin; rit != end; ++rit) if (*rit != ' ') return --(rit.base()); return --(end.base()); } mstch::criter mstch::reverse(mstch::citer it) { return std::reverse_iterator(it); } std::string mstch::html_escape(const std::string& str) { if (mstch::config::escape) return mstch::config::escape(str); std::string out; citer start = str.begin(); auto add_escape = [&out, &start](const std::string& escaped, citer& it) { out += std::string{start, it} + escaped; start = it + 1; }; for (auto it = str.begin(); it != str.end(); ++it) switch (*it) { case '&': add_escape("&", it); break; case '\'': add_escape("'", it); break; case '"': add_escape(""", it); break; case '<': add_escape("<", it); break; case '>': add_escape(">", it); break; case '/': add_escape("/", it); break; default: break; } return out + std::string{start, str.end()}; } mstch-1.0.2/src/utils.hpp000066400000000000000000000010371265373551600153060ustar00rootroot00000000000000#pragma once #include #include namespace mstch { using citer = std::string::const_iterator; using criter = std::string::const_reverse_iterator; citer first_not_ws(citer begin, citer end); citer first_not_ws(criter begin, criter end); std::string html_escape(const std::string& str); criter reverse(citer it); template auto visit(Args&&... args) -> decltype(boost::apply_visitor( std::forward(args)...)) { return boost::apply_visitor(std::forward(args)...); } } mstch-1.0.2/src/visitor/000077500000000000000000000000001265373551600151335ustar00rootroot00000000000000mstch-1.0.2/src/visitor/get_token.hpp000066400000000000000000000012621265373551600176240ustar00rootroot00000000000000#pragma once #include #include "mstch/mstch.hpp" #include "has_token.hpp" namespace mstch { class get_token: public boost::static_visitor { public: get_token(const std::string& token, const mstch::node& node): m_token(token), m_node(node) { } template const mstch::node& operator()(const T&) const { return m_node; } const mstch::node& operator()(const map& map) const { return map.at(m_token); } const mstch::node& operator()(const std::shared_ptr& object) const { return object->at(m_token); } private: const std::string& m_token; const mstch::node& m_node; }; } mstch-1.0.2/src/visitor/has_token.hpp000066400000000000000000000010461265373551600176200ustar00rootroot00000000000000#pragma once #include #include "mstch/mstch.hpp" namespace mstch { class has_token: public boost::static_visitor { public: has_token(const std::string& token): m_token(token) { } template bool operator()(const T&) const { return m_token == "."; } bool operator()(const map& map) const { return map.count(m_token) == 1; } bool operator()(const std::shared_ptr& object) const { return object->has(m_token); } private: const std::string& m_token; }; } mstch-1.0.2/src/visitor/is_node_empty.hpp000066400000000000000000000013021265373551600204760ustar00rootroot00000000000000#pragma once #include #include "mstch/mstch.hpp" namespace mstch { class is_node_empty: public boost::static_visitor { public: template bool operator()(const T&) const { return false; } bool operator()(const std::nullptr_t&) const { return true; } bool operator()(const int& value) const { return value == 0; } bool operator()(const double& value) const { return value == 0; } bool operator()(const bool& value) const { return !value; } bool operator()(const std::string& value) const { return value == ""; } bool operator()(const array& array) const { return array.size() == 0; } }; } mstch-1.0.2/src/visitor/render_node.hpp000066400000000000000000000024221265373551600201300ustar00rootroot00000000000000#pragma once #include #include #include "render_context.hpp" #include "mstch/mstch.hpp" #include "utils.hpp" namespace mstch { class render_node: public boost::static_visitor { public: enum class flag { none, escape_html }; render_node(render_context& ctx, flag p_flag = flag::none): m_ctx(ctx), m_flag(p_flag) { } template std::string operator()(const T&) const { return ""; } std::string operator()(const int& value) const { return std::to_string(value); } std::string operator()(const double& value) const { std::stringstream ss; ss << value; return ss.str(); } std::string operator()(const bool& value) const { return value ? "true" : "false"; } std::string operator()(const lambda& value) const { template_type interpreted{value([this](const mstch::node& n) { return visit(render_node(m_ctx), n); })}; auto rendered = render_context::push(m_ctx).render(interpreted); return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered; } std::string operator()(const std::string& value) const { return (m_flag == flag::escape_html) ? html_escape(value) : value; } private: render_context& m_ctx; flag m_flag; }; } mstch-1.0.2/src/visitor/render_section.hpp000066400000000000000000000026751265373551600206610ustar00rootroot00000000000000#pragma once #include #include "render_context.hpp" #include "mstch/mstch.hpp" #include "utils.hpp" #include "render_node.hpp" namespace mstch { class render_section: public boost::static_visitor { public: enum class flag { none, keep_array }; render_section( render_context& ctx, const template_type& section, const delim_type& delims, flag p_flag = flag::none): m_ctx(ctx), m_section(section), m_delims(delims), m_flag(p_flag) { } template std::string operator()(const T& t) const { return render_context::push(m_ctx, t).render(m_section); } std::string operator()(const lambda& fun) const { std::string section_str; for (auto& token: m_section) section_str += token.raw(); template_type interpreted{fun([this](const mstch::node& n) { return visit(render_node(m_ctx), n); }, section_str), m_delims}; return render_context::push(m_ctx).render(interpreted); } std::string operator()(const array& array) const { std::string out; if (m_flag == flag::keep_array) return render_context::push(m_ctx, array).render(m_section); else for (auto& item: array) out += visit(render_section( m_ctx, m_section, m_delims, flag::keep_array), item); return out; } private: render_context& m_ctx; const template_type& m_section; const delim_type& m_delims; flag m_flag; }; } mstch-1.0.2/test/000077500000000000000000000000001265373551600136245ustar00rootroot00000000000000mstch-1.0.2/test/CMakeLists.txt000066400000000000000000000042521265373551600163670ustar00rootroot00000000000000find_package(Boost 1.54 REQUIRED) include_directories( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/vendor/Catch/single_include ${CMAKE_SOURCE_DIR}/vendor/rapidjson/include ${Boost_INCLUDE_DIR}) file(GLOB data_files RELATIVE "${CMAKE_SOURCE_DIR}/test/data" "${CMAKE_SOURCE_DIR}/test/data/*.hpp") foreach(data_file ${data_files}) string(REGEX REPLACE "\\.hpp" "" test_name "${data_file}") list(APPEND tests "${test_name}") endforeach(data_file) file(GLOB string_files RELATIVE "${CMAKE_SOURCE_DIR}/test/data" "${CMAKE_SOURCE_DIR}/test/data/*.mustache" "${CMAKE_SOURCE_DIR}/test/data/*.txt" "${CMAKE_SOURCE_DIR}/test/data/*.partial") foreach(string_file ${string_files}) list(APPEND genargs "-i${string_file}") endforeach(string_file) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp COMMAND headerize --output ${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp --namespace mstchtest ${genargs} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test/data/) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp PROPERTIES GENERATED TRUE) add_custom_target(test_data_hpp DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/test_data.hpp) file(GLOB specs_files RELATIVE "${CMAKE_SOURCE_DIR}/vendor/spec/specs" "${CMAKE_SOURCE_DIR}/vendor/spec/specs/*.json") foreach(specs_file ${specs_files}) list(APPEND specsargs "-i${specs_file}") string(REGEX REPLACE "\\.json" "" test_name "${specs_file}") string(REGEX REPLACE "~" "" test_name "${test_name}") list(APPEND tests "specs_${test_name}") endforeach(specs_file) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp COMMAND headerize --output ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp --namespace mstchtest ${specsargs} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/vendor/spec/specs/) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp PROPERTIES GENERATED TRUE) add_custom_target(specs_data_hpp DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/specs_data.hpp) add_executable(mstch_test test_main.cpp) target_link_libraries(mstch_test mstch) add_dependencies(mstch_test test_data_hpp specs_data_hpp) foreach(test ${tests}) add_test(NAME ${test} COMMAND mstch_test ${test}) endforeach(test) mstch-1.0.2/test/data/000077500000000000000000000000001265373551600145355ustar00rootroot00000000000000mstch-1.0.2/test/data/ampersand_escape.hpp000066400000000000000000000001331265373551600205350ustar00rootroot00000000000000const auto ampersand_escape_data = mstch::map{ {"message", std::string{"Some "}} };mstch-1.0.2/test/data/ampersand_escape.mustache000066400000000000000000000000151265373551600215560ustar00rootroot00000000000000{{&message}} mstch-1.0.2/test/data/ampersand_escape.txt000066400000000000000000000000141265373551600205630ustar00rootroot00000000000000Some mstch-1.0.2/test/data/apostrophe.hpp000066400000000000000000000001511265373551600174270ustar00rootroot00000000000000const auto apostrophe_data = mstch::map{ {"apos", std::string{"'"}}, {"control", std::string{"X"}} };mstch-1.0.2/test/data/apostrophe.mustache000066400000000000000000000000241265373551600204500ustar00rootroot00000000000000{{apos}}{{control}} mstch-1.0.2/test/data/apostrophe.txt000066400000000000000000000000071265373551600174570ustar00rootroot00000000000000'X mstch-1.0.2/test/data/array_of_strings.hpp000066400000000000000000000002021265373551600206130ustar00rootroot00000000000000const auto array_of_strings_data = mstch::map{ {"array_of_strings", mstch::array{std::string{"hello"}, std::string{"world"}}} };mstch-1.0.2/test/data/array_of_strings.mustache000066400000000000000000000000611265373551600216400ustar00rootroot00000000000000{{#array_of_strings}}{{.}} {{/array_of_strings}} mstch-1.0.2/test/data/array_of_strings.txt000066400000000000000000000000151265373551600206450ustar00rootroot00000000000000hello world mstch-1.0.2/test/data/backslashes.hpp000066400000000000000000000001161265373551600175270ustar00rootroot00000000000000const auto backslashes_data = mstch::map{ {"value", std::string{"\\abc"}} };mstch-1.0.2/test/data/backslashes.mustache000066400000000000000000000001561265373551600205550ustar00rootroot00000000000000* {{value}} * {{{value}}} * {{&value}} mstch-1.0.2/test/data/backslashes.txt000066400000000000000000000001341265373551600175570ustar00rootroot00000000000000* \abc * \abc * \abc mstch-1.0.2/test/data/bug_11_eating_whitespace.hpp000066400000000000000000000001261265373551600220660ustar00rootroot00000000000000const auto bug_11_eating_whitespace_data = mstch::map{ {"tag", std::string{"yo"}} };mstch-1.0.2/test/data/bug_11_eating_whitespace.mustache000066400000000000000000000000141265373551600231040ustar00rootroot00000000000000{{tag}} foo mstch-1.0.2/test/data/bug_11_eating_whitespace.txt000066400000000000000000000000071265373551600221140ustar00rootroot00000000000000yo foo mstch-1.0.2/test/data/bug_length_property.hpp000066400000000000000000000001311265373551600213230ustar00rootroot00000000000000const auto bug_length_property_data = mstch::map{ {"length", std::string{"hello"}} };mstch-1.0.2/test/data/bug_length_property.mustache000066400000000000000000000000711265373551600223500ustar00rootroot00000000000000{{#length}}The length variable is: {{length}}{{/length}} mstch-1.0.2/test/data/bug_length_property.txt000066400000000000000000000000361265373551600213570ustar00rootroot00000000000000The length variable is: hello mstch-1.0.2/test/data/changing_delimiters.hpp000066400000000000000000000002151265373551600212430ustar00rootroot00000000000000const mstch::node changing_delimiters_data = mstch::map{ {"foo", std::string{"foooooooooooooo"}}, {"bar", std::string{"bar!"}} }; mstch-1.0.2/test/data/changing_delimiters.mustache000066400000000000000000000000611265373551600222640ustar00rootroot00000000000000{{=<% %>=}}<% foo %> {{foo}} <%{bar}%> {{{bar}}} mstch-1.0.2/test/data/changing_delimiters.txt000066400000000000000000000000561265373551600212760ustar00rootroot00000000000000foooooooooooooo {{foo}} bar! {{{bar}}} mstch-1.0.2/test/data/comments.hpp000066400000000000000000000002131265373551600170670ustar00rootroot00000000000000const mstch::node comments_data = mstch::map{ {"title", mstch::lambda{[]()->mstch::node{return std::string{"A Comedy of Errors"};}}} };mstch-1.0.2/test/data/comments.mustache000066400000000000000000000001011265373551600201050ustar00rootroot00000000000000

{{title}}{{! just something interesting... or not... }}

mstch-1.0.2/test/data/comments.txt000066400000000000000000000000341265373551600171200ustar00rootroot00000000000000

A Comedy of Errors

mstch-1.0.2/test/data/complex.hpp000066400000000000000000000030101265373551600167070ustar00rootroot00000000000000class complex_item: public mstch::object { private: std::string m_name; bool m_current; std::string m_url; public: complex_item(const std::string& name, bool current, const std::string& url): m_name(name), m_current(current), m_url(url) { register_methods(this, std::map{ {"name", &complex_item::name}, {"current", &complex_item::current}, {"url", &complex_item::url}, {"link", &complex_item::link} }); } mstch::node current() { return m_current; } mstch::node url() { return m_url; } mstch::node name() { return m_name; } mstch::node link() { return !m_current; } }; class complex: public mstch::object { private: std::string m_header; mstch::array m_item; public: complex(): m_header("Colors"), m_item(mstch::array{ std::make_shared("red", true, "#Red"), std::make_shared("green", false, "#Green"), std::make_shared("blue", false, "#Blue") }) { register_methods(this, std::map{ {"header", &complex::header}, {"item", &complex::item}, {"list", &complex::list}, {"empty", &complex::empty} }); } mstch::node header() { return m_header; } mstch::node item() { return m_item; } mstch::node list() { return m_item.size() != 0; } mstch::node empty() { return m_item.size() == 0; } }; const auto complex_data = std::make_shared();mstch-1.0.2/test/data/complex.mustache000066400000000000000000000004061265373551600177370ustar00rootroot00000000000000

{{header}}

{{#list}}
    {{#item}} {{#current}}
  • {{name}}
  • {{/current}} {{#link}}
  • {{name}}
  • {{/link}} {{/item}}
{{/list}} {{#empty}}

The list is empty.

{{/empty}} mstch-1.0.2/test/data/complex.txt000066400000000000000000000002111265373551600167370ustar00rootroot00000000000000

Colors

mstch-1.0.2/test/data/context_lookup.hpp000066400000000000000000000002221265373551600203170ustar00rootroot00000000000000const auto context_lookup_data = mstch::map{ {"outer", mstch::map{ {"id", 1}, {"second", mstch::map{ {"nothing", 2} }} }} };mstch-1.0.2/test/data/context_lookup.mustache000066400000000000000000000000611265373551600213420ustar00rootroot00000000000000{{#outer}}{{#second}}{{id}}{{/second}}{{/outer}} mstch-1.0.2/test/data/context_lookup.txt000066400000000000000000000000021265373551600203430ustar00rootroot000000000000001 mstch-1.0.2/test/data/delimiters.hpp000066400000000000000000000004471265373551600174140ustar00rootroot00000000000000const mstch::node delimiters_data = mstch::map{ {"first", std::string{"It worked the first time."}}, {"second", std::string{"And it worked the second time."}}, {"third", std::string{"Then, surprisingly, it worked the third time."}}, {"fourth", std::string{"Fourth time also fine!."}} }; mstch-1.0.2/test/data/delimiters.mustache000066400000000000000000000001271265373551600204310ustar00rootroot00000000000000{{=<% %>=}}* <% first %> * <% second %> <%=| |=%> * | third | |={{ }}=| * {{ fourth }} mstch-1.0.2/test/data/delimiters.txt000066400000000000000000000002071265373551600174360ustar00rootroot00000000000000* It worked the first time. * And it worked the second time. * Then, surprisingly, it worked the third time. * Fourth time also fine!. mstch-1.0.2/test/data/disappearing_whitespace.hpp000066400000000000000000000001351265373551600221270ustar00rootroot00000000000000const auto disappearing_whitespace_data = mstch::map{ {"bedrooms", true}, {"total", 1} };mstch-1.0.2/test/data/disappearing_whitespace.mustache000066400000000000000000000000501265373551600231450ustar00rootroot00000000000000{{#bedrooms}}{{total}}{{/bedrooms}} BED mstch-1.0.2/test/data/disappearing_whitespace.txt000066400000000000000000000000061265373551600221540ustar00rootroot000000000000001 BED mstch-1.0.2/test/data/dot_notation.hpp000066400000000000000000000017321265373551600177520ustar00rootroot00000000000000class dot_notation_price: public mstch::object { private: int m_value; mstch::map m_currency; public: dot_notation_price(): m_value(200), m_currency(mstch::map{{"symbol", std::string{"$"}}, {"name", std::string{"USD"}}}) { register_methods(this, std::map{ {"value", &dot_notation_price::value}, {"vat", &dot_notation_price::vat}, {"currency", &dot_notation_price::currency}}); } mstch::node value() { return m_value; } mstch::node vat() { return m_value * 0.2; } mstch::node currency() { return m_currency; } }; const auto dot_notation_data = mstch::map{ {"name", std::string{"A Book"}}, {"authors", mstch::array{std::string{"John Power"}, std::string{"Jamie Walsh"}}}, {"price", std::make_shared()}, {"availability", mstch::map{{"status", true}, {"text", std::string{"In Stock"}}}}, {"truthy", mstch::map{{"zero", 0}, {"notTrue", false}}} };mstch-1.0.2/test/data/dot_notation.mustache000066400000000000000000000006471265373551600210000ustar00rootroot00000000000000

{{name}}

Authors:

    {{#authors}}
  • {{.}}
  • {{/authors}}

Price: {{{price.currency.symbol}}}{{price.value}} {{#price.currency}}{{name}} {{availability.text}}{{/price.currency}}

VAT: {{{price.currency.symbol}}}{{#price}}{{vat}}{{/price}}

Test truthy false values:

Zero: {{truthy.zero}}

False: {{truthy.notTrue}}

mstch-1.0.2/test/data/dot_notation.txt000066400000000000000000000003721265373551600200010ustar00rootroot00000000000000

A Book

Authors:

  • John Power
  • Jamie Walsh

Price: $200 USD In Stock

VAT: $40

Test truthy false values:

Zero: 0

False: false

mstch-1.0.2/test/data/double_render.hpp000066400000000000000000000002011265373551600200500ustar00rootroot00000000000000const auto double_render_data = mstch::map{ {"foo", true}, {"bar", std::string{"{{win}}"}}, {"win", std::string{"FAIL"}} };mstch-1.0.2/test/data/double_render.mustache000066400000000000000000000000301265373551600210720ustar00rootroot00000000000000{{#foo}}{{bar}}{{/foo}} mstch-1.0.2/test/data/double_render.txt000066400000000000000000000000101265373551600200760ustar00rootroot00000000000000{{win}} mstch-1.0.2/test/data/empty_list.hpp000066400000000000000000000001061265373551600174340ustar00rootroot00000000000000const auto empty_list_data = mstch::map{ {"jobs", mstch::array{}} };mstch-1.0.2/test/data/empty_list.mustache000066400000000000000000000000561265373551600204620ustar00rootroot00000000000000These are the jobs: {{#jobs}} {{.}} {{/jobs}} mstch-1.0.2/test/data/empty_list.txt000066400000000000000000000000241265373551600174630ustar00rootroot00000000000000These are the jobs: mstch-1.0.2/test/data/empty_sections.hpp000066400000000000000000000000561265373551600203140ustar00rootroot00000000000000const auto empty_sections_data = mstch::map{};mstch-1.0.2/test/data/empty_sections.mustache000066400000000000000000000000441265373551600213330ustar00rootroot00000000000000{{#foo}}{{/foo}}foo{{#bar}}{{/bar}} mstch-1.0.2/test/data/empty_sections.txt000066400000000000000000000000041265373551600203350ustar00rootroot00000000000000foo mstch-1.0.2/test/data/empty_string.hpp000066400000000000000000000002371265373551600177740ustar00rootroot00000000000000const auto empty_string_data = mstch::map{ {"description", std::string{"That is all!"}}, {"child", mstch::map{ {"description", std::string{""}} }} };mstch-1.0.2/test/data/empty_string.mustache000066400000000000000000000000631265373551600210130ustar00rootroot00000000000000{{description}}{{#child}}{{description}}{{/child}} mstch-1.0.2/test/data/empty_string.txt000066400000000000000000000000151265373551600200160ustar00rootroot00000000000000That is all! mstch-1.0.2/test/data/empty_template.hpp000066400000000000000000000000561265373551600203000ustar00rootroot00000000000000const auto empty_template_data = mstch::map{};mstch-1.0.2/test/data/empty_template.mustache000066400000000000000000000000641265373551600213210ustar00rootroot00000000000000

Test

mstch-1.0.2/test/data/empty_template.txt000066400000000000000000000000641265373551600203270ustar00rootroot00000000000000

Test

mstch-1.0.2/test/data/error_eof_in_section.hpp000066400000000000000000000001651265373551600214440ustar00rootroot00000000000000const auto error_eof_in_section_data = mstch::map{ {"hello", mstch::array{std::string{"a"}, std::string{"b"}}} };mstch-1.0.2/test/data/error_eof_in_section.mustache000066400000000000000000000000221265373551600224560ustar00rootroot00000000000000yay{{#hello}}{{.}}mstch-1.0.2/test/data/error_eof_in_section.txt000066400000000000000000000000031265373551600214630ustar00rootroot00000000000000yaymstch-1.0.2/test/data/error_eof_in_tag.hpp000066400000000000000000000001171265373551600205500ustar00rootroot00000000000000const auto error_eof_in_tag_data = mstch::map{{"hello", std::string{"world"}}};mstch-1.0.2/test/data/error_eof_in_tag.mustache000066400000000000000000000000271265373551600215720ustar00rootroot00000000000000{{hello{{hello}}{{hellomstch-1.0.2/test/data/error_eof_in_tag.txt000066400000000000000000000000071265373551600205760ustar00rootroot00000000000000{{hellomstch-1.0.2/test/data/error_not_found.hpp000066400000000000000000000000751265373551600204540ustar00rootroot00000000000000const auto error_not_found_data = mstch::map{ {"bar", 2} };mstch-1.0.2/test/data/error_not_found.mustache000066400000000000000000000000071265373551600214710ustar00rootroot00000000000000{{foo}}mstch-1.0.2/test/data/error_not_found.txt000066400000000000000000000000001265373551600204700ustar00rootroot00000000000000mstch-1.0.2/test/data/escaped.hpp000066400000000000000000000003421265373551600166510ustar00rootroot00000000000000const mstch::node escaped_data = mstch::map{ {"title", mstch::lambda{[]()->mstch::node{ return std::string{"Bear > Shark"}; }}}, {"entities", mstch::lambda{[]()->mstch::node{ return std::string{"" \"'<>/"}; }}} };mstch-1.0.2/test/data/escaped.mustache000066400000000000000000000001021265373551600176650ustar00rootroot00000000000000

{{title}}

And even {{entities}}, but not {{{entities}}}. mstch-1.0.2/test/data/escaped.txt000066400000000000000000000001361265373551600167020ustar00rootroot00000000000000

Bear > Shark

And even &quot; "'<>/, but not " "'<>/. mstch-1.0.2/test/data/falsy.hpp000066400000000000000000000002251265373551600163630ustar00rootroot00000000000000const auto falsy_data = mstch::map{ {"emptyString", std::string{""}}, {"emptyArray", mstch::array{}}, {"zero", 0}, {"null", mstch::node{}} };mstch-1.0.2/test/data/falsy.mustache000066400000000000000000000004561265373551600174130ustar00rootroot00000000000000{{#emptyString}}empty string{{/emptyString}} {{^emptyString}}inverted empty string{{/emptyString}} {{#emptyArray}}empty array{{/emptyArray}} {{^emptyArray}}inverted empty array{{/emptyArray}} {{#zero}}zero{{/zero}} {{^zero}}inverted zero{{/zero}} {{#null}}null{{/null}} {{^null}}inverted null{{/null}} mstch-1.0.2/test/data/falsy.txt000066400000000000000000000001131265373551600164070ustar00rootroot00000000000000 inverted empty string inverted empty array inverted zero inverted null mstch-1.0.2/test/data/falsy_array.hpp000066400000000000000000000004401265373551600175600ustar00rootroot00000000000000const auto falsy_array_data = mstch::map{ {"list", mstch::array{ mstch::array{std::string{""}, std::string{"emptyString"}}, mstch::array{mstch::array{}, std::string{"emptyArray"}}, mstch::array{0, std::string{"zero"}}, mstch::array{mstch::node{}, std::string{"null"}}} } };mstch-1.0.2/test/data/falsy_array.mustache000066400000000000000000000001061265373551600206010ustar00rootroot00000000000000{{#list}} {{#.}}{{#.}}{{.}}{{/.}}{{^.}}inverted {{/.}}{{/.}} {{/list}}mstch-1.0.2/test/data/falsy_array.txt000066400000000000000000000001051265373551600176060ustar00rootroot00000000000000inverted emptyString inverted emptyArray inverted zero inverted null mstch-1.0.2/test/data/grandparent_context.hpp000066400000000000000000000011731265373551600213210ustar00rootroot00000000000000const auto grandparent_context_data = mstch::map{ {"grand_parent_id", std::string{"grand_parent1"}}, {"parent_contexts", mstch::array{ mstch::map{ {"parent_id", std::string{"parent1"}}, {"child_contexts", mstch::array{ mstch::map{{"child_id", std::string{"parent1-child1"}}}, mstch::map{{"child_id", std::string{"parent1-child2"}}} }} }, mstch::map{ {"parent_id", std::string{"parent2"}}, {"child_contexts", mstch::array{ mstch::map{{"child_id", std::string{"parent2-child1"}}}, mstch::map{{"child_id", std::string{"parent2-child2"}}} }} } }} };mstch-1.0.2/test/data/grandparent_context.mustache000066400000000000000000000002671265373551600223460ustar00rootroot00000000000000{{grand_parent_id}} {{#parent_contexts}} {{grand_parent_id}} {{parent_id}} {{#child_contexts}} {{grand_parent_id}} {{parent_id}} {{child_id}} {{/child_contexts}} {{/parent_contexts}} mstch-1.0.2/test/data/grandparent_context.txt000066400000000000000000000003161265373551600213470ustar00rootroot00000000000000grand_parent1 grand_parent1 parent1 grand_parent1 parent1 parent1-child1 grand_parent1 parent1 parent1-child2 grand_parent1 parent2 grand_parent1 parent2 parent2-child1 grand_parent1 parent2 parent2-child2 mstch-1.0.2/test/data/higher_order_sections.hpp000066400000000000000000000013751265373551600216240ustar00rootroot00000000000000class higher_order_sections: public mstch::object { private: std::string m_helper; public: higher_order_sections(): m_helper("To tinker?") { register_methods(this, std::map{ {"name", &higher_order_sections::name}, {"helper", &higher_order_sections::helper}, {"bolder", &higher_order_sections::bolder} }); } mstch::node name() { return std::string{"Tater"}; } mstch::node helper() { return m_helper; } mstch::node bolder() { return mstch::lambda{[this](const std::string& text) -> mstch::node { return "" + text + " " + m_helper; }}; } }; const mstch::node higher_order_sections_data = std::make_shared();mstch-1.0.2/test/data/higher_order_sections.mustache000066400000000000000000000000431265373551600226350ustar00rootroot00000000000000{{#bolder}}Hi {{name}}.{{/bolder}} mstch-1.0.2/test/data/higher_order_sections.txt000066400000000000000000000000341265373551600216430ustar00rootroot00000000000000Hi Tater. To tinker? mstch-1.0.2/test/data/implicit_iterator.hpp000066400000000000000000000002631265373551600207720ustar00rootroot00000000000000const auto implicit_iterator_data = mstch::map{ {"data", mstch::map{ {"author", mstch::map{ {"twitter_id", 819606}, {"name", std::string{"janl"}} }} }} }; mstch-1.0.2/test/data/implicit_iterator.mustache000066400000000000000000000003061265373551600220120ustar00rootroot00000000000000{{# data.author.twitter_id }} {{/ data.author.twitter_id }} {{# data.author.name }} {{/ data.author.name }} mstch-1.0.2/test/data/implicit_iterator.txt000066400000000000000000000001321265373551600210150ustar00rootroot00000000000000 mstch-1.0.2/test/data/included_tag.hpp000066400000000000000000000001341265373551600176660ustar00rootroot00000000000000const auto included_tag_data = mstch::map{ {"html", std::string{"I like {{mustache}}"}} };mstch-1.0.2/test/data/included_tag.mustache000066400000000000000000000000341265373551600207070ustar00rootroot00000000000000You said "{{{html}}}" today mstch-1.0.2/test/data/included_tag.txt000066400000000000000000000000451265373551600177170ustar00rootroot00000000000000You said "I like {{mustache}}" today mstch-1.0.2/test/data/inverted_section.hpp000066400000000000000000000001151265373551600206070ustar00rootroot00000000000000const auto inverted_section_data = mstch::map{ {"repos", mstch::array{}} };mstch-1.0.2/test/data/inverted_section.mustache000066400000000000000000000001411265373551600216300ustar00rootroot00000000000000{{#repos}}{{name}}{{/repos}} {{^repos}}No repos :({{/repos}} {{^nothin}}Hello!{{/nothin}} mstch-1.0.2/test/data/inverted_section.txt000066400000000000000000000000241265373551600206360ustar00rootroot00000000000000 No repos :( Hello! mstch-1.0.2/test/data/keys_with_questionmarks.hpp000066400000000000000000000001701265373551600222370ustar00rootroot00000000000000const auto keys_with_questionmarks_data = mstch::map{ {"person?", mstch::map{ {"name", std::string{"Jon"}} }} };mstch-1.0.2/test/data/keys_with_questionmarks.mustache000066400000000000000000000000511265373551600232570ustar00rootroot00000000000000{{#person?}} Hi {{name}}! {{/person?}} mstch-1.0.2/test/data/keys_with_questionmarks.txt000066400000000000000000000000121265373551600222620ustar00rootroot00000000000000 Hi Jon! mstch-1.0.2/test/data/multiline_comment.hpp000066400000000000000000000000611265373551600207670ustar00rootroot00000000000000const auto multiline_comment_data = mstch::map{};mstch-1.0.2/test/data/multiline_comment.mustache000066400000000000000000000000641265373551600220140ustar00rootroot00000000000000{{! This is a multi-line comment. }} Hello world! mstch-1.0.2/test/data/multiline_comment.txt000066400000000000000000000000151265373551600210160ustar00rootroot00000000000000Hello world! mstch-1.0.2/test/data/nested_dot.hpp000066400000000000000000000001101265373551600173660ustar00rootroot00000000000000const auto nested_dot_data = mstch::map{{"name", std::string{"Bruno"}}};mstch-1.0.2/test/data/nested_dot.mustache000066400000000000000000000000351265373551600204160ustar00rootroot00000000000000{{#name}}Hello {{.}}{{/name}}mstch-1.0.2/test/data/nested_dot.txt000066400000000000000000000000131265373551600174200ustar00rootroot00000000000000Hello Brunomstch-1.0.2/test/data/nested_higher_order_sections.hpp000066400000000000000000000004061265373551600231600ustar00rootroot00000000000000const mstch::node nested_higher_order_sections_data = mstch::map{ {"bold", mstch::lambda{[](const std::string& text) -> mstch::node { return std::string{""} + text + std::string{""}; }}}, {"person", mstch::map{{"name", std::string{"Jonas"}}}} };mstch-1.0.2/test/data/nested_higher_order_sections.mustache000066400000000000000000000000751265373551600242040ustar00rootroot00000000000000{{#bold}}{{#person}}My name is {{name}}!{{/person}}{{/bold}} mstch-1.0.2/test/data/nested_higher_order_sections.txt000066400000000000000000000000311265373551600232020ustar00rootroot00000000000000My name is Jonas! mstch-1.0.2/test/data/nested_iterating.hpp000066400000000000000000000003161265373551600205760ustar00rootroot00000000000000const auto nested_iterating_data = mstch::map{ {"inner", mstch::array{mstch::map{ {"foo", std::string{"foo"}}, {"inner", mstch::array{mstch::map{ {"bar", std::string{"bar"}} }}} }}} };mstch-1.0.2/test/data/nested_iterating.mustache000066400000000000000000000000671265373551600216230ustar00rootroot00000000000000{{#inner}}{{foo}}{{#inner}}{{bar}}{{/inner}}{{/inner}} mstch-1.0.2/test/data/nested_iterating.txt000066400000000000000000000000071265373551600206230ustar00rootroot00000000000000foobar mstch-1.0.2/test/data/nesting.hpp000066400000000000000000000003131265373551600167120ustar00rootroot00000000000000const auto nesting_data = mstch::map{ {"foo", mstch::array{ mstch::map{{"a", mstch::map{{"b", 1}}}}, mstch::map{{"a", mstch::map{{"b", 2}}}}, mstch::map{{"a", mstch::map{{"b", 3}}}} }} };mstch-1.0.2/test/data/nesting.mustache000066400000000000000000000000561265373551600177400ustar00rootroot00000000000000{{#foo}} {{#a}} {{b}} {{/a}} {{/foo}} mstch-1.0.2/test/data/nesting.txt000066400000000000000000000000221265373551600167370ustar00rootroot00000000000000 1 2 3 mstch-1.0.2/test/data/nesting_same_name.hpp000066400000000000000000000002661265373551600207260ustar00rootroot00000000000000const auto nesting_same_name_data = mstch::map{ {"items", mstch::array{ mstch::map{ {"name", std::string{"name"}}, {"items", mstch::array{1, 2, 3, 4}} } }} };mstch-1.0.2/test/data/nesting_same_name.mustache000066400000000000000000000000661265373551600217460ustar00rootroot00000000000000{{#items}}{{name}}{{#items}}{{.}}{{/items}}{{/items}} mstch-1.0.2/test/data/nesting_same_name.txt000066400000000000000000000000111265373551600207420ustar00rootroot00000000000000name1234 mstch-1.0.2/test/data/null_lookup_array.hpp000066400000000000000000000004441265373551600210110ustar00rootroot00000000000000const auto null_lookup_array_data = mstch::map{ {"name", std::string{"David"}}, {"twitter", std::string{"@dasilvacontin"}}, {"farray", mstch::array{ mstch::array{std::string{"Flor"}, std::string{"@florrts"}}, mstch::array{std::string{"Miquel"}, mstch::node{}}, }} };mstch-1.0.2/test/data/null_lookup_array.mustache000066400000000000000000000001151265373551600220260ustar00rootroot00000000000000{{#farray}} {{#.}}{{#.}}{{.}} {{/.}}{{^.}}no twitter{{/.}}{{/.}} {{/farray}} mstch-1.0.2/test/data/null_lookup_array.txt000066400000000000000000000000411265373551600210320ustar00rootroot00000000000000Flor @florrts Miquel no twitter mstch-1.0.2/test/data/null_lookup_object.hpp000066400000000000000000000005311265373551600211360ustar00rootroot00000000000000const auto null_lookup_object_data = mstch::map{ {"name", std::string{"David"}}, {"twitter", std::string{"@dasilvacontin"}}, {"fobject", mstch::array{ mstch::map{ {"name", std::string{"Flor"}}, {"twitter", std::string{"@florrts"}} }, mstch::map{ {"name", std::string{"Miquel"}}, {"twitter", mstch::node{}} } }} };mstch-1.0.2/test/data/null_lookup_object.mustache000066400000000000000000000001541265373551600221610ustar00rootroot00000000000000{{#fobject}} {{name}}'s twitter: {{#twitter}}{{.}}{{/twitter}}{{^twitter}}unknown{{/twitter}}. {{/fobject}} mstch-1.0.2/test/data/null_lookup_object.txt000066400000000000000000000000651265373551600211700ustar00rootroot00000000000000Flor's twitter: @florrts. Miquel's twitter: unknown. mstch-1.0.2/test/data/null_string.hpp000066400000000000000000000002231265373551600176030ustar00rootroot00000000000000const auto null_string_data = mstch::map{ {"name", std::string{"Elise"}}, {"glytch", true}, {"binary", false}, {"value", mstch::node{}} }; mstch-1.0.2/test/data/null_string.mustache000066400000000000000000000001031265373551600206220ustar00rootroot00000000000000Hello {{name}} glytch {{glytch}} binary {{binary}} value {{value}} mstch-1.0.2/test/data/null_string.txt000066400000000000000000000000541265373551600176350ustar00rootroot00000000000000Hello Elise glytch true binary false value mstch-1.0.2/test/data/null_view.hpp000066400000000000000000000001471265373551600172540ustar00rootroot00000000000000const auto null_view_data = mstch::map{ {"name", std::string{"Joe"}}, {"friends", mstch::node{}} };mstch-1.0.2/test/data/null_view.mustache000066400000000000000000000000661265373551600202760ustar00rootroot00000000000000{{name}}'s friends: {{#friends}}{{name}}, {{/friends}}mstch-1.0.2/test/data/null_view.txt000066400000000000000000000000171265373551600173000ustar00rootroot00000000000000Joe's friends: mstch-1.0.2/test/data/partial_array.hpp000066400000000000000000000002201265373551600200720ustar00rootroot00000000000000const auto partial_array_data = mstch::map{ {"array", mstch::array{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}} };mstch-1.0.2/test/data/partial_array.mustache000066400000000000000000000000141265373551600211150ustar00rootroot00000000000000{{>partial}}mstch-1.0.2/test/data/partial_array.partial000066400000000000000000000001011265373551600207350ustar00rootroot00000000000000Here's a non-sense array of values {{#array}} {{.}} {{/array}} mstch-1.0.2/test/data/partial_array.txt000066400000000000000000000000631265373551600201270ustar00rootroot00000000000000Here's a non-sense array of values 1 2 3 4 mstch-1.0.2/test/data/partial_array_of_partials.hpp000066400000000000000000000003761265373551600224710ustar00rootroot00000000000000const auto partial_array_of_partials_data = mstch::map{ {"numbers", mstch::array{ mstch::map{{"i", std::string{"1"}}}, mstch::map{{"i", std::string{"2"}}}, mstch::map{{"i", std::string{"3"}}}, mstch::map{{"i", std::string{"4"}}} }} };mstch-1.0.2/test/data/partial_array_of_partials.mustache000066400000000000000000000000731265373551600235050ustar00rootroot00000000000000Here is some stuff! {{#numbers}} {{>partial}} {{/numbers}} mstch-1.0.2/test/data/partial_array_of_partials.partial000066400000000000000000000000061265373551600233240ustar00rootroot00000000000000{{i}} mstch-1.0.2/test/data/partial_array_of_partials.txt000066400000000000000000000000341265373551600225100ustar00rootroot00000000000000Here is some stuff! 1 2 3 4 mstch-1.0.2/test/data/partial_array_of_partials_implicit.hpp000066400000000000000000000002471265373551600243600ustar00rootroot00000000000000const auto partial_array_of_partials_implicit_data = mstch::map{ {"numbers", mstch::array{std::string{"1"}, std::string{"2"}, std::string{"3"}, std::string{"4"}}} };mstch-1.0.2/test/data/partial_array_of_partials_implicit.mustache000066400000000000000000000000731265373551600253770ustar00rootroot00000000000000Here is some stuff! {{#numbers}} {{>partial}} {{/numbers}} mstch-1.0.2/test/data/partial_array_of_partials_implicit.partial000066400000000000000000000000061265373551600252160ustar00rootroot00000000000000{{.}} mstch-1.0.2/test/data/partial_array_of_partials_implicit.txt000066400000000000000000000000341265373551600244020ustar00rootroot00000000000000Here is some stuff! 1 2 3 4 mstch-1.0.2/test/data/partial_empty.hpp000066400000000000000000000000731265373551600201200ustar00rootroot00000000000000const auto partial_empty_data = mstch::map{ {"foo", 1} };mstch-1.0.2/test/data/partial_empty.mustache000066400000000000000000000000311265373551600211340ustar00rootroot00000000000000hey {{foo}} {{>partial}} mstch-1.0.2/test/data/partial_empty.partial000066400000000000000000000000001265373551600207530ustar00rootroot00000000000000mstch-1.0.2/test/data/partial_empty.txt000066400000000000000000000000061265373551600201440ustar00rootroot00000000000000hey 1 mstch-1.0.2/test/data/partial_template.hpp000066400000000000000000000003361265373551600205770ustar00rootroot00000000000000const mstch::node partial_template_data = mstch::map{ {"title", mstch::lambda{[]()->mstch::node{ return std::string{"Welcome"}; }}}, {"again", mstch::lambda{[]()->mstch::node{ return std::string{"Goodbye"}; }}}, };mstch-1.0.2/test/data/partial_template.mustache000066400000000000000000000000401265373551600216110ustar00rootroot00000000000000

{{title}}

{{>partial}} mstch-1.0.2/test/data/partial_template.partial000066400000000000000000000000221265373551600214340ustar00rootroot00000000000000Again, {{again}}! mstch-1.0.2/test/data/partial_template.txt000066400000000000000000000000411265373551600206200ustar00rootroot00000000000000

Welcome

Again, Goodbye! mstch-1.0.2/test/data/partial_view.hpp000066400000000000000000000016101265373551600177320ustar00rootroot00000000000000class partial_view: public mstch::object { private: int m_value; public: partial_view(): m_value(10000) { register_methods(this, std::map{ {"greeting", &partial_view::greeting}, {"farewell", &partial_view::farewell}, {"name", &partial_view::name}, {"value", &partial_view::value}, {"taxed_value", &partial_view::taxed_value}, {"in_ca", &partial_view::in_ca} }); } mstch::node greeting() { return std::string{"Welcome"}; } mstch::node farewell() { return std::string{"Fair enough, right?"}; } mstch::node name() { return std::string{"Chris"}; } mstch::node value() { return m_value; } mstch::node taxed_value() { return m_value - (m_value * 0.4); } mstch::node in_ca() { return true; } }; const auto partial_view_data = std::make_shared();mstch-1.0.2/test/data/partial_view.mustache000066400000000000000000000000711265373551600207540ustar00rootroot00000000000000

{{greeting}}

{{>partial}}

{{farewell}}

mstch-1.0.2/test/data/partial_view.partial000066400000000000000000000001511265373551600205760ustar00rootroot00000000000000Hello {{name}} You have just won ${{value}}! {{#in_ca}} Well, ${{ taxed_value }}, after taxes. {{/in_ca}}mstch-1.0.2/test/data/partial_view.txt000066400000000000000000000001561265373551600177660ustar00rootroot00000000000000

Welcome

Hello Chris You have just won $10000! Well, $6000, after taxes.

Fair enough, right?

mstch-1.0.2/test/data/partial_whitespace.hpp000066400000000000000000000017311265373551600211200ustar00rootroot00000000000000class partial_whitespace: public mstch::object { private: int m_value; public: partial_whitespace(): m_value(10000) { register_methods(this, std::map{ {"greeting", &partial_whitespace::greeting}, {"farewell", &partial_whitespace::farewell}, {"name", &partial_whitespace::name}, {"value", &partial_whitespace::value}, {"taxed_value", &partial_whitespace::taxed_value}, {"in_ca", &partial_whitespace::in_ca} }); } mstch::node greeting() { return std::string{"Welcome"}; } mstch::node farewell() { return std::string{"Fair enough, right?"}; } mstch::node name() { return std::string{"Chris"}; } mstch::node value() { return m_value; } mstch::node taxed_value() { return static_cast(m_value - (m_value * 0.4)); } mstch::node in_ca() { return true; } }; const auto partial_whitespace_data = std::make_shared();mstch-1.0.2/test/data/partial_whitespace.mustache000066400000000000000000000001011265373551600221300ustar00rootroot00000000000000

{{ greeting }}

{{> partial }}

{{ farewell }}

mstch-1.0.2/test/data/partial_whitespace.partial000066400000000000000000000001611265373551600217610ustar00rootroot00000000000000Hello {{ name}} You have just won ${{value }}! {{# in_ca }} Well, ${{ taxed_value }}, after taxes. {{/ in_ca }}mstch-1.0.2/test/data/partial_whitespace.txt000066400000000000000000000001561265373551600211500ustar00rootroot00000000000000

Welcome

Hello Chris You have just won $10000! Well, $6000, after taxes.

Fair enough, right?

mstch-1.0.2/test/data/recursion_with_same_names.hpp000066400000000000000000000004271265373551600225050ustar00rootroot00000000000000const auto recursion_with_same_names_data = mstch::map{ {"name", std::string{"name"}}, {"description", std::string{"desc"}}, {"terms", mstch::array{ mstch::map{{"name", std::string{"t1"}}, {"index", 0}}, mstch::map{{"name", std::string{"t2"}}, {"index", 1}} }} };mstch-1.0.2/test/data/recursion_with_same_names.mustache000066400000000000000000000001131265373551600235170ustar00rootroot00000000000000{{ name }} {{ description }} {{#terms}} {{name}} {{index}} {{/terms}} mstch-1.0.2/test/data/recursion_with_same_names.txt000066400000000000000000000000351265373551600225300ustar00rootroot00000000000000name desc t1 0 t2 1 mstch-1.0.2/test/data/reuse_of_enumerables.hpp000066400000000000000000000003111265373551600214320ustar00rootroot00000000000000const auto reuse_of_enumerables_data = mstch::map{ {"terms", mstch::array{ mstch::map{{"name", std::string{"t1"}}, {"index", 0}}, mstch::map{{"name", std::string{"t2"}}, {"index", 1}} }} };mstch-1.0.2/test/data/reuse_of_enumerables.mustache000066400000000000000000000001321265373551600224550ustar00rootroot00000000000000{{#terms}} {{name}} {{index}} {{/terms}} {{#terms}} {{name}} {{index}} {{/terms}} mstch-1.0.2/test/data/reuse_of_enumerables.txt000066400000000000000000000000441265373551600214650ustar00rootroot00000000000000 t1 0 t2 1 t1 0 t2 1 mstch-1.0.2/test/data/section_as_context.hpp000066400000000000000000000005321265373551600211410ustar00rootroot00000000000000const auto section_as_context_data = mstch::map{ {"a_object", mstch::map{ {"title", std::string{"this is an object"}}, {"description", std::string{"one of its attributes is a list"}}, {"a_list", mstch::array{ mstch::map{{"label", std::string{"listitem1"}}}, mstch::map{{"label", std::string{"listitem2"}}} }} }} };mstch-1.0.2/test/data/section_as_context.mustache000066400000000000000000000002201265373551600221550ustar00rootroot00000000000000{{#a_object}}

{{title}}

{{description}}

    {{#a_list}}
  • {{label}}
  • {{/a_list}}
{{/a_object}} mstch-1.0.2/test/data/section_as_context.txt000066400000000000000000000002031265373551600211640ustar00rootroot00000000000000

this is an object

one of its attributes is a list

  • listitem1
  • listitem2
mstch-1.0.2/test/data/section_functions_in_partials.hpp000066400000000000000000000003151265373551600233660ustar00rootroot00000000000000const mstch::node section_functions_in_partials_data = mstch::map{ {"bold", mstch::lambda{[](const std::string& text) -> mstch::node { return std::string{""} + text + std::string{""}; }}} };mstch-1.0.2/test/data/section_functions_in_partials.mustache000066400000000000000000000000451265373551600244100ustar00rootroot00000000000000{{> partial}}

some more text

mstch-1.0.2/test/data/section_functions_in_partials.partial000066400000000000000000000000361265373551600242330ustar00rootroot00000000000000{{#bold}}Hello There{{/bold}} mstch-1.0.2/test/data/section_functions_in_partials.txt000066400000000000000000000000521265373551600234140ustar00rootroot00000000000000Hello There

some more text

mstch-1.0.2/test/data/simple.hpp000066400000000000000000000011461265373551600165410ustar00rootroot00000000000000class simple: public mstch::object { private: int m_value; public: simple(): m_value(10000) { register_methods(this, std::map{ {"name", &simple::name}, {"value", &simple::value}, {"taxed_value", &simple::taxed_value}, {"in_ca", &simple::in_ca}}); } mstch::node name() { return std::string{"Chris"}; } mstch::node value() { return m_value; } mstch::node taxed_value() { return m_value - (m_value * 0.4); } mstch::node in_ca() { return true; } }; const auto simple_data = std::make_shared();mstch-1.0.2/test/data/simple.mustache000066400000000000000000000001521265373551600175570ustar00rootroot00000000000000Hello {{name}} You have just won ${{value}}! {{#in_ca}} Well, ${{ taxed_value }}, after taxes. {{/in_ca}} mstch-1.0.2/test/data/simple.txt000066400000000000000000000001001265373551600165560ustar00rootroot00000000000000Hello Chris You have just won $10000! Well, $6000, after taxes. mstch-1.0.2/test/data/string_as_context.hpp000066400000000000000000000002441265373551600210030ustar00rootroot00000000000000const auto string_as_context_data = mstch::map{ {"a_string", std::string{"aa"}}, {"a_list", mstch::array{std::string{"a"},std::string{"b"},std::string{"c"}}} };mstch-1.0.2/test/data/string_as_context.mustache000066400000000000000000000001001265373551600220140ustar00rootroot00000000000000
    {{#a_list}}
  • {{a_string}}/{{.}}
  • {{/a_list}}
mstch-1.0.2/test/data/string_as_context.txt000066400000000000000000000000721265373551600210320ustar00rootroot00000000000000
  • aa/a
  • aa/b
  • aa/c
mstch-1.0.2/test/data/two_in_a_row.hpp000066400000000000000000000001641265373551600177350ustar00rootroot00000000000000const auto two_in_a_row_data = mstch::map{ {"name", std::string{"Joe"}}, {"greeting", std::string{"Welcome"}} };mstch-1.0.2/test/data/two_in_a_row.mustache000066400000000000000000000000301265373551600207470ustar00rootroot00000000000000{{greeting}}, {{name}}! mstch-1.0.2/test/data/two_in_a_row.txt000066400000000000000000000000161265373551600177610ustar00rootroot00000000000000Welcome, Joe! mstch-1.0.2/test/data/two_sections.hpp000066400000000000000000000000541265373551600177650ustar00rootroot00000000000000const auto two_sections_data = mstch::map{};mstch-1.0.2/test/data/two_sections.mustache000066400000000000000000000000441265373551600210060ustar00rootroot00000000000000{{#foo}} {{/foo}} {{#bar}} {{/bar}} mstch-1.0.2/test/data/two_sections.txt000066400000000000000000000000001265373551600200040ustar00rootroot00000000000000mstch-1.0.2/test/data/unescaped.hpp000066400000000000000000000002101265373551600172060ustar00rootroot00000000000000const mstch::node unescaped_data = mstch::map{ {"title", mstch::lambda{[]()->mstch::node{ return std::string{"Bear > Shark"}; }}} };mstch-1.0.2/test/data/unescaped.mustache000066400000000000000000000000251265373551600202340ustar00rootroot00000000000000

{{{title}}}

mstch-1.0.2/test/data/unescaped.txt000066400000000000000000000000261265373551600172430ustar00rootroot00000000000000

Bear > Shark

mstch-1.0.2/test/data/whitespace.hpp000066400000000000000000000001561265373551600174040ustar00rootroot00000000000000const auto whitespace_data = mstch::map{ {"tag1", std::string{"Hello"}}, {"tag2", std::string{"World"}} };mstch-1.0.2/test/data/whitespace.mustache000066400000000000000000000000251265373551600204210ustar00rootroot00000000000000{{tag1}} {{tag2}}. mstch-1.0.2/test/data/whitespace.txt000066400000000000000000000000171265373551600174300ustar00rootroot00000000000000Hello World. mstch-1.0.2/test/data/zero_view.hpp000066400000000000000000000001101265373551600172470ustar00rootroot00000000000000const auto zero_view_data = mstch::map{{"nums", mstch::array{0, 1, 2}}};mstch-1.0.2/test/data/zero_view.mustache000066400000000000000000000000301265373551600202720ustar00rootroot00000000000000{{#nums}}{{.}},{{/nums}}mstch-1.0.2/test/data/zero_view.txt000066400000000000000000000000061265373551600173030ustar00rootroot000000000000000,1,2,mstch-1.0.2/test/specs_lambdas.hpp000066400000000000000000000026201265373551600171350ustar00rootroot00000000000000std::map specs_lambdas { {"Interpolation", mstch::lambda{[](const std::string&) -> mstch::node { return std::string{"world"}; }}}, {"Interpolation - Expansion", mstch::lambda{[](const std::string&) -> mstch::node { return std::string{"{{planet}}"}; }}}, {"Interpolation - Alternate Delimiters", mstch::lambda{[](const std::string&) -> mstch::node { return std::string{"|planet| => {{planet}}"}; }}}, {"Interpolation - Multiple Calls", mstch::lambda{[](const std::string&) -> mstch::node { static int calls = 0; return ++calls; }}}, {"Escaping", mstch::lambda{[](const std::string&) -> mstch::node { return std::string{">"}; }}}, {"Section", mstch::lambda{[](const std::string& txt) -> mstch::node { return std::string{(txt == "{{x}}") ? "yes" : "no"}; }}}, {"Section - Expansion", mstch::lambda{[](const std::string& txt) -> mstch::node { return txt + std::string{"{{planet}}"} + txt; }}}, {"Section - Alternate Delimiters", mstch::lambda{[](const std::string& txt) -> mstch::node { return txt + std::string{"{{planet}} => |planet|"} + txt; }}}, {"Section - Multiple Calls", mstch::lambda{[](const std::string& txt) -> mstch::node { return "__" + txt + "__"; }}}, {"Inverted Section", mstch::lambda{[](const std::string&) -> mstch::node { return false; }}} };mstch-1.0.2/test/test_context.hpp000066400000000000000000000040641265373551600170640ustar00rootroot00000000000000#include "data/simple.hpp" #include "data/empty_string.hpp" #include "data/multiline_comment.hpp" #include "data/included_tag.hpp" #include "data/string_as_context.hpp" #include "data/falsy_array.hpp" #include "data/nested_dot.hpp" #include "data/escaped.hpp" #include "data/partial_view.hpp" #include "data/nested_higher_order_sections.hpp" #include "data/zero_view.hpp" #include "data/disappearing_whitespace.hpp" #include "data/ampersand_escape.hpp" #include "data/falsy.hpp" #include "data/reuse_of_enumerables.hpp" #include "data/apostrophe.hpp" #include "data/grandparent_context.hpp" #include "data/higher_order_sections.hpp" #include "data/empty_list.hpp" #include "data/two_in_a_row.hpp" #include "data/partial_array_of_partials.hpp" #include "data/keys_with_questionmarks.hpp" #include "data/error_not_found.hpp" #include "data/complex.hpp" #include "data/double_render.hpp" #include "data/null_lookup_object.hpp" #include "data/error_eof_in_tag.hpp" #include "data/delimiters.hpp" #include "data/null_view.hpp" #include "data/null_string.hpp" #include "data/comments.hpp" #include "data/null_lookup_array.hpp" #include "data/section_as_context.hpp" #include "data/unescaped.hpp" #include "data/dot_notation.hpp" #include "data/recursion_with_same_names.hpp" #include "data/two_sections.hpp" #include "data/partial_array_of_partials_implicit.hpp" #include "data/changing_delimiters.hpp" #include "data/nesting_same_name.hpp" #include "data/partial_empty.hpp" #include "data/inverted_section.hpp" #include "data/nested_iterating.hpp" #include "data/partial_template.hpp" #include "data/nesting.hpp" #include "data/bug_11_eating_whitespace.hpp" #include "data/implicit_iterator.hpp" #include "data/whitespace.hpp" #include "data/array_of_strings.hpp" #include "data/empty_sections.hpp" #include "data/context_lookup.hpp" #include "data/section_functions_in_partials.hpp" #include "data/partial_whitespace.hpp" #include "data/backslashes.hpp" #include "data/error_eof_in_section.hpp" #include "data/empty_template.hpp" #include "data/partial_array.hpp" #include "data/bug_length_property.hpp" mstch-1.0.2/test/test_main.cpp000066400000000000000000000107641265373551600163230ustar00rootroot00000000000000#define CATCH_CONFIG_MAIN #include "catch.hpp" #include "rapidjson/document.h" #include "mstch/mstch.hpp" #include "test_context.hpp" #include "test_data.hpp" #include "specs_data.hpp" #include "specs_lambdas.hpp" using namespace mstchtest; mstch::node to_value(const rapidjson::Value& val) { if (val.IsString()) return std::string{val.GetString()}; if (val.IsBool()) return val.GetBool(); if (val.IsDouble()) return val.GetDouble(); if (val.IsInt()) return val.GetInt(); return mstch::node{}; } mstch::array to_array(const rapidjson::Value& val); mstch::map to_object(const rapidjson::Value& val) { mstch::map ret; for (auto i = val.MemberBegin(); i != val.MemberEnd(); ++i) { if (i->value.IsArray()) ret.insert(std::make_pair(i->name.GetString(), to_array(i->value))); else if (i->value.IsObject()) ret.insert(std::make_pair(i->name.GetString(), to_object(i->value))); else ret.insert(std::make_pair(i->name.GetString(), to_value(i->value))); } return ret; } mstch::array to_array(const rapidjson::Value& val) { mstch::array ret; for (auto i = val.Begin(); i != val.End(); ++i) { if (i->IsArray()) ret.push_back(to_array(*i)); else if (i->IsObject()) ret.push_back(to_object(*i)); else ret.push_back(to_value(*i)); } return ret; } mstch::node parse_with_rapidjson(const std::string& str) { rapidjson::Document doc; doc.Parse(str.c_str()); return to_object(doc); } #define MSTCH_PARTIAL_TEST(x) TEST_CASE(#x) { \ REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data, {{"partial", x ## _partial}})); \ } #define MSTCH_TEST(x) TEST_CASE(#x) { \ REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data)); \ } #define SPECS_TEST(x) TEST_CASE("specs_" #x) { \ using boost::get; \ auto data = parse_with_rapidjson(x ## _json); \ for (auto& test_item: get(get(data)["tests"])) {\ auto test = get(test_item); \ std::map partials; \ if (test.count("partials")) \ for (auto& partial_item: get(test["partials"])) \ partials.insert(std::make_pair(partial_item.first, get(partial_item.second))); \ mstch::map context; \ for (auto& data_item: get(test["data"])) \ if (data_item.first == "lambda") \ context.insert(std::make_pair(data_item.first, specs_lambdas[get(test["name"])])); \ else \ context.insert(data_item); \ SECTION(get(test["name"])) \ REQUIRE(mstch::render( \ get(test["template"]), \ context, partials) == \ get(test["expected"])); \ } \ } MSTCH_TEST(ampersand_escape) MSTCH_TEST(apostrophe) MSTCH_TEST(array_of_strings) MSTCH_TEST(backslashes) MSTCH_TEST(bug_11_eating_whitespace) MSTCH_TEST(bug_length_property) MSTCH_TEST(changing_delimiters) MSTCH_TEST(comments) MSTCH_TEST(complex) MSTCH_TEST(context_lookup) MSTCH_TEST(delimiters) MSTCH_TEST(disappearing_whitespace) MSTCH_TEST(dot_notation) MSTCH_TEST(double_render) MSTCH_TEST(empty_list) MSTCH_TEST(empty_sections) MSTCH_TEST(empty_string) MSTCH_TEST(empty_template) MSTCH_TEST(error_eof_in_section) MSTCH_TEST(error_eof_in_tag) MSTCH_TEST(error_not_found) MSTCH_TEST(escaped) MSTCH_TEST(falsy) MSTCH_TEST(falsy_array) MSTCH_TEST(grandparent_context) MSTCH_TEST(higher_order_sections) MSTCH_TEST(implicit_iterator) MSTCH_TEST(included_tag) 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) MSTCH_TEST(null_lookup_array) MSTCH_TEST(null_lookup_object) MSTCH_TEST(null_string) MSTCH_TEST(null_view) 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_PARTIAL_TEST(partial_view) MSTCH_PARTIAL_TEST(partial_whitespace) 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(simple) 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) SPECS_TEST(comments) SPECS_TEST(delimiters) SPECS_TEST(interpolation) SPECS_TEST(inverted) SPECS_TEST(partials) SPECS_TEST(sections) SPECS_TEST(lambdas) mstch-1.0.2/vendor/000077500000000000000000000000001265373551600141425ustar00rootroot00000000000000mstch-1.0.2/vendor/Catch/000077500000000000000000000000001265373551600151645ustar00rootroot00000000000000mstch-1.0.2/vendor/benchmark/000077500000000000000000000000001265373551600160745ustar00rootroot00000000000000mstch-1.0.2/vendor/headerize/000077500000000000000000000000001265373551600161025ustar00rootroot00000000000000mstch-1.0.2/vendor/rapidjson/000077500000000000000000000000001265373551600161335ustar00rootroot00000000000000mstch-1.0.2/vendor/spec/000077500000000000000000000000001265373551600150745ustar00rootroot00000000000000