Inja  3.3.0
A Template Engine for Modern C++
environment.hpp
1 #ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
2 #define INCLUDE_INJA_ENVIRONMENT_HPP_
3 
4 #include <fstream>
5 #include <iostream>
6 #include <memory>
7 #include <sstream>
8 #include <string>
9 #include <string_view>
10 
11 #include "config.hpp"
12 #include "function_storage.hpp"
13 #include "parser.hpp"
14 #include "renderer.hpp"
15 #include "template.hpp"
16 #include "utils.hpp"
17 
18 namespace inja {
19 
23 class Environment {
24  LexerConfig lexer_config;
25  ParserConfig parser_config;
26  RenderConfig render_config;
27 
28  FunctionStorage function_storage;
29  TemplateStorage template_storage;
30 
31 protected:
32  std::string input_path;
33  std::string output_path;
34 
35 public:
36  Environment(): Environment("") {}
37 
38  explicit Environment(const std::string& global_path): input_path(global_path), output_path(global_path) {}
39 
40  Environment(const std::string& input_path, const std::string& output_path): input_path(input_path), output_path(output_path) {}
41 
43  void set_statement(const std::string& open, const std::string& close) {
44  lexer_config.statement_open = open;
45  lexer_config.statement_open_no_lstrip = open + "+";
46  lexer_config.statement_open_force_lstrip = open + "-";
47  lexer_config.statement_close = close;
48  lexer_config.statement_close_force_rstrip = "-" + close;
49  lexer_config.update_open_chars();
50  }
51 
53  void set_line_statement(const std::string& open) {
54  lexer_config.line_statement = open;
55  lexer_config.update_open_chars();
56  }
57 
59  void set_expression(const std::string& open, const std::string& close) {
60  lexer_config.expression_open = open;
61  lexer_config.expression_open_force_lstrip = open + "-";
62  lexer_config.expression_close = close;
63  lexer_config.expression_close_force_rstrip = "-" + close;
64  lexer_config.update_open_chars();
65  }
66 
68  void set_comment(const std::string& open, const std::string& close) {
69  lexer_config.comment_open = open;
70  lexer_config.comment_open_force_lstrip = open + "-";
71  lexer_config.comment_close = close;
72  lexer_config.comment_close_force_rstrip = "-" + close;
73  lexer_config.update_open_chars();
74  }
75 
77  void set_trim_blocks(bool trim_blocks) {
78  lexer_config.trim_blocks = trim_blocks;
79  }
80 
82  void set_lstrip_blocks(bool lstrip_blocks) {
83  lexer_config.lstrip_blocks = lstrip_blocks;
84  }
85 
87  void set_search_included_templates_in_files(bool search_in_files) {
88  parser_config.search_included_templates_in_files = search_in_files;
89  }
90 
92  void set_throw_at_missing_includes(bool will_throw) {
93  render_config.throw_at_missing_includes = will_throw;
94  }
95 
96  Template parse(std::string_view input) {
97  Parser parser(parser_config, lexer_config, template_storage, function_storage);
98  return parser.parse(input, input_path);
99  }
100 
101  Template parse_template(const std::string& filename) {
102  Parser parser(parser_config, lexer_config, template_storage, function_storage);
103  auto result = Template(parser.load_file(input_path + static_cast<std::string>(filename)));
104  parser.parse_into_template(result, input_path + static_cast<std::string>(filename));
105  return result;
106  }
107 
108  Template parse_file(const std::string& filename) {
109  return parse_template(filename);
110  }
111 
112  std::string render(std::string_view input, const json& data) {
113  return render(parse(input), data);
114  }
115 
116  std::string render(const Template& tmpl, const json& data) {
117  std::stringstream os;
118  render_to(os, tmpl, data);
119  return os.str();
120  }
121 
122  std::string render_file(const std::string& filename, const json& data) {
123  return render(parse_template(filename), data);
124  }
125 
126  std::string render_file_with_json_file(const std::string& filename, const std::string& filename_data) {
127  const json data = load_json(filename_data);
128  return render_file(filename, data);
129  }
130 
131  void write(const std::string& filename, const json& data, const std::string& filename_out) {
132  std::ofstream file(output_path + filename_out);
133  file << render_file(filename, data);
134  file.close();
135  }
136 
137  void write(const Template& temp, const json& data, const std::string& filename_out) {
138  std::ofstream file(output_path + filename_out);
139  file << render(temp, data);
140  file.close();
141  }
142 
143  void write_with_json_file(const std::string& filename, const std::string& filename_data, const std::string& filename_out) {
144  const json data = load_json(filename_data);
145  write(filename, data, filename_out);
146  }
147 
148  void write_with_json_file(const Template& temp, const std::string& filename_data, const std::string& filename_out) {
149  const json data = load_json(filename_data);
150  write(temp, data, filename_out);
151  }
152 
153  std::ostream& render_to(std::ostream& os, const Template& tmpl, const json& data) {
154  Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
155  return os;
156  }
157 
158  std::string load_file(const std::string& filename) {
159  Parser parser(parser_config, lexer_config, template_storage, function_storage);
160  return parser.load_file(input_path + filename);
161  }
162 
163  json load_json(const std::string& filename) {
164  std::ifstream file;
165  file.open(input_path + filename);
166  if (file.fail()) {
167  INJA_THROW(FileError("failed accessing file at '" + input_path + filename + "'"));
168  }
169 
170  return json::parse(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
171  }
172 
176  void add_callback(const std::string& name, const CallbackFunction& callback) {
177  add_callback(name, -1, callback);
178  }
179 
183  void add_void_callback(const std::string& name, const VoidCallbackFunction& callback) {
184  add_void_callback(name, -1, callback);
185  }
186 
190  void add_callback(const std::string& name, int num_args, const CallbackFunction& callback) {
191  function_storage.add_callback(name, num_args, callback);
192  }
193 
197  void add_void_callback(const std::string& name, int num_args, const VoidCallbackFunction& callback) {
198  function_storage.add_callback(name, num_args, [callback](Arguments& args) {
199  callback(args);
200  return json();
201  });
202  }
203 
208  void include_template(const std::string& name, const Template& tmpl) {
209  template_storage[name] = tmpl;
210  }
211 
215  void set_include_callback(const std::function<Template(const std::string&, const std::string&)>& callback) {
216  parser_config.include_callback = callback;
217  }
218 };
219 
223 inline std::string render(std::string_view input, const json& data) {
224  return Environment().render(input, data);
225 }
226 
230 inline void render_to(std::ostream& os, std::string_view input, const json& data) {
231  Environment env;
232  env.render_to(os, env.parse(input), data);
233 }
234 
235 } // namespace inja
236 
237 #endif // INCLUDE_INJA_ENVIRONMENT_HPP_
inja::Environment::set_include_callback
void set_include_callback(const std::function< Template(const std::string &, const std::string &)> &callback)
Sets a function that is called when an included file is not found.
Definition: environment.hpp:215
inja::Environment::set_statement
void set_statement(const std::string &open, const std::string &close)
Sets the opener and closer for template statements.
Definition: environment.hpp:43
inja::Environment::set_comment
void set_comment(const std::string &open, const std::string &close)
Sets the opener and closer for template comments.
Definition: environment.hpp:68
inja::Environment
Class for changing the configuration.
Definition: environment.hpp:23
inja::Environment::set_trim_blocks
void set_trim_blocks(bool trim_blocks)
Sets whether to remove the first newline after a block.
Definition: environment.hpp:77
inja::Environment::add_void_callback
void add_void_callback(const std::string &name, int num_args, const VoidCallbackFunction &callback)
Adds a void callback with given number or arguments.
Definition: environment.hpp:197
inja::RenderConfig
Class for render configuration.
Definition: config.hpp:75
inja::LexerConfig
Class for lexer configuration.
Definition: config.hpp:14
inja::Environment::set_line_statement
void set_line_statement(const std::string &open)
Sets the opener for template line statements.
Definition: environment.hpp:53
inja::Environment::include_template
void include_template(const std::string &name, const Template &tmpl)
Definition: environment.hpp:208
inja::FunctionStorage
Class for builtin functions and user-defined callbacks.
Definition: function_storage.hpp:16
inja::Parser
Class for parsing an inja Template.
Definition: parser.hpp:24
inja::Environment::set_lstrip_blocks
void set_lstrip_blocks(bool lstrip_blocks)
Sets whether to strip the spaces and tabs from the start of a line to a block.
Definition: environment.hpp:82
inja::ParserConfig
Class for parser configuration.
Definition: config.hpp:66
inja::Environment::add_callback
void add_callback(const std::string &name, int num_args, const CallbackFunction &callback)
Adds a callback with given number or arguments.
Definition: environment.hpp:190
inja::Environment::set_expression
void set_expression(const std::string &open, const std::string &close)
Sets the opener and closer for template expressions.
Definition: environment.hpp:59
inja::Environment::add_callback
void add_callback(const std::string &name, const CallbackFunction &callback)
Adds a variadic callback.
Definition: environment.hpp:176
inja::Environment::set_search_included_templates_in_files
void set_search_included_templates_in_files(bool search_in_files)
Sets the element notation syntax.
Definition: environment.hpp:87
inja::Environment::set_throw_at_missing_includes
void set_throw_at_missing_includes(bool will_throw)
Sets whether a missing include will throw an error.
Definition: environment.hpp:92
inja::Environment::add_void_callback
void add_void_callback(const std::string &name, const VoidCallbackFunction &callback)
Adds a variadic void callback.
Definition: environment.hpp:183
inja::Template
The main inja Template.
Definition: template.hpp:17