ferencd@0: #ifndef TEMPLATER_H ferencd@0: #define TEMPLATER_H ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include "template_struct.h" ferencd@0: #include ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: #ifndef _WIN32 ferencd@0: #include ferencd@0: #endif ferencd@0: ferencd@0: static const std::string TEMPLATES_DIRECTORY = "theme/current/"; ferencd@0: ferencd@0: static const std::string TEMPLATE_VARIABLE_START_DELIMITER = "{#"; ferencd@0: static const std::string TEMPLATE_VARIABLE_END_DELIMITER = "}"; ferencd@0: ferencd@0: static const std::string INCLUDE_TAG = "" meaning ferencd@0: * that when the IncludeableTemplate is included its variables (specified in the list only) are exchhanged to the ferencd@0: * ones with values from the parameters. ferencd@0: * ferencd@0: * @param templatized - the actual content of the template string ferencd@0: * @param inc_pos - the start position ferencd@0: * @param do_variable_replacement - whether wer should replace the variables after including ferencd@0: * ferencd@0: * @return the templated string, where the includes were resolved and eventually the variables were replaced ferencd@0: */ ferencd@0: std::string resolve_includes(std::string templatized, size_t inc_pos, bool do_variable_replacement = true); ferencd@0: ferencd@0: std::string resolve_structure_declaration(size_t struct_pos, std::string templatized); ferencd@0: std::string resolve_parameters(size_t parameters_pos, std::string templatized); ferencd@0: std::string resolve_ifs(size_t if_pos, std::string templatized); ferencd@0: std::string resolve_ifeq(size_t if_pos, std::string templatized); ferencd@0: std::string resolve_defines(std::string content); ferencd@0: std::string resolve_script(size_t pos, const std::string &content, const std::string& tag); ferencd@0: std::string resolve_scripts(std::string templatized, const std::string& tag); ferencd@0: std::string resolve_loops(std::string templatized, const template_vector_par &v); ferencd@0: std::string resolve_ifeqs(std::string templatized); ferencd@0: ferencd@0: /** ferencd@0: * @brief resolve_translations resolves all the translations ferencd@0: * @param templatized ferencd@0: * @param target_language ferencd@0: * @param generate_span - whether to generate HTML spans for the translated elements ferencd@0: * @param translations - a map with the span ID's and their corresponding translations ferencd@0: * @return ferencd@0: */ ferencd@0: std::string resolve_translations(std::string templatized, const std::string& target_language, bool generate_span, std::map > &translations); ferencd@0: ferencd@0: /** ferencd@0: * @brief resolve_translation resolves one translation ferencd@0: * @param if_pos ferencd@0: * @param templatized ferencd@0: * @param target_language ferencd@0: * @param generate_span - whether to generate a span HTML element for this translation ferencd@0: * @param span_id - this will be the ID of the span, generated for this translation, used by the javascript at a later stage to set the language upon change ferencd@0: * @param translations - a map of translations for this given translation, for each language (key) the corresponding translated text (value) ferencd@0: * @return ferencd@0: */ ferencd@0: std::string resolve_translation(size_t if_pos, std::string templatized, const std::string& target_language, bool generate_span, std::string& span_id, std::map &translations); ferencd@0: std::string resolve_dynamic_section(std::string templatized, const template_vector_par &v); ferencd@0: ferencd@0: protected: ferencd@0: ferencd@0: // the string representation of the key/value pairs of the template that will be worked with ferencd@0: std::map kps; ferencd@0: ferencd@0: // the structures that are defined in this template are populated from this map of key/structure paris ferencd@0: std::map structures; ferencd@0: ferencd@0: // the parameters of te template ferencd@0: std::map m_parameters; ferencd@0: ferencd@0: // working data ferencd@0: std::string precalculated = ""; ferencd@0: std::string error = ""; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: class templater : public templater_base ferencd@0: { ferencd@0: protected: ferencd@0: bool resolve_in_get = true; ferencd@0: bool external_content_set = false; ferencd@0: std::string external_content = ""; ferencd@0: std::map > m_translation_map; ferencd@0: public: ferencd@0: ferencd@0: const std::map >& get_translations() ferencd@0: { ferencd@0: return m_translation_map; ferencd@0: } ferencd@0: ferencd@0: templater& templatize() ferencd@0: { ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: templater& templatize(const template_vector_par& v) ferencd@0: { ferencd@0: return dynamic_cast(templater_base::templatize(v)); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: templater& templatize(const template_par& b) ferencd@0: { ferencd@0: precalculated = ""; ferencd@0: kps.insert(make_pair(b.key(), unafrog::utils::to_string(b.value()))); ferencd@0: ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: templater& templatize(const nlohmann::json& j) ferencd@0: { ferencd@0: precalculated = ""; ferencd@0: for (const auto& [k, v] : j.items()) ferencd@0: { ferencd@0: if(v.is_string()) ferencd@0: { ferencd@0: std::string s = unafrog::utils::to_string(v); ferencd@0: remove_quotes(s); ferencd@0: kps.insert(make_pair(unafrog::utils::to_string(k), s)); ferencd@0: } ferencd@0: } ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: templater& templatize(const template_struct& s) ferencd@0: { ferencd@0: return dynamic_cast(templater_base::templatize(s)); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: templater& templatize(const template_struct& s, Args1... args) ferencd@0: { ferencd@0: precalculated = ""; ferencd@0: templatize(s); ferencd@0: return templatize(args...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: templater& templatize(const template_vector_par& v, Args1... args) ferencd@0: { ferencd@0: dynamic_cast(templater_base::templatize(v)); ferencd@0: return templatize(args...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: templater& templatize(const template_par& first, Args1... args) ferencd@0: { ferencd@0: precalculated = ""; ferencd@0: kps.insert(make_pair(first.key(), unafrog::utils::to_string(first.value()))); ferencd@0: return templatize(args...); ferencd@0: } ferencd@0: ferencd@0: void do_not_resolve_in_get() override ferencd@0: { ferencd@0: resolve_in_get = false; ferencd@0: } ferencd@0: void do_resolve_in_get() override ferencd@0: { ferencd@0: resolve_in_get = true; ferencd@0: } ferencd@0: ferencd@0: templater& set(const std::string& ec) ferencd@0: { ferencd@0: external_content = ec; ferencd@0: external_content_set = true; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: std::string get() override ferencd@0: { ferencd@0: if(precalculated.empty()) ferencd@0: { ferencd@0: std::string templatized = (external_content_set && external_content.size() > 0) ? external_content : templater_base::get(name()); ferencd@0: if(resolve_in_get) ferencd@0: { ferencd@0: templatized = resolve_ifeqs(templatized); ferencd@0: templatized = resolve_scripts(templatized, SCRIPT_TAG); ferencd@0: precalculated = templatized; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: precalculated = templatized; ferencd@0: } ferencd@0: ferencd@0: if(kps.count("target_language")) ferencd@0: { ferencd@0: precalculated = resolve_translations(precalculated, kps["target_language"], true, m_translation_map); ferencd@0: } ferencd@0: ferencd@0: return precalculated; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: return precalculated; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: std::string name() const override ferencd@0: { ferencd@0: return T::name(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: std::ostream& operator << (std::ostream& os, const templater& t) ferencd@0: { ferencd@0: os << t.get(); ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: template ferencd@0: struct translator : public templater ferencd@0: { ferencd@0: translator& templatize() ferencd@0: { ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: translator& templatize(const template_vector_par& v) ferencd@0: { ferencd@0: return dynamic_cast(templater_base::templatize(v)); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: translator& templatize(const template_par& b) ferencd@0: { ferencd@0: templater::precalculated = ""; ferencd@0: templater::kps.insert(make_pair(b.key(), unafrog::utils::to_string(b.value()))); ferencd@0: ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: translator& templatize(const nlohmann::json& j) ferencd@0: { ferencd@0: templater::precalculated = ""; ferencd@0: for (const auto& [k, v] : j.items()) ferencd@0: { ferencd@0: if(v.is_string()) ferencd@0: { ferencd@0: std::string s = unafrog::utils::to_string(v); ferencd@0: remove_quotes(s); ferencd@0: templater::kps.insert(make_pair(unafrog::utils::to_string(k), s)); ferencd@0: } ferencd@0: } ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: translator& templatize(const template_struct& s) ferencd@0: { ferencd@0: return dynamic_cast(templater_base::templatize(s)); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: translator& templatize(const template_struct& s, Args1... args) ferencd@0: { ferencd@0: templater::precalculated = ""; ferencd@0: templatize(s); ferencd@0: return templatize(args...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: translator& templatize(const template_par& first, Args1... args) ferencd@0: { ferencd@0: templater::precalculated = ""; ferencd@0: templater::kps.insert(make_pair(first.key(), unafrog::utils::to_string(first.value()))); ferencd@0: return templatize(args...); ferencd@0: } ferencd@0: ferencd@0: translator& set() ferencd@0: { ferencd@0: templater::get(); ferencd@0: templater::external_content = templater::precalculated; ferencd@0: templater::external_content_set = true; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: std::string translate(const std::string& target_language) ferencd@0: { ferencd@0: if(templater::external_content_set && templater::external_content.length() > 0) ferencd@0: { ferencd@0: return translate(templater::external_content, target_language, this->m_translation_map); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: std::string s = templater().templatize().get(); ferencd@0: return translate(s, target_language, this->m_translation_map); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: static std::string translate(const std::string& in, const std::string& target_language, std::map >& translation_map) ferencd@0: { ferencd@0: //TODO mutex ferencd@0: GENERIC_STRING_TEMPLATE(Translateable); ferencd@0: auto t = templater(); ferencd@0: std::string res = t.set(in).templatize("target_language" target_language).get(); ferencd@0: translation_map = t.get_translations(); ferencd@0: return res; ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: HTML_TEMPLATE(mainpage); ferencd@0: HTML_TEMPLATE(category_list); ferencd@0: HTML_TEMPLATE(recipe); ferencd@0: HTML_TEMPLATE(footer); ferencd@0: HTML_TEMPLATE(languages); ferencd@0: ferencd@0: #endif // TEMPLATER_H