77 lines
2.7 KiB
C++
77 lines
2.7 KiB
C++
#include "templating.hpp"
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <regex>
|
|
#include <stdexcept>
|
|
|
|
Templating::Templating(const std::string& template_dir)
|
|
: inja_env(std::filesystem::canonical(template_dir).string()),
|
|
template_dir(std::filesystem::canonical(template_dir).string())
|
|
{
|
|
inja_env.set_search_included_templates_in_files(true);
|
|
}
|
|
|
|
std::string Templating::preprocess_template(const std::string& template_name) {
|
|
namespace fs = std::filesystem;
|
|
|
|
fs::path abs_template_dir = fs::path(template_dir);
|
|
fs::path abs_template_file = fs::canonical(abs_template_dir / template_name);
|
|
|
|
std::ifstream file(abs_template_file);
|
|
if (!file.is_open()) {
|
|
throw std::runtime_error("Failed to open template file: " + abs_template_file.string());
|
|
}
|
|
|
|
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
|
|
|
std::regex extends_regex(R"(\{\%\s*extends\s*(['"])(.+?)\1\s*\%\})");
|
|
std::smatch match;
|
|
|
|
if (std::regex_search(content, match, extends_regex)) {
|
|
std::string quote = match[1].str();
|
|
std::string original_path = match[2].str();
|
|
|
|
if (original_path.find("/") == std::string::npos &&
|
|
!original_path.empty() &&
|
|
original_path.front() != '/') {
|
|
|
|
fs::path abs_extended_template = fs::canonical(abs_template_dir / original_path);
|
|
fs::path rel_path = fs::relative(abs_extended_template, abs_template_file.parent_path());
|
|
|
|
std::string new_path = rel_path.generic_string();
|
|
|
|
content = std::regex_replace(content, extends_regex,
|
|
"{% extends " + quote + new_path + quote + " %}");
|
|
}
|
|
}
|
|
|
|
return content;
|
|
}
|
|
|
|
|
|
crow::response Templating::render_template(const std::string& template_name, const inja::json& data) {
|
|
try {
|
|
std::string preprocessed = preprocess_template(template_name);
|
|
inja::Template tpl = inja_env.parse(preprocessed);
|
|
std::string rendered = inja_env.render(tpl, data);
|
|
return crow::response(rendered);
|
|
|
|
} catch (const std::exception& e) {
|
|
return crow::response(500, e.what());
|
|
}
|
|
}
|
|
|
|
crow::response Templating::render_template(const std::string& template_name) {
|
|
return render_template(template_name, inja::json{});
|
|
}
|
|
|
|
std::string Templating::render_template_string(const std::string& template_name, const inja::json& data) {
|
|
std::string preprocessed = preprocess_template(template_name);
|
|
inja::Template tpl = inja_env.parse(preprocessed);
|
|
return inja_env.render(tpl, data);
|
|
}
|
|
|
|
std::string Templating::render_template_string(const std::string& template_name) {
|
|
return render_template_string(template_name, inja::json{});
|
|
}
|