mstch/README.md

281 lines
7.3 KiB
Markdown
Raw Normal View History

2015-04-24 07:35:29 +08:00
# mstch - {{mustache}} templates in C++11
2015-04-27 17:08:10 +08:00
![mstch logo](http://i.imgur.com/MRyStO5.png)
2015-04-24 18:16:03 +08:00
2015-04-24 20:47:12 +08:00
mstch is a complete implementation of [{{mustache}}](http://mustache.github.io/)
2015-05-04 20:43:20 +08:00
templates using modern C++. It's compliant with [specifications](https://github.com/mustache/spec)
2015-10-18 22:08:41 +08:00
v1.1.3, including the lambda module.
2015-04-24 07:48:42 +08:00
2015-05-09 15:43:50 +08:00
[![GitHub version](https://badge.fury.io/gh/no1msd%2Fmstch.svg)](http://badge.fury.io/gh/no1msd%2Fmstch)
2015-04-24 07:35:29 +08:00
[![Build Status](https://travis-ci.org/no1msd/mstch.svg?branch=master)](https://travis-ci.org/no1msd/mstch)
2015-10-02 03:48:25 +08:00
[![Build status](https://ci.appveyor.com/api/projects/status/d6mxp0uba5646x16?svg=true)](https://ci.appveyor.com/project/no1msd/mstch)
2015-04-24 07:35:29 +08:00
2015-04-24 18:25:24 +08:00
## Supported features
mstch supports the complete feature set described in the `mustache(5)` [manpage](http://mustache.github.com/mustache.5.html):
2015-05-04 20:43:20 +08:00
- JSON-like data structure using [Boost.Variant](http://www.boost.org/libs/variant)
2015-04-24 18:25:24 +08:00
- variables, sections, inverted sections
- partials
- changing the delimiter
- C++11 lambdas
- C++ objects as view models
2015-04-24 07:35:29 +08:00
## Basic usage
```c++
#include <iostream>
#include <mstch/mstch.hpp>
int main() {
std::string view{"{{#names}}Hi {{name}}!\n{{/names}}"};
mstch::map context{
{"names", mstch::array{
2015-04-24 07:37:09 +08:00
mstch::map{{"name", std::string{"Chris"}}},
mstch::map{{"name", std::string{"Mark"}}},
mstch::map{{"name", std::string{"Scott"}}},
}}
2015-04-24 07:35:29 +08:00
};
std::cout << mstch::render(view, context) << std::endl;
return 0;
}
```
The output of this example will be:
2015-04-24 21:51:41 +08:00
```html
2015-04-24 07:48:42 +08:00
Hi Chris!
Hi Mark!
Hi Scott!
2015-04-24 07:35:29 +08:00
```
2015-04-24 20:47:12 +08:00
### Data structure
The types in the example above, `mstch::array` and `mstch::map` are actually
aliases for standard types:
```c++
using map = std::map<const std::string, node>;
using array = std::vector<node>;
```
2015-05-09 17:38:41 +08:00
`mstch::node` is a `boost::variant` that can hold a `std::string`, `int`,
`double`, `bool`, `mstch::lambda` or a `std::shared_ptr<mstch::object>`
2015-04-24 20:47:12 +08:00
(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
2015-04-24 21:51:41 +08:00
converted to `bool`. Alternatively you can use [C++14 string_literals](http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s)
2015-04-24 20:47:12 +08:00
if your compiler supports it.
## Advanced usage
### Partials
2015-04-24 21:20:49 +08:00
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{"<strong>{{name}}\n</strong>"};
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;
```
2015-04-24 22:20:30 +08:00
Output:
2015-04-24 21:20:49 +08:00
2015-04-24 21:51:41 +08:00
```html
2015-04-24 21:20:49 +08:00
<strong>Chris</strong>
<strong>Mark</strong>
<strong>Scott</strong>
```
2015-04-24 20:47:12 +08:00
### Lambdas
2015-04-24 21:51:41 +08:00
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
2015-05-05 20:15:47 +08:00
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.
2015-04-24 21:51:41 +08:00
2015-05-05 20:15:47 +08:00
The lambda expression accepts either no parameters:
2015-04-24 21:51:41 +08:00
```c++
std::string view{"Hello {{lambda}}!"};
mstch::map context{
2015-05-05 20:15:47 +08:00
{"lambda", mstch::lambda{[]() -> mstch::node {
2015-04-24 21:51:41 +08:00
return std::string{"World"};
}}}
};
std::cout << mstch::render(view, context) << std::endl;
```
2015-04-24 22:20:30 +08:00
Output:
2015-04-24 21:51:41 +08:00
```html
Hello World!
```
2015-05-05 20:15:47 +08:00
Or it accepts a `const std::string&` that gets the unrendered literal block:
2015-04-24 21:51:41 +08:00
```c++
std::string view{"{{#bold}}{{yay}} :){{/bold}}"};
mstch::map context{
{"yay", std::string{"Yay!"}},
2015-05-05 20:15:47 +08:00
{"bold", mstch::lambda{[](const std::string& text) -> mstch::node {
2015-05-04 22:14:32 +08:00
return "<b>" + text + "</b>";
2015-04-24 21:51:41 +08:00
}}}
};
std::cout << mstch::render(view, context) << std::endl;
```
2015-04-24 22:20:30 +08:00
Output:
2015-04-24 21:51:41 +08:00
```html
<b>Yay! :)</b>
```
2015-04-24 20:47:12 +08:00
### Objects
2015-04-24 22:20:30 +08:00
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() {
2015-04-24 22:22:07 +08:00
return mstch::array{
std::string{"Chris"}, std::string{"Mark"}, std::string{"Scott"}};
2015-04-24 22:20:30 +08:00
}
private:
int m_value;
};
std::string view{"{{#names}}<b>{{count}}</b>: {{.}}\n{{/names}}"};
const auto context = std::make_shared<example>();
std::cout << mstch::render(view, context) << std::endl;
```
Output:
```html
<b>1</b>: Chris
<b>2</b>: Mark
<b>3</b>: Scott
```
2015-04-24 20:47:12 +08:00
2016-02-02 04:08:46 +08:00
### 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<std::string(const std::string&)>`.
For example you can turn off escaping entirely with a lambda:
```c++
mstch::config::escape = [](const std::string& str) -> std::string {
return str;
};
```
2015-04-24 07:35:29 +08:00
## Requirements
2015-04-27 00:35:30 +08:00
- A C++ compiler with decent C++11 support. Currently tested with:
2015-10-18 06:24:51 +08:00
- GCC 4.7, 4.8, 4.9, 5.1
- clang 3.5, 3.6, 3.7 (both libstdc++ and libc++ are supported)
2015-10-02 06:23:15 +08:00
- MSVC 2013, 2015
2015-05-04 20:43:20 +08:00
- Boost 1.54+ for [Boost.Variant](http://www.boost.org/libs/variant)
2015-09-30 22:34:36 +08:00
- CMake 3.0+ for building
2015-04-24 07:35:29 +08:00
2015-10-16 02:22:19 +08:00
## Using mstch in your project
2015-04-24 07:35:29 +08:00
2015-10-16 02:22:19 +08:00
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
2015-10-18 06:18:01 +08:00
its include path, and add a static library target named `mstch`. For example:
2015-10-16 02:22:19 +08:00
```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:
2015-04-24 07:35:29 +08:00
```bash
$ mkdir build
$ cd build
$ cmake ..
$ make
2015-04-24 07:48:42 +08:00
$ make install
2015-04-24 07:35:29 +08:00
```
2015-10-16 02:22:19 +08:00
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)
```
2015-04-24 20:47:12 +08:00
## Running the unit tests
2015-10-16 23:26:23 +08:00
Unit tests are using the [Catch](https://github.com/philsquared/Catch) framework
and [rapidjson](http://rapidjson.org/) to parse the
2015-10-18 06:18:01 +08:00
[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.
2015-04-24 07:35:29 +08:00
2015-05-05 15:07:20 +08:00
Don't forget to initialize submodules:
```bash
$ git submodule init
$ git submodule update
```
To build and run the unit tests:
2015-04-24 07:35:29 +08:00
```bash
$ mkdir build
$ cd build
$ cmake -DWITH_UNIT_TESTS=ON ..
$ make
$ make test
```
2015-04-27 22:45:59 +08:00
## License
mstch is licensed under the [MIT license](https://github.com/no1msd/mstch/blob/master/LICENSE).