Overview

Description

Boost.Mustache is an implementation of Mustache templates in C++11.

Mustache is a simple templating language in which tags of the form {{something}} are replaced with the value of the entity something, which typically means with the member "something" of the JSON object passed when rendering the template.

Boost.Mustache can take a Boost.JSON object as the context against which data references are resolved, but it can also take arbitrary values that can be converted to boost::json::value by using boost::json::value_from. This allows, for instance, described classes (structs and classes annotated with Boost.Describe) to be passed as the data context, such that references to e.g. {{title}} in the template are resolved to the corresponding title member of the class.

Boost.Mustache implements the mandatory portions of the Mustache specification. At the moment it doesn’t implement any of the extensions.

Supported Compilers

  • GCC 5 or later with -std=c++11 or above

  • Clang 3.9 or later with -std=c++11 or above

  • Visual Studio 2015 or later

Tested on Github Actions and Appveyor.

Usage Examples

Generating a markdown document from a C++ struct

#include <boost/mustache.hpp>
#include <boost/describe.hpp>
#include <vector>
#include <string>
#include <iostream>

struct item
{
    std::string title;
    std::string author;
    std::string link;
};

BOOST_DESCRIBE_STRUCT(item, (), (title, author, link))

struct reference
{
    std::string heading;
    std::vector<item> items;
};

BOOST_DESCRIBE_STRUCT(reference, (), (heading, items))

int main()
{
    reference ref =
    {
        "Reference",
        {
            {
                "Better Bit Mixing - Improving on MurmurHash3's 64-bit Finalizer",
                "David Stafford",
                "https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html"
            },
            {
                "Stronger, better, morer, Moremur; a better Murmur3-type mixer",
                "Pelle Evensen",
                "https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html"
            },
            {
                "Improved mx3 and the RRC test",
                "Jon Maiga",
                "http://jonkagstrom.com/mx3/mx3_rev2.html"
            }
        }
    };

    std::string tmpl =
R"(# {{{heading}}}

{{#items}}
* __{{{title}}}__
_{{{author}}}_
[{{{link}}}]({{{link}}})

{{/items}})";

    boost::mustache::render( tmpl, std::cout, ref, {} );
}

Output:

# Reference

* __Better Bit Mixing - Improving on MurmurHash3's 64-bit Finalizer__
_David Stafford_
[https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html](https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)

* __Stronger, better, morer, Moremur; a better Murmur3-type mixer__
_Pelle Evensen_
[https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html](https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html)

* __Improved mx3 and the RRC test__
_Jon Maiga_
[http://jonkagstrom.com/mx3/mx3_rev2.html](http://jonkagstrom.com/mx3/mx3_rev2.html)

Generating an HTML document from a C++ struct

#include <boost/mustache.hpp>
#include <boost/describe.hpp>
#include <vector>
#include <string>
#include <iostream>

// C++ data

struct item
{
    std::string title;
    std::string author;
    std::string link;
};

BOOST_DESCRIBE_STRUCT(item, (), (title, author, link))

struct reference
{
    std::string heading;
    std::vector<item> items;
};

BOOST_DESCRIBE_STRUCT(reference, (), (heading, items))

// Templates

constexpr char header[] =

R"(<html>
<head>
  <title>{{heading}}</title>
</head>
<body>
)";

constexpr char footer[] =

R"(</body>
</html>
)";

constexpr char item[] =

R"(<li>
  <strong>{{title}}</strong><br>
  <em>{{author}}</em><br>
  <a href="{{link}}">{{link}}</a>
</li>
)";

constexpr char body[] =

R"(<h1>{{heading}}</h1>
<ul>
{{#items}}
  {{>item}}
{{/items}}
</ul>
)";

constexpr char html[] =

R"({{>header}}
  {{>body}}
{{>footer}}
)";

//

int main()
{
    reference ref =
    {
        "Reference",
        {
            {
                "Better Bit Mixing - Improving on MurmurHash3's 64-bit Finalizer",
                "David Stafford",
                "https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html"
            },
            {
                "Stronger, better, morer, Moremur; a better Murmur3-type mixer",
                "Pelle Evensen",
                "https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html"
            },
            {
                "Improved mx3 and the RRC test",
                "Jon Maiga",
                "http://jonkagstrom.com/mx3/mx3_rev2.html"
            }
        }
    };

    boost::mustache::render( html, std::cout, ref,
        { { "header", header }, { "footer", footer }, { "item", item }, { "body", body } } );
}

Output:

<html>
<head>
  <title>Reference</title>
</head>
<body>
  <h1>Reference</h1>
  <ul>
    <li>
      <strong>Better Bit Mixing - Improving on MurmurHash3's 64-bit Finalizer</strong><br>
      <em>David Stafford</em><br>
      <a href="https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html">https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html</a>
    </li>
    <li>
      <strong>Stronger, better, morer, Moremur; a better Murmur3-type mixer</strong><br>
      <em>Pelle Evensen</em><br>
      <a href="https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html">https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html</a>
    </li>
    <li>
      <strong>Improved mx3 and the RRC test</strong><br>
      <em>Jon Maiga</em><br>
      <a href="http://jonkagstrom.com/mx3/mx3_rev2.html">http://jonkagstrom.com/mx3/mx3_rev2.html</a>
    </li>
  </ul>
</body>
</html>

Reference

<boost/mustache/output_ref.hpp>

Synopsis

namespace boost {
namespace mustache {

class output_ref
{
public:

    // only enabled when St is string-like
    template<class St> output_ref( St& st );

    // only enabled when Os is an output stream
    template<class Os> output_ref( Os& os );

    void write( boost::core::string_view sv );
};

} // namespace mustache
} // namespace boost

Constructors

// only enabled when St is string-like
template<class St> output_ref( St& st );
Effects:

Constructs an output_ref for which calling write(sv) performs st.append(sv.data(), sv.data() + sv.size()).

Remarks:

This constructor is only enabled when typename St::value_type exists and is char.

// only enabled when Os is an output stream
template<class Os> output_ref( Os& os );
Effects:

Constructs an output_ref for which calling write(sv) performs os.write(sv.data(), sv.size()).

Remarks:

This constructor is only enabled when Os* is convertible to std::ostream*.

write

void write( boost::core::string_view sv );
Effects:

Outputs the characters in sv in the manner determined by the constructor.

<boost/mustache/renderer.hpp>

Synopsis

namespace boost {
namespace mustache {

class renderer
{
public:

    template<class T1, class T2>
    explicit renderer( T1 const& data, T2 const& partials, boost::json::storage_ptr sp = {} );

    void render_some( boost::core::string_view in, output_ref out );
    void finish( output_ref out );
};

} // namespace mustache
} // namespace boost

Constructor

template<class T1, class T2>
explicit renderer( T1 const& data, T2 const& partials, boost::json::storage_ptr sp = {} );
Effects:
  • Converts data to boost::json::value by boost::json::value_from(data, sp) and stores it at the top of the context stack.

  • Converts partials to boost::json::object by boost::json::value_from(partials, sp).as_object() and stores it.

  • Stores sp and does all subsequent allocations through it.

render_some

void render_some( boost::core::string_view in, output_ref out );
Effects:

Consumes the next part of the input template from in and outputs the portion rendered so far by calling out.write. Uses the stored data to resolve data references and the stored partials to resolve references to partials.

finish

void finish( output_ref out );
Effects:

Should be called once at end of input. Outputs the remaining portion of the rendered output by calling out.write.

<boost/mustache/render.hpp>

Synopsis

namespace boost {
namespace mustache {

template<class T1 = boost::json::value, class T2 = boost::json::object>
void render( boost::core::string_view tmpl, output_ref out, T1 const& data,
    T2 const& partials, boost::json::storage_ptr sp = {} );

} // namespace mustache
} // namespace boost

render

template<class T1 = boost::json::value, class T2 = boost::json::object>
void render( boost::core::string_view tmpl, output_ref out, T1 const& data,
    T2 const& partials, boost::json::storage_ptr sp = {} );
Effects:
  • Constructs a renderer as if by renderer rd(data, partials, sp);

  • Invokes rd.render_some(tmpl, out).

  • Invokes rd.finish(tmpl, out).

<boost/mustache.hpp>

This convenience header includes all the headers previously mentioned.

This documentation is copyright 2022 Peter Dimov and is distributed under the Boost Software License, Version 1.0.