2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25#ifndef INCLUDE_INJA_INJA_HPP_
26#define INCLUDE_INJA_INJA_HPP_
29#ifndef INCLUDE_INJA_JSON_HPP_
30#define INCLUDE_INJA_JSON_HPP_
32#include <nlohmann/json.hpp>
45#ifndef INCLUDE_INJA_THROW_HPP_
46#define INCLUDE_INJA_THROW_HPP_
48#if (defined(__cpp_exceptions
) || defined(__EXCEPTIONS
) || defined(_CPPUNWIND)) && !defined(INJA_NOEXCEPTION)
50#define INJA_THROW(exception) throw exception
55#define INJA_THROW(exception)
57 std::ignore = exception
59#ifndef INJA_NOEXCEPTION
60#define INJA_NOEXCEPTION
67#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
68#define INCLUDE_INJA_ENVIRONMENT_HPP_
79#ifndef INCLUDE_INJA_CONFIG_HPP_
80#define INCLUDE_INJA_CONFIG_HPP_
87#ifndef INCLUDE_INJA_TEMPLATE_HPP_
88#define INCLUDE_INJA_TEMPLATE_HPP_
95#ifndef INCLUDE_INJA_NODE_HPP_
96#define INCLUDE_INJA_NODE_HPP_
101#include <string_view>
106#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
107#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
112#include <string_view>
125
126
237 auto it =
function_storage.find(std::make_pair(
static_cast<std::string>(name), num_args));
242 }
else if (num_args > 0) {
258#ifndef INCLUDE_INJA_UTILS_HPP_
259#define INCLUDE_INJA_UTILS_HPP_
264#include <string_view>
268#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
269#define INCLUDE_INJA_EXCEPTIONS_HPP_
288 explicit InjaError(
const std::string& type,
const std::string& message)
289 : std::runtime_error(
"[inja.exception." + type +
"] " + message)
296 : std::runtime_error(
"[inja.exception." + type +
"] (at " + std::to_string(location
.line) +
":" +
297 std::to_string(location
.column) +
") " + message)
338 inline std::string_view
slice(std::string_view view, size_t start, size_t end) {
339 start = std::min(start, view.size());
340 end = std::min(std::max(start, end), view.size());
341 return view.substr(start, end - start);
344 inline std::pair<std::string_view, std::string_view>
split(std::string_view view,
char Separator) {
345 const size_t idx = view.find(Separator);
346 if (idx == std::string_view::npos) {
347 return std::make_pair(view, std::string_view());
349 return std::make_pair(
slice(view
, 0
, idx
),
slice(view
, idx + 1
, std::string_view::npos
));
352 inline bool starts_with(std::string_view view, std::string_view prefix) {
353 return (view.size() >= prefix.size() && view.compare(0, prefix.size(), prefix) == 0);
360 const std::size_t last_newline = sliced.rfind(
'\n');
362 if (last_newline == std::string_view::npos) {
363 return {1, sliced.length() + 1};
367 size_t count_lines = 0;
368 size_t search_start = 0;
369 while (search_start <= sliced.size()) {
370 search_start = sliced.find(
'\n', search_start) + 1;
371 if (search_start == 0) {
377 return {count_lines + 1, sliced.length() - last_newline};
384 for (
auto pos = s.find(f);
385 pos != std::string::npos;
386 s.replace(pos, f.size(), t),
387 pos = s.find(f, pos + t.size()))
441
442
516 std::string_view part;
518 result.push_back(
'/');
519 result.append(part.begin(), part.end());
520 }
while (!ptr_name.empty());
524 explicit DataNode(std::string_view ptr_name, size_t pos)
824#ifndef INCLUDE_INJA_STATISTICS_HPP_
825#define INCLUDE_INJA_STATISTICS_HPP_
832
833
836 for (
const auto& n : node
.nodes) {
910
911
920 :
content(std::move(content)) {
940
941
992
993
1001
1002
1015#ifndef INCLUDE_INJA_PARSER_HPP_
1016#define INCLUDE_INJA_PARSER_HPP_
1019#include <filesystem>
1025#include <string_view>
1036#ifndef INCLUDE_INJA_LEXER_HPP_
1037#define INCLUDE_INJA_LEXER_HPP_
1041#include <string_view>
1048#ifndef INCLUDE_INJA_TOKEN_HPP_
1049#define INCLUDE_INJA_TOKEN_HPP_
1052#include <string_view>
1057
1058
1117 return static_cast<std::string>(
text);
1131
1132
1164 scan_body(std::string_view close,
Token::
Kind closeKind, std::string_view close_trim = std::string_view(),
bool trim =
false) {
1171 if (ch ==
' ' || ch ==
'\t' || ch ==
'\r') {
1202 if (std::isalpha(ch)) {
1305 if (!std::isalnum(ch) && ch !=
'.' && ch !=
'/' && ch !=
'_' && ch !=
'-') {
1320 if (!(std::isdigit(ch) || ch ==
'.' || ch ==
'e' || ch ==
'E' ||
1371 }
else if (ch ==
'\r') {
1381 std::string_view result = text;
1382 while (!result.empty()) {
1383 const char ch = result.back();
1384 if (ch ==
' ' || ch ==
'\t') {
1385 result.remove_suffix(1);
1386 }
else if (ch ==
'\n' || ch ==
'\r') {
1434 if (open_start == std::string_view::npos) {
1442 const std::string_view open_str =
m_in.substr(
pos);
1443 bool must_lstrip =
false;
1536 if (end == std::string_view::npos) {
1577
1578
1625 const std::string_view data_text(begin,
static_cast<std::size_t>(end - begin));
1626 arguments.emplace_back(std::make_shared<
LiteralNode>(data_text, data_text.data() - content_ptr));
1630 auto function = operator_stack.top();
1631 operator_stack.pop();
1633 if (
static_cast<
int>(arguments.size()) < function->
number_args) {
1639 arguments.pop_back();
1641 arguments.emplace_back(function);
1649 const std::string original_name = template_name;
1653 template_name = (path / original_name).string();
1654 if (template_name.compare(0, 2,
"./") == 0) {
1655 template_name.erase(0, 2);
1661 file.open(template_name);
1663 const std::string text((std::istreambuf_iterator<
char>(file)), std::istreambuf_iterator<
char>());
1701 size_t current_bracket_level{0};
1702 size_t current_brace_level{0};
1710 if (current_brace_level == 0 && current_bracket_level == 0) {
1716 if (current_brace_level == 0 && current_bracket_level == 0) {
1722 if (current_brace_level == 0 && current_bracket_level == 0) {
1725 current_bracket_level += 1;
1728 if (current_brace_level == 0 && current_bracket_level == 0) {
1731 current_brace_level += 1;
1734 if (current_bracket_level == 0) {
1738 current_bracket_level -= 1;
1739 if (current_brace_level == 0 && current_bracket_level == 0) {
1744 if (current_brace_level == 0) {
1748 current_brace_level -= 1;
1749 if (current_brace_level == 0 && current_bracket_level == 0) {
1759 if (current_brace_level == 0 && current_bracket_level == 0) {
1766 goto parse_operator;
1793 arguments.emplace_back(func);
1797 arguments.emplace_back(
1877 while (!operator_stack.empty() && ((operator_stack.top()->
precedence > function_node->
precedence) ||
1883 operator_stack.emplace(function_node);
1886 if (current_brace_level == 0 && current_bracket_level == 0) {
1891 if (current_brace_level == 0 && current_bracket_level == 0) {
1904 arguments.emplace_back(expr);
1917 func->
arguments.emplace_back(arguments.back());
1918 arguments.pop_back();
1945 arguments.emplace_back(func);
1955 while (!operator_stack.empty()) {
1960 if (arguments.size() == 1) {
1961 expr = arguments[0];
1963 }
else if (arguments.size() > 1) {
2032 const std::string block_name =
static_cast<std::string>(
tok.text);
2034 auto block_statement_node =
2039 auto success = tmpl
.block_storage.emplace(block_name, block_statement_node);
2040 if (!success.second) {
2074 const Token key_token = value_token;
2079 static_cast<std::string>(value_token
.text),
2139 const std::string key =
static_cast<std::string>(
tok.text);
2146 if (tok.text !=
static_cast<
decltype(
tok.text)>(
"=")) {
2245 static std::string
load_file(
const std::filesystem::path& filename) {
2247 file.open(filename);
2251 std::string text((std::istreambuf_iterator<
char>(file)), std::istreambuf_iterator<
char>());
2261#ifndef INCLUDE_INJA_RENDERER_HPP_
2262#define INCLUDE_INJA_RENDERER_HPP_
2269#include <filesystem>
2296
2297
2300 buffer.reserve(data.size() + data.size() / 10);
2301 for (size_t pos = 0; pos != data.size(); ++pos) {
2302 switch (data[pos]) {
2304 buffer.append(
"&");
2307 buffer.append(
""");
2310 buffer.append(
"'");
2313 buffer.append(
"<");
2316 buffer.append(
">");
2319 buffer.append(&data[pos], 1);
2327
2328
2354 if (data->is_boolean()) {
2355 return data->get<
bool>();
2356 }
else if (data->is_number()) {
2357 return (*data != 0);
2358 }
else if (data->is_null()) {
2361 return !data->empty();
2365 if (value->is_string()) {
2371 }
else if (value->is_number_unsigned()) {
2373 }
else if (value->is_number_integer()) {
2375 }
else if (value->is_null()) {
2382 if (!expression_list
.root) {
2397 if (result ==
nullptr) {
2407 return std::make_shared<
json>(*result);
2416 auto result_ptr = std::make_shared<
json>(result);
2421 template <size_t N, size_t N_start = 0,
bool throw_not_found =
true>
2424 throw_renderer_error("function needs " + std::to_string(N_start + N) +
" variables, but has only found " +
2429 for (size_t i = N_start; i < N_start + N; i += 1) {
2439 std::array<
const json*, N> result;
2440 for (size_t i = 0; i < N; i += 1) {
2444 if (!result[N - i - 1]) {
2448 if (throw_not_found) {
2456 template <
bool throw_not_found =
true>
2470 for (size_t i = 0; i < N; i += 1) {
2474 if (!result[N - i - 1]) {
2478 if (throw_not_found) {
2487 for (
const auto& n : node
.nodes) {
2517 const auto value = std::make_shared<
json>(function_data
.callback(empty_args));
2541 make_result(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end()
);
2569 if (args[0]->is_string() && args[1]->is_string()) {
2571 }
else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2572 make_result(args[0]->get<
const json::number_integer_t>() + args[1]->get<
const json::number_integer_t>()
);
2574 make_result(args[0]->get<
const json::number_float_t>() + args[1]->get<
const json::number_float_t>()
);
2579 if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2580 make_result(args[0]->get<
const json::number_integer_t>() - args[1]->get<
const json::number_integer_t>()
);
2582 make_result(args[0]->get<
const json::number_float_t>() - args[1]->get<
const json::number_float_t>()
);
2587 if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2588 make_result(args[0]->get<
const json::number_integer_t>() * args[1]->get<
const json::number_integer_t>()
);
2590 make_result(args[0]->get<
const json::number_float_t>() * args[1]->get<
const json::number_float_t>()
);
2595 if (args[1]->get<
const json::number_float_t>() == 0) {
2598 make_result(args[0]->get<
const json::number_float_t>() / args[1]->get<
const json::number_float_t>()
);
2602 if (args[0]->is_number_integer() && args[1]->get<
const json::number_integer_t>() >= 0) {
2603 const auto result =
static_cast<
json::number_integer_t>(
2604 std::pow(args[0]->get<
const json::number_integer_t>(), args[1]->get<
const json::number_integer_t>()));
2608 std::pow(args[0]->get<
const json::number_float_t>(), args[1]->get<
const json::number_integer_t>());
2614 make_result(args[0]->get<
const json::number_integer_t>() % args[1]->get<
const json::number_integer_t>()
);
2629 if (args[0]->is_object()) {
2637 result[0] =
static_cast<
char>(::toupper(result[0]));
2638 std::transform(result.begin() + 1, result.end(), result.begin() + 1, [](
char c) {
2639 return static_cast<
char>(::tolower(c));
2649 const auto divisor = args[1]->get<
const json::number_integer_t>();
2650 make_result((divisor != 0) && (args[0]->get<
const json::number_integer_t>() % divisor == 0)
);
2661 auto&& name = args[1]->get_ref<
const json::string_t&>();
2680 if (val->is_string()) {
2688 std::transform(result.begin(), result.end(), result.begin(), [](
char c) {
2689 return static_cast<
char>(::tolower(c));
2695 const auto result = std::max_element(args[0]->begin(), args[0]->end());
2700 const auto result = std::min_element(args[0]->begin(), args[0]->end());
2708 std::iota(result.begin(), result.end(), 0);
2713 auto result = args[0]->get<std::string>();
2719 const auto precision = args[1]->get<
const json::number_integer_t>();
2720 const double result =
2721 std::round(args[0]->get<
const json::number_float_t>() * std::pow(10.0, precision)) / std::pow(10.0, precision);
2722 if (precision == 0) {
2730 std::sort(result_ptr->begin(), result_ptr->end());
2736 std::transform(result.begin(), result.end(), result.begin(), [](
char c) {
2737 return static_cast<
char>(::toupper(c));
2769 const size_t level_diff = (args.size() == 1) ? args[0]->get<std::size_t>() : 1;
2799 const auto separator = args[1]->get<
json::string_t>();
2800 std::ostringstream os;
2802 for (
const auto& value : *args[0]) {
2804 if (value.is_string()) {
2805 os << value.get<std::string>();
2830 if (!result->is_array()) {
2842 for (
auto it = result->begin(); it != result->end(); ++it) {
2850 if (index == result->size() - 1) {
2869 if (!result->is_object()) {
2880 for (
auto it = result->begin(); it != result->end(); ++it) {
2889 if (index == result->size() - 1) {
2928 const Template* parent_template = &included_template_it->second;
2951 std::string ptr = node
.key;
2968 if (loop_data !=
nullptr) {
2991
2992
3013 Environment(
const std::filesystem::path& input_path,
const std::filesystem::path& output_path)
3098 std::stringstream os;
3112 void write(
const std::filesystem::path& filename,
const json& data,
const std::string& filename_out) {
3125 write_with_json_file(
const std::filesystem::path& filename,
const std::string& filename_data,
const std::string& filename_out) {
3140 std::ostream&
render_to(std::ostream& os,
const std::string_view input,
const json& data) {
3156 return json::parse(std::istreambuf_iterator<
char>(file), std::istreambuf_iterator<
char>());
3160
3161
3167
3168
3174
3175
3181
3182
3191
3192
3193
3199
3200
3207
3208
3209 inline std::string
render(std::string_view input,
const json& data) {
3214
3215
3216 inline void render_to(std::ostream& os, std::string_view input,
const json& data) {
std::vector< mqtt::lib::Function > functions
std::vector< mqtt::lib::VoidFunction > voidFunctions
Base node class for the abstract syntax tree (AST).
virtual void accept(NodeVisitor &v) const =0
std::vector< std::shared_ptr< AstNode > > nodes
void accept(NodeVisitor &v) const override
void accept(NodeVisitor &v) const override
BlockStatementNode(BlockNode *const parent, const std::string &name, size_t pos)
static std::string convert_dot_to_ptr(std::string_view ptr_name)
void accept(NodeVisitor &v) const override
DataNode(std::string_view ptr_name, size_t pos)
const json::json_pointer ptr
Class for changing the configuration.
Environment(const std::filesystem::path &input_path, const std::filesystem::path &output_path)
std::ostream & render_to(std::ostream &os, const Template &tmpl, const json &data)
TemplateStorage template_storage
FunctionStorage function_storage
void set_throw_at_missing_includes(bool will_throw)
Sets whether a missing include will throw an error.
void add_void_callback(const std::string &name, int num_args, const VoidCallbackFunction &callback)
Adds a void callback with given number or arguments.
void set_statement(const std::string &open, const std::string &close)
Sets the opener and closer for template statements.
std::string render_file(const std::filesystem::path &filename, const json &data)
std::string render(const Template &tmpl, const json &data)
Environment(const std::filesystem::path &global_path)
void set_search_included_templates_in_files(bool search_in_files)
Sets the element notation syntax.
json load_json(const std::string &filename)
void set_trim_blocks(bool trim_blocks)
Sets whether to remove the first newline after a block.
std::string load_file(const std::string &filename)
RenderConfig render_config
void set_lstrip_blocks(bool lstrip_blocks)
Sets whether to strip the spaces and tabs from the start of a line to a block.
void set_comment(const std::string &open, const std::string &close)
Sets the opener and closer for template comments.
void set_line_statement(const std::string &open)
Sets the opener for template line statements.
void set_html_autoescape(bool will_escape)
Sets whether we'll automatically perform HTML escape.
std::filesystem::path output_path
std::string render_file_with_json_file(const std::filesystem::path &filename, const std::string &filename_data)
void write(const Template &temp, const json &data, const std::string &filename_out)
Template parse(std::string_view input)
Template parse_template(const std::filesystem::path &filename)
void set_include_callback(const std::function< Template(const std::filesystem::path &, const std::string &)> &callback)
Sets a function that is called when an included file is not found.
void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out)
void set_expression(const std::string &open, const std::string &close)
Sets the opener and closer for template expressions.
std::string render(std::string_view input, const json &data)
void add_callback(const std::string &name, const CallbackFunction &callback)
Adds a variadic callback.
void include_template(const std::string &name, const Template &tmpl)
std::filesystem::path input_path
void add_void_callback(const std::string &name, const VoidCallbackFunction &callback)
Adds a variadic void callback.
void add_callback(const std::string &name, int num_args, const CallbackFunction &callback)
Adds a callback with given number or arguments.
std::ostream & render_to(std::ostream &os, const std::string_view input, const json &data)
void write_with_json_file(const std::filesystem::path &filename, const std::string &filename_data, const std::string &filename_out)
ParserConfig parser_config
void write(const std::filesystem::path &filename, const json &data, const std::string &filename_out)
Template parse_file(const std::filesystem::path &filename)
void accept(NodeVisitor &v) const override
ExpressionListNode(size_t pos)
std::shared_ptr< ExpressionNode > root
void accept(NodeVisitor &v) const override
ExpressionNode(size_t pos)
ExtendsStatementNode(const std::string &file, size_t pos)
void accept(NodeVisitor &v) const override
ForArrayStatementNode(const std::string &value, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
ForObjectStatementNode(const std::string &key, const std::string &value, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
ExpressionListNode condition
virtual void accept(NodeVisitor &v) const =0
ForStatementNode(BlockNode *const parent, size_t pos)
std::vector< std::shared_ptr< ExpressionNode > > arguments
Associativity associativity
void accept(NodeVisitor &v) const override
CallbackFunction callback
FunctionNode(Op operation, size_t pos)
FunctionStorage::Operation Op
FunctionNode(std::string_view name, size_t pos)
Class for builtin functions and user-defined callbacks.
void add_builtin(std::string_view name, int num_args, Operation op)
std::map< std::pair< std::string, int >, FunctionData > function_storage
void add_callback(std::string_view name, int num_args, const CallbackFunction &callback)
FunctionData find_function(std::string_view name, int num_args) const
void accept(NodeVisitor &v) const override
BlockNode false_statement
IfStatementNode(BlockNode *const parent, size_t pos)
ExpressionListNode condition
IfStatementNode(bool is_nested, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
IncludeStatementNode(const std::string &file, size_t pos)
Class for lexing an inja Template.
const LexerConfig & config
SourceLocation current_position() const
static std::string_view clear_final_line_if_whitespace(std::string_view text)
const LexerConfig & get_config() const
void skip_whitespaces_and_newlines()
Token make_token(Token::Kind kind) const
@ StatementStartForceLstrip
@ ExpressionStartForceLstrip
@ CommentStartForceLstrip
Token scan_body(std::string_view close, Token::Kind closeKind, std::string_view close_trim=std::string_view(), bool trim=false)
Lexer(const LexerConfig &config)
void skip_whitespaces_and_first_newline()
void start(std::string_view input)
void accept(NodeVisitor &v) const override
LiteralNode(std::string_view data_text, size_t pos)
virtual void visit(const DataNode &node)=0
virtual void visit(const SetStatementNode &node)=0
virtual void visit(const ExpressionListNode &node)=0
virtual ~NodeVisitor()=default
virtual void visit(const StatementNode &node)=0
virtual void visit(const ExtendsStatementNode &node)=0
virtual void visit(const IncludeStatementNode &node)=0
virtual void visit(const TextNode &node)=0
virtual void visit(const ForStatementNode &node)=0
virtual void visit(const LiteralNode &node)=0
virtual void visit(const ExpressionNode &node)=0
virtual void visit(const ForObjectStatementNode &node)=0
virtual void visit(const BlockStatementNode &node)=0
virtual void visit(const IfStatementNode &node)=0
virtual void visit(const FunctionNode &node)=0
virtual void visit(const ForArrayStatementNode &node)=0
virtual void visit(const BlockNode &node)=0
Class for parsing an inja Template.
void throw_parser_error(const std::string &message) const
std::string parse_filename() const
std::stack< BlockStatementNode * > block_statement_stack
void parse_into(Template &tmpl, const std::filesystem::path &path)
void add_operator(Arguments &arguments, OperatorStack &operator_stack)
std::stack< ForStatementNode * > for_statement_stack
ExpressionListNode * current_expression_list
std::vector< std::shared_ptr< ExpressionNode > > Arguments
TemplateStorage & template_storage
std::stack< std::shared_ptr< FunctionNode > > OperatorStack
std::shared_ptr< ExpressionNode > parse_expression(Template &tmpl)
Parser(const ParserConfig &parser_config, const LexerConfig &lexer_config, TemplateStorage &template_storage, const FunctionStorage &function_storage)
const FunctionStorage & function_storage
void add_to_template_storage(const std::filesystem::path &path, std::string &template_name)
const ParserConfig & config
static std::string load_file(const std::filesystem::path &filename)
std::stack< IfStatementNode * > if_statement_stack
BlockNode * current_block
void add_literal(Arguments &arguments, const char *content_ptr)
Template parse(std::string_view input, const std::filesystem::path &path)
std::string_view literal_start
bool parse_expression(Template &tmpl, Token::Kind closing)
void parse_into_template(Template &tmpl, const std::filesystem::path &filename)
bool parse_statement(Template &tmpl, Token::Kind closing, const std::filesystem::path &path)
Class for rendering a Template with data.
std::array< const json *, N > get_arguments(const FunctionNode &node)
void visit(const FunctionNode &node) override
void visit(const ExpressionListNode &node) override
const std::shared_ptr< json > eval_expression_list(const ExpressionListNode &expression_list)
std::vector< std::shared_ptr< json > > data_tmp_stack
void visit(const DataNode &node) override
void visit(const StatementNode &) override
std::ostream * output_stream
void throw_renderer_error(const std::string &message, const AstNode &node)
const RenderConfig config
std::stack< const json * > data_eval_stack
std::stack< const DataNode * > not_found_stack
void visit(const TextNode &node) override
std::vector< const BlockStatementNode * > block_statement_stack
Arguments get_argument_vector(const FunctionNode &node)
static bool truthy(const json *data)
const Template * current_template
void visit(const ExpressionNode &) override
void print_data(const std::shared_ptr< json > &value)
void visit(const SetStatementNode &node) override
void visit(const IncludeStatementNode &node) override
void visit(const ForStatementNode &) override
FunctionStorage::Operation Op
std::vector< const Template * > template_stack
void visit(const ForArrayStatementNode &node) override
const FunctionStorage & function_storage
const TemplateStorage & template_storage
void visit(const IfStatementNode &node) override
void make_result(const json &&result)
void render_to(std::ostream &os, const Template &tmpl, const json &data, json *loop_data=nullptr)
Renderer(const RenderConfig &config, const TemplateStorage &template_storage, const FunctionStorage &function_storage)
void visit(const BlockNode &node) override
void visit(const LiteralNode &node) override
void visit(const ExtendsStatementNode &node) override
void visit(const ForObjectStatementNode &node) override
void visit(const BlockStatementNode &node) override
ExpressionListNode expression
SetStatementNode(const std::string &key, size_t pos)
void accept(NodeVisitor &v) const override
StatementNode(size_t pos)
virtual void accept(NodeVisitor &v) const =0
A class for counting statistics on a Template.
void visit(const LiteralNode &) override
void visit(const IfStatementNode &node) override
void visit(const DataNode &) override
void visit(const IncludeStatementNode &) override
void visit(const ForArrayStatementNode &node) override
void visit(const StatementNode &) override
void visit(const BlockNode &node) override
void visit(const FunctionNode &node) override
void visit(const ExpressionListNode &node) override
void visit(const ForStatementNode &) override
void visit(const SetStatementNode &) override
void visit(const ExtendsStatementNode &) override
void visit(const TextNode &) override
void visit(const ExpressionNode &) override
void visit(const ForObjectStatementNode &node) override
void visit(const BlockStatementNode &node) override
TextNode(size_t pos, size_t length)
void accept(NodeVisitor &v) const override
static void store(const inja::Arguments &args)
static double recall_as_float(const inja::Arguments &args)
static const std::string & recall(const inja::Arguments &args)
static bool exists(const inja::Arguments &args)
static bool is_empty(const inja::Arguments &args)
Storage & operator=(const Storage &)=delete
static int recall_as_int(const inja::Arguments &args)
std::map< std::string, std::string > storage
Storage(const Storage &)=delete
static Storage & instance()
#define INJA_THROW(exception)
std::pair< std::string_view, std::string_view > split(std::string_view view, char Separator)
bool starts_with(std::string_view view, std::string_view prefix)
std::string_view slice(std::string_view view, size_t start, size_t end)
std::vector< const nlohmann::json * > Arguments
void replace_substring(std::string &s, const std::string &f, const std::string &t)
std::function< void(Arguments &args)> VoidCallbackFunction
std::string render(std::string_view input, const json &data)
render with default settings to a string
std::map< std::string, Template > TemplateStorage
void render_to(std::ostream &os, std::string_view input, const json &data)
render with default settings to the given output stream
std::function< json(Arguments &args)> CallbackFunction
SourceLocation get_source_location(std::string_view content, size_t pos)
std::string htmlescape(const std::string &data)
Escapes HTML.
DataError(const std::string &message, SourceLocation location)
FileError(const std::string &message)
FileError(const std::string &message, SourceLocation location)
const Operation operation
FunctionData(const Operation &op, const CallbackFunction &cb=CallbackFunction{})
const CallbackFunction callback
InjaError(const std::string &type, const std::string &message)
InjaError(const std::string &type, const std::string &message, SourceLocation location)
const SourceLocation location
const std::string message
Class for lexer configuration.
std::string expression_open_force_lstrip
std::string expression_close
std::string expression_close_force_rstrip
std::string comment_open_force_lstrip
std::string comment_close
std::string statement_close
std::string expression_open
std::string comment_close_force_rstrip
std::string statement_open_force_lstrip
std::string statement_close_force_rstrip
std::string statement_open_no_lstrip
std::string statement_open
std::string line_statement
Class for parser configuration.
bool search_included_templates_in_files
std::function< Template(const std::filesystem::path &, const std::string &)> include_callback
ParserError(const std::string &message, SourceLocation location)
Class for render configuration.
bool throw_at_missing_includes
RenderError(const std::string &message, SourceLocation location)
size_t count_variables() const
Return number of variables (total number, not distinct ones) in the template.
std::map< std::string, std::shared_ptr< BlockStatementNode > > block_storage
Template(std::string content)
Helper-class for the inja Lexer.
constexpr Token()=default
std::string describe() const
constexpr Token(Kind kind, std::string_view text)