mirror of
https://github.com/pantor/inja.git
synced 2026-02-20 18:36:24 +00:00
add config throw_missing_includes, search_in_files
This commit is contained in:
13
README.md
13
README.md
@@ -178,17 +178,22 @@ render("{% if not guest_count %}…{% endif %}", data); // True
|
||||
|
||||
#### Includes
|
||||
|
||||
You can either include other template files or already parsed templates.
|
||||
You can either include other in-memory templates or from the file system.
|
||||
```.cpp
|
||||
// Other template files are included relative from the current file location
|
||||
render("{% include \"footer.html\" %}", data);
|
||||
|
||||
// To include in-memory templates, add them to the environment first
|
||||
inja::Template content_template = env.parse("Hello {{ neighbour }}!");
|
||||
env.include_template("content", content_template);
|
||||
env.render("Content: {% include \"content\" %}", data); // "Content: Hello Peter!"
|
||||
|
||||
// Other template files are included relative from the current file location
|
||||
render("{% include \"footer.html\" %}", data);
|
||||
|
||||
// You can disable to search for templates in the file system via
|
||||
env.set_search_included_templates_in_files(false);
|
||||
```
|
||||
|
||||
Inja will throw an `inja::RenderError` if an included file is not found.
|
||||
|
||||
### Functions
|
||||
|
||||
A few functions are implemented within the inja template syntax. They can be called with
|
||||
|
||||
@@ -50,6 +50,14 @@ struct LexerConfig {
|
||||
*/
|
||||
struct ParserConfig {
|
||||
ElementNotation notation {ElementNotation::Dot};
|
||||
bool search_included_templates_in_files {true};
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Class for render configuration.
|
||||
*/
|
||||
struct RenderConfig {
|
||||
bool throw_at_missing_includes {true};
|
||||
};
|
||||
|
||||
} // namespace inja
|
||||
|
||||
@@ -26,6 +26,16 @@ using json = nlohmann::json;
|
||||
* \brief Class for changing the configuration.
|
||||
*/
|
||||
class Environment {
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
RenderConfig render_config;
|
||||
|
||||
FunctionStorage function_storage;
|
||||
TemplateStorage template_storage;
|
||||
|
||||
public:
|
||||
Environment() : Environment("") {}
|
||||
|
||||
@@ -76,6 +86,16 @@ public:
|
||||
parser_config.notation = notation;
|
||||
}
|
||||
|
||||
/// Sets the element notation syntax
|
||||
void set_search_included_templates_in_files(bool search_in_files) {
|
||||
parser_config.search_included_templates_in_files = search_in_files;
|
||||
}
|
||||
|
||||
/// Sets whether a missing include will throw an error
|
||||
void set_throw_at_missing_includes(bool will_throw) {
|
||||
render_config.throw_at_missing_includes = will_throw;
|
||||
}
|
||||
|
||||
Template parse(nonstd::string_view input) {
|
||||
Parser parser(parser_config, lexer_config, template_storage);
|
||||
return parser.parse(input);
|
||||
@@ -127,7 +147,7 @@ public:
|
||||
}
|
||||
|
||||
std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) {
|
||||
Renderer(template_storage, function_storage).render_to(os, tmpl, data);
|
||||
Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -154,16 +174,6 @@ public:
|
||||
void include_template(const std::string &name, const Template &tmpl) {
|
||||
template_storage[name] = tmpl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
|
||||
FunctionStorage function_storage;
|
||||
TemplateStorage template_storage;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -475,7 +475,7 @@ public:
|
||||
}
|
||||
// sys::path::remove_dots(pathname, true, sys::path::Style::posix);
|
||||
|
||||
if (template_storage.find(pathname) == template_storage.end()) {
|
||||
if (config.search_included_templates_in_files && template_storage.find(pathname) == template_storage.end()) {
|
||||
Template include_template = parse_template(pathname);
|
||||
template_storage.emplace(pathname, include_template);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "exceptions.hpp"
|
||||
#include "node.hpp"
|
||||
#include "template.hpp"
|
||||
@@ -176,9 +177,11 @@ class Renderer {
|
||||
std::vector<const json *> m_tmp_args;
|
||||
json m_tmp_val;
|
||||
|
||||
RenderConfig config;
|
||||
|
||||
public:
|
||||
Renderer(const TemplateStorage &included_templates, const FunctionStorage &callbacks)
|
||||
: template_storage(included_templates), function_storage(callbacks) {
|
||||
Renderer(const RenderConfig& config, const TemplateStorage &included_templates, const FunctionStorage &callbacks)
|
||||
: config(config), template_storage(included_templates), function_storage(callbacks) {
|
||||
m_stack.reserve(16);
|
||||
m_tmp_args.reserve(4);
|
||||
m_loop_stack.reserve(16);
|
||||
@@ -471,10 +474,14 @@ public:
|
||||
break;
|
||||
}
|
||||
case Node::Op::Include: {
|
||||
auto sub_renderer = Renderer(template_storage, function_storage);
|
||||
auto sub_renderer = Renderer(config, template_storage, function_storage);
|
||||
auto include_name = get_imm(node)->get_ref<const std::string &>();
|
||||
auto included_template = template_storage.find(include_name)->second;
|
||||
sub_renderer.render_to(os, included_template, *m_data, m_loop_data);
|
||||
auto included_template_it = template_storage.find(include_name);
|
||||
if (included_template_it != template_storage.end()) {
|
||||
sub_renderer.render_to(os, included_template_it->second, *m_data, m_loop_data);
|
||||
} else if (config.throw_at_missing_includes) {
|
||||
throw_renderer_error("include '" + include_name + "' not found", node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Node::Op::Callback: {
|
||||
|
||||
@@ -1488,6 +1488,14 @@ struct LexerConfig {
|
||||
*/
|
||||
struct ParserConfig {
|
||||
ElementNotation notation {ElementNotation::Dot};
|
||||
bool search_included_templates_in_files {true};
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Class for render configuration.
|
||||
*/
|
||||
struct RenderConfig {
|
||||
bool throw_at_missing_includes {true};
|
||||
};
|
||||
|
||||
} // namespace inja
|
||||
@@ -2760,7 +2768,7 @@ public:
|
||||
}
|
||||
// sys::path::remove_dots(pathname, true, sys::path::Style::posix);
|
||||
|
||||
if (template_storage.find(pathname) == template_storage.end()) {
|
||||
if (config.search_included_templates_in_files && template_storage.find(pathname) == template_storage.end()) {
|
||||
Template include_template = parse_template(pathname);
|
||||
template_storage.emplace(pathname, include_template);
|
||||
}
|
||||
@@ -2910,6 +2918,8 @@ public:
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// #include "config.hpp"
|
||||
|
||||
// #include "exceptions.hpp"
|
||||
|
||||
// #include "node.hpp"
|
||||
@@ -3079,9 +3089,11 @@ class Renderer {
|
||||
std::vector<const json *> m_tmp_args;
|
||||
json m_tmp_val;
|
||||
|
||||
RenderConfig config;
|
||||
|
||||
public:
|
||||
Renderer(const TemplateStorage &included_templates, const FunctionStorage &callbacks)
|
||||
: template_storage(included_templates), function_storage(callbacks) {
|
||||
Renderer(const RenderConfig& config, const TemplateStorage &included_templates, const FunctionStorage &callbacks)
|
||||
: config(config), template_storage(included_templates), function_storage(callbacks) {
|
||||
m_stack.reserve(16);
|
||||
m_tmp_args.reserve(4);
|
||||
m_loop_stack.reserve(16);
|
||||
@@ -3374,10 +3386,14 @@ public:
|
||||
break;
|
||||
}
|
||||
case Node::Op::Include: {
|
||||
auto sub_renderer = Renderer(template_storage, function_storage);
|
||||
auto sub_renderer = Renderer(config, template_storage, function_storage);
|
||||
auto include_name = get_imm(node)->get_ref<const std::string &>();
|
||||
auto included_template = template_storage.find(include_name)->second;
|
||||
sub_renderer.render_to(os, included_template, *m_data, m_loop_data);
|
||||
auto included_template_it = template_storage.find(include_name);
|
||||
if (included_template_it != template_storage.end()) {
|
||||
sub_renderer.render_to(os, included_template_it->second, *m_data, m_loop_data);
|
||||
} else if (config.throw_at_missing_includes) {
|
||||
throw_renderer_error("include '" + include_name + "' not found", node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Node::Op::Callback: {
|
||||
@@ -3521,6 +3537,16 @@ using json = nlohmann::json;
|
||||
* \brief Class for changing the configuration.
|
||||
*/
|
||||
class Environment {
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
RenderConfig render_config;
|
||||
|
||||
FunctionStorage function_storage;
|
||||
TemplateStorage template_storage;
|
||||
|
||||
public:
|
||||
Environment() : Environment("") {}
|
||||
|
||||
@@ -3571,6 +3597,16 @@ public:
|
||||
parser_config.notation = notation;
|
||||
}
|
||||
|
||||
/// Sets the element notation syntax
|
||||
void set_search_included_templates_in_files(bool search_in_files) {
|
||||
parser_config.search_included_templates_in_files = search_in_files;
|
||||
}
|
||||
|
||||
/// Sets whether a missing include will throw an error
|
||||
void set_throw_at_missing_includes(bool will_throw) {
|
||||
render_config.throw_at_missing_includes = will_throw;
|
||||
}
|
||||
|
||||
Template parse(nonstd::string_view input) {
|
||||
Parser parser(parser_config, lexer_config, template_storage);
|
||||
return parser.parse(input);
|
||||
@@ -3622,7 +3658,7 @@ public:
|
||||
}
|
||||
|
||||
std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) {
|
||||
Renderer(template_storage, function_storage).render_to(os, tmpl, data);
|
||||
Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -3649,16 +3685,6 @@ public:
|
||||
void include_template(const std::string &name, const Template &tmpl) {
|
||||
template_storage[name] = tmpl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string input_path;
|
||||
std::string output_path;
|
||||
|
||||
LexerConfig lexer_config;
|
||||
ParserConfig parser_config;
|
||||
|
||||
FunctionStorage function_storage;
|
||||
TemplateStorage template_storage;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -73,3 +73,12 @@ TEST_CASE("global-path") {
|
||||
CHECK(env_result.load_file("global-path-result.txt") == "Hello Jeff.");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("include-without-local-files") {
|
||||
inja::Environment env {test_file_directory};
|
||||
env.set_search_included_templates_in_files(false);
|
||||
|
||||
SUBCASE("html") {
|
||||
CHECK_THROWS_WITH(env.render_file_with_json_file("html/template.txt", "html/data.json"), "[inja.exception.render_error] (at 21:1) include '../test/data/html/header.txt' not found");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user