| // Copyright (c) 2019 Pantor. All rights reserved. |
| |
| #ifndef INCLUDE_INJA_ENVIRONMENT_HPP_ |
| #define INCLUDE_INJA_ENVIRONMENT_HPP_ |
| |
| #include <fstream> |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| |
| #include <nlohmann/json.hpp> |
| |
| #include "config.hpp" |
| #include "function_storage.hpp" |
| #include "parser.hpp" |
| #include "renderer.hpp" |
| #include "string_view.hpp" |
| #include "template.hpp" |
| #include "utils.hpp" |
| |
| namespace inja { |
| |
| using json = nlohmann::json; |
| |
| /*! |
| * \brief Class for changing the configuration. |
| */ |
| class Environment { |
| public: |
| Environment() : Environment("") {} |
| |
| explicit Environment(const std::string &global_path) : m_input_path(global_path), m_output_path(global_path) {} |
| |
| Environment(const std::string &input_path, const std::string &output_path) |
| : m_input_path(input_path), m_output_path(output_path) {} |
| |
| /// Sets the opener and closer for template statements |
| void set_statement(const std::string &open, const std::string &close) { |
| m_lexer_config.statement_open = open; |
| m_lexer_config.statement_close = close; |
| m_lexer_config.update_open_chars(); |
| } |
| |
| /// Sets the opener for template line statements |
| void set_line_statement(const std::string &open) { |
| m_lexer_config.line_statement = open; |
| m_lexer_config.update_open_chars(); |
| } |
| |
| /// Sets the opener and closer for template expressions |
| void set_expression(const std::string &open, const std::string &close) { |
| m_lexer_config.expression_open = open; |
| m_lexer_config.expression_close = close; |
| m_lexer_config.update_open_chars(); |
| } |
| |
| /// Sets the opener and closer for template comments |
| void set_comment(const std::string &open, const std::string &close) { |
| m_lexer_config.comment_open = open; |
| m_lexer_config.comment_close = close; |
| m_lexer_config.update_open_chars(); |
| } |
| |
| /// Sets whether to remove the first newline after a block |
| void set_trim_blocks(bool trim_blocks) { m_lexer_config.trim_blocks = trim_blocks; } |
| |
| /// Sets whether to strip the spaces and tabs from the start of a line to a block |
| void set_lstrip_blocks(bool lstrip_blocks) { m_lexer_config.lstrip_blocks = lstrip_blocks; } |
| |
| /// Sets the element notation syntax |
| void set_element_notation(ElementNotation notation) { m_parser_config.notation = notation; } |
| |
| Template parse(nonstd::string_view input) { |
| Parser parser(m_parser_config, m_lexer_config, m_included_templates); |
| return parser.parse(input); |
| } |
| |
| Template parse_template(const std::string &filename) { |
| Parser parser(m_parser_config, m_lexer_config, m_included_templates); |
| return parser.parse_template(m_input_path + static_cast<std::string>(filename)); |
| } |
| |
| std::string render(nonstd::string_view input, const json &data) { return render(parse(input), data); } |
| |
| std::string render(const Template &tmpl, const json &data) { |
| std::stringstream os; |
| render_to(os, tmpl, data); |
| return os.str(); |
| } |
| |
| std::string render_file(const std::string &filename, const json &data) { |
| return render(parse_template(filename), data); |
| } |
| |
| std::string render_file_with_json_file(const std::string &filename, const std::string &filename_data) { |
| const json data = load_json(filename_data); |
| return render_file(filename, data); |
| } |
| |
| void write(const std::string &filename, const json &data, const std::string &filename_out) { |
| std::ofstream file(m_output_path + filename_out); |
| file << render_file(filename, data); |
| file.close(); |
| } |
| |
| void write(const Template &temp, const json &data, const std::string &filename_out) { |
| std::ofstream file(m_output_path + filename_out); |
| file << render(temp, data); |
| file.close(); |
| } |
| |
| void write_with_json_file(const std::string &filename, const std::string &filename_data, |
| const std::string &filename_out) { |
| const json data = load_json(filename_data); |
| write(filename, data, filename_out); |
| } |
| |
| void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out) { |
| const json data = load_json(filename_data); |
| write(temp, data, filename_out); |
| } |
| |
| std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) { |
| Renderer(m_included_templates, m_callbacks).render_to(os, tmpl, data); |
| return os; |
| } |
| |
| std::string load_file(const std::string &filename) { |
| Parser parser(m_parser_config, m_lexer_config, m_included_templates); |
| return parser.load_file(m_input_path + filename); |
| } |
| |
| json load_json(const std::string &filename) { |
| std::ifstream file = open_file_or_throw(m_input_path + filename); |
| json j; |
| file >> j; |
| return j; |
| } |
| |
| void add_callback(const std::string &name, unsigned int numArgs, const CallbackFunction &callback) { |
| m_callbacks.add_callback(name, numArgs, callback); |
| } |
| |
| /** Includes a template with a given name into the environment. |
| * Then, a template can be rendered in another template using the |
| * include "<name>" syntax. |
| */ |
| void include_template(const std::string &name, const Template &tmpl) { m_included_templates[name] = tmpl; } |
| |
| private: |
| std::string m_input_path; |
| std::string m_output_path; |
| |
| LexerConfig m_lexer_config; |
| ParserConfig m_parser_config; |
| |
| FunctionStorage m_callbacks; |
| TemplateStorage m_included_templates; |
| }; |
| |
| /*! |
| @brief render with default settings to a string |
| */ |
| inline std::string render(nonstd::string_view input, const json &data) { return Environment().render(input, data); } |
| |
| /*! |
| @brief render with default settings to the given output stream |
| */ |
| inline void render_to(std::ostream &os, nonstd::string_view input, const json &data) { |
| Environment env; |
| env.render_to(os, env.parse(input), data); |
| } |
| |
| } // namespace inja |
| |
| #endif // INCLUDE_INJA_ENVIRONMENT_HPP_ |