2015-04-23 23:35:29 +00:00
|
|
|
# mstch - {{mustache}} templates in C++11
|
|
|
|
|
2015-04-27 09:08:10 +00:00
|
|
|
![mstch logo](http://i.imgur.com/MRyStO5.png)
|
2015-04-24 10:16:03 +00:00
|
|
|
|
2015-04-24 12:47:12 +00:00
|
|
|
mstch is a complete implementation of [{{mustache}}](http://mustache.github.io/)
|
2015-05-04 12:43:20 +00:00
|
|
|
templates using modern C++. It's compliant with [specifications](https://github.com/mustache/spec)
|
2015-05-04 14:14:32 +00:00
|
|
|
v1.1.2, including the lambda module.
|
2015-04-23 23:48:42 +00:00
|
|
|
|
2015-05-05 14:25:59 +00:00
|
|
|
It works great with [json.hpp](https://github.com/no1msd/json.hpp).
|
|
|
|
|
2015-05-09 07:43:50 +00:00
|
|
|
[![GitHub version](https://badge.fury.io/gh/no1msd%2Fmstch.svg)](http://badge.fury.io/gh/no1msd%2Fmstch)
|
2015-04-23 23:35:29 +00:00
|
|
|
[![Build Status](https://travis-ci.org/no1msd/mstch.svg?branch=master)](https://travis-ci.org/no1msd/mstch)
|
|
|
|
|
2015-04-24 10:25:24 +00: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 12:43:20 +00:00
|
|
|
- JSON-like data structure using [Boost.Variant](http://www.boost.org/libs/variant)
|
2015-04-24 10:25:24 +00:00
|
|
|
- variables, sections, inverted sections
|
|
|
|
- partials
|
|
|
|
- changing the delimiter
|
|
|
|
- C++11 lambdas
|
|
|
|
- C++ objects as view models
|
|
|
|
|
2015-04-23 23:35:29 +00: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-23 23:37:09 +00:00
|
|
|
mstch::map{{"name", std::string{"Chris"}}},
|
|
|
|
mstch::map{{"name", std::string{"Mark"}}},
|
|
|
|
mstch::map{{"name", std::string{"Scott"}}},
|
|
|
|
}}
|
2015-04-23 23:35:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
std::cout << mstch::render(view, context) << std::endl;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
The output of this example will be:
|
|
|
|
|
2015-04-24 13:51:41 +00:00
|
|
|
```html
|
2015-04-23 23:48:42 +00:00
|
|
|
Hi Chris!
|
|
|
|
Hi Mark!
|
|
|
|
Hi Scott!
|
2015-04-23 23:35:29 +00:00
|
|
|
```
|
|
|
|
|
2015-04-24 12:47:12 +00: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 09:38:41 +00: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 12:47:12 +00: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 13:51:41 +00: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 12:47:12 +00:00
|
|
|
if your compiler supports it.
|
|
|
|
|
|
|
|
## Advanced usage
|
|
|
|
|
|
|
|
### Partials
|
|
|
|
|
2015-04-24 13:20:49 +00: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 14:20:30 +00:00
|
|
|
Output:
|
2015-04-24 13:20:49 +00:00
|
|
|
|
2015-04-24 13:51:41 +00:00
|
|
|
```html
|
2015-04-24 13:20:49 +00:00
|
|
|
<strong>Chris</strong>
|
|
|
|
<strong>Mark</strong>
|
|
|
|
<strong>Scott</strong>
|
|
|
|
```
|
2015-04-24 12:47:12 +00:00
|
|
|
|
|
|
|
### Lambdas
|
|
|
|
|
2015-04-24 13:51:41 +00: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 12:15:47 +00: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 13:51:41 +00:00
|
|
|
|
2015-05-05 12:15:47 +00:00
|
|
|
The lambda expression accepts either no parameters:
|
2015-04-24 13:51:41 +00:00
|
|
|
|
|
|
|
```c++
|
|
|
|
std::string view{"Hello {{lambda}}!"};
|
|
|
|
mstch::map context{
|
2015-05-05 12:15:47 +00:00
|
|
|
{"lambda", mstch::lambda{[]() -> mstch::node {
|
2015-04-24 13:51:41 +00:00
|
|
|
return std::string{"World"};
|
|
|
|
}}}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::cout << mstch::render(view, context) << std::endl;
|
|
|
|
```
|
|
|
|
|
2015-04-24 14:20:30 +00:00
|
|
|
Output:
|
2015-04-24 13:51:41 +00:00
|
|
|
|
|
|
|
```html
|
|
|
|
Hello World!
|
|
|
|
```
|
|
|
|
|
2015-05-05 12:15:47 +00:00
|
|
|
Or it accepts a `const std::string&` that gets the unrendered literal block:
|
2015-04-24 13:51:41 +00:00
|
|
|
|
|
|
|
```c++
|
|
|
|
std::string view{"{{#bold}}{{yay}} :){{/bold}}"};
|
|
|
|
mstch::map context{
|
|
|
|
{"yay", std::string{"Yay!"}},
|
2015-05-05 12:15:47 +00:00
|
|
|
{"bold", mstch::lambda{[](const std::string& text) -> mstch::node {
|
2015-05-04 14:14:32 +00:00
|
|
|
return "<b>" + text + "</b>";
|
2015-04-24 13:51:41 +00:00
|
|
|
}}}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::cout << mstch::render(view, context) << std::endl;
|
|
|
|
```
|
|
|
|
|
2015-04-24 14:20:30 +00:00
|
|
|
Output:
|
2015-04-24 13:51:41 +00:00
|
|
|
|
|
|
|
```html
|
|
|
|
<b>Yay! :)</b>
|
|
|
|
```
|
2015-04-24 12:47:12 +00:00
|
|
|
|
|
|
|
### Objects
|
|
|
|
|
2015-04-24 14:20:30 +00: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 14:22:07 +00:00
|
|
|
return mstch::array{
|
|
|
|
std::string{"Chris"}, std::string{"Mark"}, std::string{"Scott"}};
|
2015-04-24 14:20:30 +00: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 12:47:12 +00:00
|
|
|
|
2015-04-23 23:35:29 +00:00
|
|
|
## Requirements
|
|
|
|
|
2015-04-26 16:35:30 +00:00
|
|
|
- A C++ compiler with decent C++11 support. Currently tested with:
|
|
|
|
- GCC 4.7, 4.8, 4.9
|
2015-04-27 11:59:52 +00:00
|
|
|
- clang 3.4.2, 3.5
|
2015-05-04 12:43:20 +00:00
|
|
|
- Boost 1.54+ for [Boost.Variant](http://www.boost.org/libs/variant)
|
2015-04-24 12:47:12 +00:00
|
|
|
- CMake 2.8+ for building
|
2015-04-23 23:35:29 +00:00
|
|
|
|
2015-04-23 23:48:42 +00:00
|
|
|
## Installing
|
2015-04-23 23:35:29 +00:00
|
|
|
|
|
|
|
From the root of the source tree:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ mkdir build
|
|
|
|
$ cd build
|
|
|
|
$ cmake ..
|
|
|
|
$ make
|
2015-04-23 23:48:42 +00:00
|
|
|
$ make install
|
2015-04-23 23:35:29 +00:00
|
|
|
```
|
|
|
|
|
2015-04-24 12:47:12 +00:00
|
|
|
## Running the unit tests
|
|
|
|
|
|
|
|
Unit tests are using the [Catch](https://github.com/philsquared/Catch) framework,
|
2015-05-05 15:17:11 +00:00
|
|
|
included in the repository. [Boost.Program_Options](http://www.boost.org/libs/program_options),
|
2015-05-04 12:43:20 +00:00
|
|
|
[Boost.Spirit](http://www.boost.org/libs/spirit), and [The Boost Algorithm Library](http://www.boost.org/libs/algorithm)
|
2015-04-24 12:47:12 +00:00
|
|
|
are also required to build them.
|
2015-04-23 23:35:29 +00:00
|
|
|
|
2015-05-05 07:07:20 +00:00
|
|
|
Don't forget to initialize submodules:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ git submodule init
|
|
|
|
$ git submodule update
|
|
|
|
```
|
|
|
|
|
|
|
|
To build and run the unit tests:
|
|
|
|
|
2015-04-23 23:35:29 +00:00
|
|
|
```bash
|
|
|
|
$ mkdir build
|
|
|
|
$ cd build
|
|
|
|
$ cmake -DWITH_UNIT_TESTS=ON ..
|
|
|
|
$ make
|
|
|
|
$ make test
|
|
|
|
```
|
2015-04-27 14:45:59 +00:00
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
mstch is licensed under the [MIT license](https://github.com/no1msd/mstch/blob/master/LICENSE).
|