compliance with specs v1.1.3
This commit is contained in:
parent
f81c594c3b
commit
0f1a7056c1
15 changed files with 114 additions and 88 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
mstch is a complete implementation of [{{mustache}}](http://mustache.github.io/)
|
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)
|
templates using modern C++. It's compliant with [specifications](https://github.com/mustache/spec)
|
||||||
v1.1.2, including the lambda module.
|
v1.1.3, including the lambda module.
|
||||||
|
|
||||||
[![GitHub version](https://badge.fury.io/gh/no1msd%2Fmstch.svg)](http://badge.fury.io/gh/no1msd%2Fmstch)
|
[![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://travis-ci.org/no1msd/mstch.svg?branch=master)](https://travis-ci.org/no1msd/mstch)
|
||||||
|
|
|
@ -7,29 +7,29 @@ using namespace mstch;
|
||||||
const mstch::node render_context::null_node;
|
const mstch::node render_context::null_node;
|
||||||
|
|
||||||
render_context::push::push(render_context& context, const mstch::node& node):
|
render_context::push::push(render_context& context, const mstch::node& node):
|
||||||
context(context)
|
m_context(context)
|
||||||
{
|
{
|
||||||
context.nodes.emplace_front(node);
|
context.m_nodes.emplace_front(node);
|
||||||
context.node_ptrs.emplace_front(&node);
|
context.m_node_ptrs.emplace_front(&node);
|
||||||
context.state.push(std::unique_ptr<render_state>(new outside_section));
|
context.m_state.push(std::unique_ptr<render_state>(new outside_section));
|
||||||
}
|
}
|
||||||
|
|
||||||
render_context::push::~push() {
|
render_context::push::~push() {
|
||||||
context.nodes.pop_front();
|
m_context.m_nodes.pop_front();
|
||||||
context.node_ptrs.pop_front();
|
m_context.m_node_ptrs.pop_front();
|
||||||
context.state.pop();
|
m_context.m_state.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string render_context::push::render(const template_type& templt) {
|
std::string render_context::push::render(const template_type& templt) {
|
||||||
return context.render(templt);
|
return m_context.render(templt);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_context::render_context(
|
render_context::render_context(
|
||||||
const mstch::node& node,
|
const mstch::node& node,
|
||||||
const std::map<std::string, template_type>& partials):
|
const std::map<std::string, template_type>& partials):
|
||||||
partials(partials), nodes(1, node), node_ptrs(1, &node)
|
m_partials(partials), m_nodes(1, node), m_node_ptrs(1, &node)
|
||||||
{
|
{
|
||||||
state.push(std::unique_ptr<render_state>(new outside_section));
|
m_state.push(std::unique_ptr<render_state>(new outside_section));
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstch::node& render_context::find_node(
|
const mstch::node& render_context::find_node(
|
||||||
|
@ -47,7 +47,7 @@ const mstch::node& render_context::find_node(
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstch::node& render_context::get_node(const std::string& token) {
|
const mstch::node& render_context::get_node(const std::string& token) {
|
||||||
return find_node(token, node_ptrs);
|
return find_node(token, m_node_ptrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string render_context::render(
|
std::string render_context::render(
|
||||||
|
@ -57,8 +57,8 @@ std::string render_context::render(
|
||||||
bool prev_eol = true;
|
bool prev_eol = true;
|
||||||
for (auto& token: templt) {
|
for (auto& token: templt) {
|
||||||
if (prev_eol && prefix.length() != 0)
|
if (prev_eol && prefix.length() != 0)
|
||||||
output += state.top()->render(*this, {prefix});
|
output += m_state.top()->render(*this, {prefix});
|
||||||
output += state.top()->render(*this, token);
|
output += m_state.top()->render(*this, token);
|
||||||
prev_eol = token.eol();
|
prev_eol = token.eol();
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
@ -67,6 +67,6 @@ std::string render_context::render(
|
||||||
std::string render_context::render_partial(
|
std::string render_context::render_partial(
|
||||||
const std::string& partial_name, const std::string& prefix)
|
const std::string& partial_name, const std::string& prefix)
|
||||||
{
|
{
|
||||||
return partials.count(partial_name) ?
|
return m_partials.count(partial_name) ?
|
||||||
render(partials.at(partial_name), prefix) : "";
|
render(m_partials.at(partial_name), prefix) : "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class render_context {
|
||||||
~push();
|
~push();
|
||||||
std::string render(const template_type& templt);
|
std::string render(const template_type& templt);
|
||||||
private:
|
private:
|
||||||
render_context& context;
|
render_context& m_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
render_context(
|
render_context(
|
||||||
|
@ -33,7 +33,7 @@ class render_context {
|
||||||
const std::string& partial_name, const std::string& prefix);
|
const std::string& partial_name, const std::string& prefix);
|
||||||
template<class T, class... Args>
|
template<class T, class... Args>
|
||||||
void set_state(Args&& ... args) {
|
void set_state(Args&& ... args) {
|
||||||
state.top() = std::unique_ptr<render_state>(
|
m_state.top() = std::unique_ptr<render_state>(
|
||||||
new T(std::forward<Args>(args)...));
|
new T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ class render_context {
|
||||||
const mstch::node& find_node(
|
const mstch::node& find_node(
|
||||||
const std::string& token,
|
const std::string& token,
|
||||||
std::list<node const*> current_nodes);
|
std::list<node const*> current_nodes);
|
||||||
std::map<std::string, template_type> partials;
|
std::map<std::string, template_type> m_partials;
|
||||||
std::deque<mstch::node> nodes;
|
std::deque<mstch::node> m_nodes;
|
||||||
std::list<const mstch::node*> node_ptrs;
|
std::list<const mstch::node*> m_node_ptrs;
|
||||||
std::stack<std::unique_ptr<render_state>> state;
|
std::stack<std::unique_ptr<render_state>> m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,30 +5,30 @@
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
in_section::in_section(type type, const std::string& section_name):
|
in_section::in_section(type type, const token& start_token):
|
||||||
m_type(type), section_name(section_name), skipped_openings(0)
|
m_type(type), m_start_token(start_token), m_skipped_openings(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string in_section::render(render_context& ctx, const token& token) {
|
std::string in_section::render(render_context& ctx, const token& token) {
|
||||||
if (token.token_type() == token::type::section_close)
|
if (token.token_type() == token::type::section_close)
|
||||||
if (token.name() == section_name && skipped_openings == 0) {
|
if (token.name() == m_start_token.name() && m_skipped_openings == 0) {
|
||||||
auto& node = ctx.get_node(section_name);
|
auto& node = ctx.get_node(m_start_token.name());
|
||||||
std::string out;
|
std::string out;
|
||||||
|
|
||||||
if (m_type == type::normal && !visit(is_node_empty(), node))
|
if (m_type == type::normal && !visit(is_node_empty(), node))
|
||||||
out = visit(render_section(ctx, section), node);
|
out = visit(render_section(ctx, m_section, m_start_token.delims()), node);
|
||||||
else if (m_type == type::inverted && visit(is_node_empty(), node))
|
else if (m_type == type::inverted && visit(is_node_empty(), node))
|
||||||
out = render_context::push(ctx).render(section);
|
out = render_context::push(ctx).render(m_section);
|
||||||
|
|
||||||
ctx.set_state<outside_section>();
|
ctx.set_state<outside_section>();
|
||||||
return out;
|
return out;
|
||||||
} else
|
} else
|
||||||
skipped_openings--;
|
m_skipped_openings--;
|
||||||
else if (token.token_type() == token::type::inverted_section_open ||
|
else if (token.token_type() == token::type::inverted_section_open ||
|
||||||
token.token_type() == token::type::section_open)
|
token.token_type() == token::type::section_open)
|
||||||
skipped_openings++;
|
m_skipped_openings++;
|
||||||
|
|
||||||
section << token;
|
m_section << token;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ namespace mstch {
|
||||||
class in_section: public render_state {
|
class in_section: public render_state {
|
||||||
public:
|
public:
|
||||||
enum class type { inverted, normal };
|
enum class type { inverted, normal };
|
||||||
in_section(type type, const std::string §ion_name);
|
in_section(type type, const token& start_token);
|
||||||
std::string render(render_context &context, const token &token) override;
|
std::string render(render_context& context, const token& token) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const type m_type;
|
const type m_type;
|
||||||
const std::string section_name;
|
const token& m_start_token;
|
||||||
template_type section;
|
template_type m_section;
|
||||||
int skipped_openings;
|
int m_skipped_openings;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ std::string outside_section::render(
|
||||||
using flag = render_node::flag;
|
using flag = render_node::flag;
|
||||||
switch (token.token_type()) {
|
switch (token.token_type()) {
|
||||||
case token::type::section_open:
|
case token::type::section_open:
|
||||||
ctx.set_state<in_section>(in_section::type::normal, token.name());
|
ctx.set_state<in_section>(in_section::type::normal, token);
|
||||||
break;
|
break;
|
||||||
case token::type::inverted_section_open:
|
case token::type::inverted_section_open:
|
||||||
ctx.set_state<in_section>(in_section::type::inverted, token.name());
|
ctx.set_state<in_section>(in_section::type::inverted, token);
|
||||||
break;
|
break;
|
||||||
case token::type::variable:
|
case token::type::variable:
|
||||||
return visit(render_node(ctx, flag::escape_html), ctx.get_node(token.name()));
|
return visit(render_node(ctx, flag::escape_html), ctx.get_node(token.name()));
|
||||||
|
|
|
@ -2,7 +2,16 @@
|
||||||
|
|
||||||
using namespace mstch;
|
using namespace mstch;
|
||||||
|
|
||||||
template_type::template_type(const std::string& str) {
|
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);
|
tokenize(str);
|
||||||
strip_whitespace();
|
strip_whitespace();
|
||||||
}
|
}
|
||||||
|
@ -13,45 +22,44 @@ void template_type::process_text(citer begin, citer end) {
|
||||||
auto start = begin;
|
auto start = begin;
|
||||||
for (auto it = begin; it != end; ++it)
|
for (auto it = begin; it != end; ++it)
|
||||||
if (*it == '\n' || it == end - 1) {
|
if (*it == '\n' || it == end - 1) {
|
||||||
tokens.push_back({{start, it + 1}});
|
m_tokens.push_back({{start, it + 1}});
|
||||||
start = it + 1;
|
start = it + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_type::tokenize(const std::string& tmp) {
|
void template_type::tokenize(const std::string& tmp) {
|
||||||
std::string open{"{{"}, close{"}}"};
|
|
||||||
citer beg = tmp.begin();
|
citer beg = tmp.begin();
|
||||||
auto npos = std::string::npos;
|
auto npos = std::string::npos;
|
||||||
|
|
||||||
for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
|
for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
|
||||||
auto open_pos = tmp.find(open, cur_pos);
|
auto open_pos = tmp.find(m_open, cur_pos);
|
||||||
auto close_pos = tmp.find(
|
auto close_pos = tmp.find(
|
||||||
close, open_pos == npos ? open_pos : open_pos + 1);
|
m_close, open_pos == npos ? open_pos : open_pos + 1);
|
||||||
|
|
||||||
if (close_pos != npos && open_pos != npos) {
|
if (close_pos != npos && open_pos != npos) {
|
||||||
if (*(beg + open_pos + open.size()) == '{' &&
|
if (*(beg + open_pos + m_open.size()) == '{' &&
|
||||||
*(beg + close_pos + close.size()) == '}')
|
*(beg + close_pos + m_close.size()) == '}')
|
||||||
++close_pos;
|
++close_pos;
|
||||||
|
|
||||||
process_text(beg + cur_pos, beg + open_pos);
|
process_text(beg + cur_pos, beg + open_pos);
|
||||||
cur_pos = close_pos + close.size();
|
cur_pos = close_pos + m_close.size();
|
||||||
tokens.push_back({{beg + open_pos, beg + close_pos + close.size()},
|
m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()},
|
||||||
open.size(), close.size()});
|
m_open.size(), m_close.size()});
|
||||||
|
|
||||||
if(cur_pos == tmp.size()) {
|
if (cur_pos == tmp.size()) {
|
||||||
tokens.push_back({{""}});
|
m_tokens.push_back({{""}});
|
||||||
tokens.back().eol(true);
|
m_tokens.back().eol(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*(beg + open_pos + open.size()) == '=' &&
|
if (*(beg + open_pos + m_open.size()) == '=' &&
|
||||||
*(beg + close_pos - 1) == '=')
|
*(beg + close_pos - 1) == '=')
|
||||||
{
|
{
|
||||||
auto tok_beg = beg + open_pos + open.size() + 1;
|
auto tok_beg = beg + open_pos + m_open.size() + 1;
|
||||||
auto tok_end = beg + close_pos - 1;
|
auto tok_end = beg + close_pos - 1;
|
||||||
auto front_skip = first_not_ws(tok_beg, tok_end);
|
auto front_skip = first_not_ws(tok_beg, tok_end);
|
||||||
auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
|
auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
|
||||||
open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
|
m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
|
||||||
close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
|
m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
process_text(beg + cur_pos, tmp.end());
|
process_text(beg + cur_pos, tmp.end());
|
||||||
|
@ -61,10 +69,10 @@ void template_type::tokenize(const std::string& tmp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void template_type::strip_whitespace() {
|
void template_type::strip_whitespace() {
|
||||||
auto line_begin = tokens.begin();
|
auto line_begin = m_tokens.begin();
|
||||||
bool has_tag = false, non_space = false;
|
bool has_tag = false, non_space = false;
|
||||||
|
|
||||||
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
|
for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) {
|
||||||
auto type = (*it).token_type();
|
auto type = (*it).token_type();
|
||||||
if (type != token::type::text && type != token::type::variable &&
|
if (type != token::type::text && type != token::type::variable &&
|
||||||
type != token::type::unescaped_variable)
|
type != token::type::unescaped_variable)
|
||||||
|
@ -77,7 +85,7 @@ void template_type::strip_whitespace() {
|
||||||
store_prefixes(line_begin);
|
store_prefixes(line_begin);
|
||||||
|
|
||||||
auto c = line_begin;
|
auto c = line_begin;
|
||||||
for (bool end = false; !end; (*c).ws_only() ? c = tokens.erase(c) : ++c)
|
for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c)
|
||||||
if ((end = (*c).eol()))
|
if ((end = (*c).eol()))
|
||||||
it = c - 1;
|
it = c - 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,15 @@ class template_type {
|
||||||
public:
|
public:
|
||||||
template_type() = default;
|
template_type() = default;
|
||||||
template_type(const std::string& str);
|
template_type(const std::string& str);
|
||||||
std::vector<token>::const_iterator begin() const { return tokens.begin(); }
|
template_type(const std::string& str, const delim_type& delims);
|
||||||
std::vector<token>::const_iterator end() const { return tokens.end(); }
|
std::vector<token>::const_iterator begin() const { return m_tokens.begin(); }
|
||||||
void operator<<(const token& token) { tokens.push_back(token); }
|
std::vector<token>::const_iterator end() const { return m_tokens.end(); }
|
||||||
|
void operator<<(const token& token) { m_tokens.push_back(token); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<token> tokens;
|
std::vector<token> m_tokens;
|
||||||
|
std::string m_open;
|
||||||
|
std::string m_close;
|
||||||
void strip_whitespace();
|
void strip_whitespace();
|
||||||
void process_text(citer beg, citer end);
|
void process_text(citer beg, citer end);
|
||||||
void tokenize(const std::string& tmp);
|
void tokenize(const std::string& tmp);
|
||||||
|
|
|
@ -31,6 +31,8 @@ token::token(const std::string& str, std::size_t left, std::size_t right):
|
||||||
if (m_type != type::variable)
|
if (m_type != type::variable)
|
||||||
c = first_not_ws(c + 1, str.end() - right);
|
c = first_not_ws(c + 1, str.end() - right);
|
||||||
m_name = {c, first_not_ws(str.rbegin() + right, str.rend() - left) + 1};
|
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 {
|
} else {
|
||||||
m_type = type::text;
|
m_type = type::text;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace mstch {
|
namespace mstch {
|
||||||
|
|
||||||
|
using delim_type = std::pair<std::string, std::string>;
|
||||||
|
|
||||||
class token {
|
class token {
|
||||||
public:
|
public:
|
||||||
enum class type {
|
enum class type {
|
||||||
|
@ -15,6 +17,7 @@ class token {
|
||||||
const std::string& raw() const { return m_raw; };
|
const std::string& raw() const { return m_raw; };
|
||||||
const std::string& name() const { return m_name; };
|
const std::string& name() const { return m_name; };
|
||||||
const std::string& partial_prefix() const { return m_partial_prefix; };
|
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) {
|
void partial_prefix(const std::string& p_partial_prefix) {
|
||||||
m_partial_prefix = p_partial_prefix;
|
m_partial_prefix = p_partial_prefix;
|
||||||
};
|
};
|
||||||
|
@ -27,6 +30,7 @@ class token {
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::string m_raw;
|
std::string m_raw;
|
||||||
std::string m_partial_prefix;
|
std::string m_partial_prefix;
|
||||||
|
delim_type m_delims;
|
||||||
bool m_eol;
|
bool m_eol;
|
||||||
bool m_ws_only;
|
bool m_ws_only;
|
||||||
type token_info(char c);
|
type token_info(char c);
|
||||||
|
|
|
@ -10,26 +10,26 @@ namespace mstch {
|
||||||
class get_token: public boost::static_visitor<const mstch::node&> {
|
class get_token: public boost::static_visitor<const mstch::node&> {
|
||||||
public:
|
public:
|
||||||
get_token(const std::string& token, const mstch::node& node):
|
get_token(const std::string& token, const mstch::node& node):
|
||||||
token(token), node(node)
|
m_token(token), m_node(node)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
const mstch::node& operator()(const T&) const {
|
const mstch::node& operator()(const T&) const {
|
||||||
return node;
|
return m_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstch::node& operator()(const map& map) const {
|
const mstch::node& operator()(const map& map) const {
|
||||||
return map.at(token);
|
return map.at(m_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mstch::node& operator()(const std::shared_ptr<object>& object) const {
|
const mstch::node& operator()(const std::shared_ptr<object>& object) const {
|
||||||
return object->at(token);
|
return object->at(m_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string& token;
|
const std::string& m_token;
|
||||||
const mstch::node& node;
|
const mstch::node& m_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,24 +8,24 @@ namespace mstch {
|
||||||
|
|
||||||
class has_token: public boost::static_visitor<bool> {
|
class has_token: public boost::static_visitor<bool> {
|
||||||
public:
|
public:
|
||||||
has_token(const std::string& token): token(token) {
|
has_token(const std::string& token): m_token(token) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
bool operator()(const T&) const {
|
bool operator()(const T&) const {
|
||||||
return token == ".";
|
return m_token == ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const map& map) const {
|
bool operator()(const map& map) const {
|
||||||
return map.count(token) == 1;
|
return map.count(m_token) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const std::shared_ptr<object>& object) const {
|
bool operator()(const std::shared_ptr<object>& object) const {
|
||||||
return object->has(token);
|
return object->has(m_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string& token;
|
const std::string& m_token;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ class render_node: public boost::static_visitor<std::string> {
|
||||||
public:
|
public:
|
||||||
enum class flag { none, escape_html };
|
enum class flag { none, escape_html };
|
||||||
render_node(render_context& ctx, flag p_flag = flag::none):
|
render_node(render_context& ctx, flag p_flag = flag::none):
|
||||||
ctx(ctx), m_flag(p_flag)
|
m_ctx(ctx), m_flag(p_flag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,9 @@ class render_node: public boost::static_visitor<std::string> {
|
||||||
|
|
||||||
std::string operator()(const lambda& value) const {
|
std::string operator()(const lambda& value) const {
|
||||||
template_type interpreted{value([this](const mstch::node& n) {
|
template_type interpreted{value([this](const mstch::node& n) {
|
||||||
return visit(render_node(ctx), n);
|
return visit(render_node(m_ctx), n);
|
||||||
})};
|
})};
|
||||||
auto rendered = render_context::push(ctx).render(interpreted);
|
auto rendered = render_context::push(m_ctx).render(interpreted);
|
||||||
return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered;
|
return (m_flag == flag::escape_html) ? html_escape(rendered) : rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class render_node: public boost::static_visitor<std::string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
render_context& ctx;
|
render_context& m_ctx;
|
||||||
flag m_flag;
|
flag m_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,39 +15,42 @@ class render_section: public boost::static_visitor<std::string> {
|
||||||
render_section(
|
render_section(
|
||||||
render_context& ctx,
|
render_context& ctx,
|
||||||
const template_type& section,
|
const template_type& section,
|
||||||
|
const delim_type& delims,
|
||||||
flag p_flag = flag::none):
|
flag p_flag = flag::none):
|
||||||
ctx(ctx), section(section), m_flag(p_flag)
|
m_ctx(ctx), m_section(section), m_delims(delims), m_flag(p_flag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::string operator()(const T& t) const {
|
std::string operator()(const T& t) const {
|
||||||
return render_context::push(ctx, t).render(section);
|
return render_context::push(m_ctx, t).render(m_section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator()(const lambda& fun) const {
|
std::string operator()(const lambda& fun) const {
|
||||||
std::string section_str;
|
std::string section_str;
|
||||||
for(auto& token: section)
|
for (auto& token: m_section)
|
||||||
section_str += token.raw();
|
section_str += token.raw();
|
||||||
template_type interpreted{fun([this](const mstch::node& n) {
|
template_type interpreted{fun([this](const mstch::node& n) {
|
||||||
return visit(render_node(ctx), n);
|
return visit(render_node(m_ctx), n);
|
||||||
}, section_str)};
|
}, section_str), m_delims};
|
||||||
return render_context::push(ctx).render(interpreted);
|
return render_context::push(m_ctx).render(interpreted);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator()(const array& array) const {
|
std::string operator()(const array& array) const {
|
||||||
std::string out;
|
std::string out;
|
||||||
if(m_flag == flag::keep_array)
|
if (m_flag == flag::keep_array)
|
||||||
return render_context::push(ctx, array).render(section);
|
return render_context::push(m_ctx, array).render(m_section);
|
||||||
else
|
else
|
||||||
for (auto& item: array)
|
for (auto& item: array)
|
||||||
out += visit(render_section(ctx, section, flag::keep_array), item);
|
out += visit(render_section(
|
||||||
|
m_ctx, m_section, m_delims, flag::keep_array), item);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
render_context& ctx;
|
render_context& m_ctx;
|
||||||
const template_type& section;
|
const template_type& m_section;
|
||||||
|
const delim_type& m_delims;
|
||||||
flag m_flag;
|
flag m_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ std::map<std::string,mstch::node> specs_lambdas {
|
||||||
{"Interpolation - Expansion", mstch::lambda{[](const std::string&) -> mstch::node {
|
{"Interpolation - Expansion", mstch::lambda{[](const std::string&) -> mstch::node {
|
||||||
return std::string{"{{planet}}"};
|
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 {
|
{"Interpolation - Multiple Calls", mstch::lambda{[](const std::string&) -> mstch::node {
|
||||||
static int calls = 0; return ++calls;
|
static int calls = 0; return ++calls;
|
||||||
}}},
|
}}},
|
||||||
|
@ -17,6 +20,9 @@ std::map<std::string,mstch::node> specs_lambdas {
|
||||||
{"Section - Expansion", mstch::lambda{[](const std::string& txt) -> mstch::node {
|
{"Section - Expansion", mstch::lambda{[](const std::string& txt) -> mstch::node {
|
||||||
return txt + std::string{"{{planet}}"} + txt;
|
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 {
|
{"Section - Multiple Calls", mstch::lambda{[](const std::string& txt) -> mstch::node {
|
||||||
return "__" + txt + "__";
|
return "__" + txt + "__";
|
||||||
}}},
|
}}},
|
||||||
|
|
Loading…
Reference in a new issue