|
ferencd@0
|
1 #ifndef TEMPLATER_H
|
|
ferencd@0
|
2 #define TEMPLATER_H
|
|
ferencd@0
|
3
|
|
ferencd@0
|
4 #include <common.h>
|
|
ferencd@0
|
5 #include <named_operator.hpp>
|
|
ferencd@0
|
6 #include <json.h>
|
|
ferencd@0
|
7 #include "template_struct.h"
|
|
ferencd@0
|
8 #include <boost/noncopyable.hpp>
|
|
ferencd@0
|
9
|
|
ferencd@0
|
10 #include <string>
|
|
ferencd@0
|
11 #include <iostream>
|
|
ferencd@0
|
12 #include <vector>
|
|
ferencd@0
|
13 #include <set>
|
|
ferencd@0
|
14 #include <map>
|
|
ferencd@0
|
15 #include <sstream>
|
|
ferencd@0
|
16 #include <string>
|
|
ferencd@0
|
17 #include <map>
|
|
ferencd@0
|
18 #include <fstream>
|
|
ferencd@0
|
19 #include <memory>
|
|
ferencd@0
|
20
|
|
ferencd@0
|
21 #include <sys/types.h>
|
|
ferencd@0
|
22 #include <sys/stat.h>
|
|
ferencd@0
|
23
|
|
ferencd@0
|
24 #ifndef _WIN32
|
|
ferencd@0
|
25 #include <unistd.h>
|
|
ferencd@0
|
26 #endif
|
|
ferencd@0
|
27
|
|
ferencd@0
|
28 static const std::string TEMPLATES_DIRECTORY = "theme/current/";
|
|
ferencd@0
|
29
|
|
ferencd@0
|
30 static const std::string TEMPLATE_VARIABLE_START_DELIMITER = "{#";
|
|
ferencd@0
|
31 static const std::string TEMPLATE_VARIABLE_END_DELIMITER = "}";
|
|
ferencd@0
|
32
|
|
ferencd@0
|
33 static const std::string INCLUDE_TAG = "<!--#include";
|
|
ferencd@0
|
34 static const std::string TRANSLATE_TAG = "<!--#translate";
|
|
ferencd@0
|
35 static const std::string IF_TAG = "<!--#if";
|
|
ferencd@0
|
36 static const std::string IFEQ_TAG = "<!--#eq";
|
|
ferencd@0
|
37 static const std::string ELSE_TAG = "<!--#else";
|
|
ferencd@0
|
38 static const std::string ENDIF_TAG = "<!--#endif";
|
|
ferencd@0
|
39 static const std::string ENDEQ_TAG = "<!--#endeq";
|
|
ferencd@0
|
40 static const std::string STRUCT_TAG = "<!--#struct";
|
|
ferencd@0
|
41 static const std::string PARAMETERS_TAG = "<!--#parameters";
|
|
ferencd@0
|
42 static const std::string LOOP_TAG = "<!--#loop";
|
|
ferencd@0
|
43 static const std::string ENDLOOP_TAG = "<!--#endloop";
|
|
ferencd@0
|
44 static const std::string ENDTRANSLATE_TAG = "<!--#endtranslate";
|
|
ferencd@0
|
45 static const std::string DEFINE_TAG = "<!--#define";
|
|
ferencd@0
|
46
|
|
ferencd@0
|
47 // difference between script and inline script: inline-script is execute BEFORE the variable replacements, thus
|
|
ferencd@0
|
48 // it has the chance to modify the variables
|
|
ferencd@0
|
49 static const std::string SCRIPT_TAG = "<!--#script";
|
|
ferencd@0
|
50 static const std::string INIT_SCRIPT_TAG = "<!--#init-script";
|
|
ferencd@0
|
51 static const std::string ENDSCRIPT_TAG = "<!--#endscript";
|
|
ferencd@0
|
52
|
|
ferencd@0
|
53 /**
|
|
ferencd@0
|
54 * @brief The template_base class is the basic class for all the templates
|
|
ferencd@0
|
55 */
|
|
ferencd@0
|
56 class template_base
|
|
ferencd@0
|
57 {
|
|
ferencd@0
|
58 public:
|
|
ferencd@0
|
59 virtual ~template_base() = default;
|
|
ferencd@0
|
60 virtual std::string content() const = 0;
|
|
ferencd@0
|
61 virtual std::string base_dir() const = 0;
|
|
ferencd@0
|
62 virtual bool check() const = 0;
|
|
ferencd@0
|
63 };
|
|
ferencd@0
|
64
|
|
ferencd@0
|
65 /**
|
|
ferencd@0
|
66 * @brief The file_template class is a class for a template that resides in a file
|
|
ferencd@0
|
67 */
|
|
ferencd@0
|
68 class file_template : public template_base
|
|
ferencd@0
|
69 {
|
|
ferencd@0
|
70 public:
|
|
ferencd@0
|
71 file_template() = default;
|
|
ferencd@0
|
72
|
|
ferencd@0
|
73 virtual std::string fileName() const = 0;
|
|
ferencd@0
|
74 std::string base_dir() const override;
|
|
ferencd@0
|
75 virtual std::string content() const;
|
|
ferencd@0
|
76 virtual bool check() const;
|
|
ferencd@0
|
77 };
|
|
ferencd@0
|
78
|
|
ferencd@0
|
79 /**
|
|
ferencd@0
|
80 * @brief The template_warehouse class is the class that keeps track of the templates that were registered
|
|
ferencd@0
|
81 */
|
|
ferencd@0
|
82 class template_warehouse : public boost::noncopyable
|
|
ferencd@0
|
83 {
|
|
ferencd@0
|
84 public:
|
|
ferencd@0
|
85 static template_warehouse& instance();
|
|
ferencd@0
|
86
|
|
ferencd@0
|
87 std::string getTemplateContent(const std::string& templateName);
|
|
ferencd@0
|
88 bool registerTemplate(const std::string& name, template_base *templateClass);
|
|
ferencd@0
|
89 bool checkTemplates();
|
|
ferencd@0
|
90
|
|
ferencd@0
|
91 private:
|
|
ferencd@0
|
92 template_warehouse() = default;
|
|
ferencd@0
|
93 std::map <std::string, std::shared_ptr<template_base>> templates;
|
|
ferencd@0
|
94 };
|
|
ferencd@0
|
95
|
|
ferencd@0
|
96 #define GENERIC_TEMPLATE(Class, Type) \
|
|
ferencd@0
|
97 class Class : public file_template \
|
|
ferencd@0
|
98 { \
|
|
ferencd@0
|
99 public: \
|
|
ferencd@0
|
100 Class() = default; \
|
|
ferencd@0
|
101 static std::string name() {return std::string(#Class); } \
|
|
ferencd@0
|
102 virtual std::string fileName() const {return std::string(#Class) + "." + #Type; } \
|
|
ferencd@0
|
103 }; \
|
|
ferencd@0
|
104 [[maybe_unused]] static bool dummy##Class##Type = template_warehouse::instance().registerTemplate(#Class, new Class)
|
|
ferencd@0
|
105
|
|
ferencd@0
|
106 #define GENERIC_FILE_TEMPLATE(Class, Filename) \
|
|
ferencd@0
|
107 class Class : public file_template \
|
|
ferencd@0
|
108 { \
|
|
ferencd@0
|
109 public: \
|
|
ferencd@0
|
110 Class() = default; \
|
|
ferencd@0
|
111 static std::string name() {return std::string(#Class); } \
|
|
ferencd@0
|
112 virtual std::string fileName() const {return Filename ; } \
|
|
ferencd@0
|
113 }; \
|
|
ferencd@0
|
114 [[maybe_unused]] static bool dummy##Class##Type = template_warehouse::instance().registerTemplate(#Class, new Class)
|
|
ferencd@0
|
115
|
|
ferencd@0
|
116
|
|
ferencd@0
|
117 #define CSS_TEMPLATE(Class) GENERIC_TEMPLATE(Class, css)
|
|
ferencd@0
|
118 #define JS_TEMPLATE(Class) GENERIC_TEMPLATE(Class, js)
|
|
ferencd@0
|
119 #define TXT_TEMPLATE(Class) GENERIC_TEMPLATE(Class, txt)
|
|
ferencd@0
|
120 #define HTML_TEMPLATE(Class) GENERIC_TEMPLATE(Class, html)
|
|
ferencd@0
|
121
|
|
ferencd@0
|
122 #if (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__))
|
|
ferencd@0
|
123 #define REG_VAR(Class) [[maybe_unused]] static bool dummy##Class##Type __attribute__((unused)) = template_warehouse::instance().registerTemplate(#Class, new Class)
|
|
ferencd@0
|
124 #else
|
|
ferencd@0
|
125 #define REG_VAR(Class) [[gnu::unused]] static bool dummy##Class##Type = template_warehouse::instance().registerTemplate(#Class, new Class)
|
|
ferencd@0
|
126 #endif
|
|
ferencd@0
|
127
|
|
ferencd@0
|
128 #define STRING_TEMPLATE(Class, s) \
|
|
ferencd@0
|
129 class Class : public template_base \
|
|
ferencd@0
|
130 { \
|
|
ferencd@0
|
131 public: \
|
|
ferencd@0
|
132 Class() : m_content(s) {} \
|
|
ferencd@0
|
133 virtual ~Class() = default; \
|
|
ferencd@0
|
134 static std::string name() {return std::string(#Class); } \
|
|
ferencd@0
|
135 std::string base_dir() const override { return TEMPLATES_DIRECTORY; } \
|
|
ferencd@0
|
136 virtual std::string content() const override \
|
|
ferencd@0
|
137 { \
|
|
ferencd@0
|
138 return m_content; \
|
|
ferencd@0
|
139 } \
|
|
ferencd@0
|
140 virtual bool check() const override { return true; } \
|
|
ferencd@0
|
141 private: \
|
|
ferencd@0
|
142 std::string m_content; \
|
|
ferencd@0
|
143 }; \
|
|
ferencd@0
|
144 REG_VAR(Class)
|
|
ferencd@0
|
145
|
|
ferencd@0
|
146 #define STRING_VAR_TEMPLATE(Class, s) \
|
|
ferencd@0
|
147 static std::string _TS_ ## _Class = s; \
|
|
ferencd@0
|
148 class Class : public template_base \
|
|
ferencd@0
|
149 { \
|
|
ferencd@0
|
150 public: \
|
|
ferencd@0
|
151 Class() : m_content(_TS_ ## _Class) {} \
|
|
ferencd@0
|
152 virtual ~Class() = default; \
|
|
ferencd@0
|
153 static std::string name() {return std::string(#Class); } \
|
|
ferencd@0
|
154 std::string base_dir() const override { return TEMPLATES_DIRECTORY; } \
|
|
ferencd@0
|
155 virtual std::string content() const \
|
|
ferencd@0
|
156 { \
|
|
ferencd@0
|
157 return m_content; \
|
|
ferencd@0
|
158 } \
|
|
ferencd@0
|
159 virtual bool check() const { return true; } \
|
|
ferencd@0
|
160 private: \
|
|
ferencd@0
|
161 std::string m_content; \
|
|
ferencd@0
|
162 }; \
|
|
ferencd@0
|
163 REG_VAR(Class)
|
|
ferencd@0
|
164
|
|
ferencd@0
|
165 #define GENERIC_STRING_TEMPLATE(Class) \
|
|
ferencd@0
|
166 class Class : public template_base \
|
|
ferencd@0
|
167 { \
|
|
ferencd@0
|
168 public: \
|
|
ferencd@0
|
169 Class() : template_base() {} \
|
|
ferencd@0
|
170 virtual ~Class() = default; \
|
|
ferencd@0
|
171 static std::string name() {return std::string(#Class); } \
|
|
ferencd@0
|
172 std::string base_dir() const override { return TEMPLATES_DIRECTORY; } \
|
|
ferencd@0
|
173 virtual std::string content() const override \
|
|
ferencd@0
|
174 { \
|
|
ferencd@0
|
175 return m_content; \
|
|
ferencd@0
|
176 } \
|
|
ferencd@0
|
177 virtual bool check() const override { return true; } \
|
|
ferencd@0
|
178 private: \
|
|
ferencd@0
|
179 std::string m_content; \
|
|
ferencd@0
|
180 }; \
|
|
ferencd@0
|
181 REG_VAR(Class)
|
|
ferencd@0
|
182
|
|
ferencd@0
|
183
|
|
ferencd@0
|
184 /**
|
|
ferencd@0
|
185 * This class is the base for the template pairs of (key, value) that can be inserted in the tmeplate
|
|
ferencd@0
|
186 **/
|
|
ferencd@0
|
187 class template_pair_base
|
|
ferencd@0
|
188 {
|
|
ferencd@0
|
189 public:
|
|
ferencd@0
|
190 virtual ~template_pair_base() = default;
|
|
ferencd@0
|
191 };
|
|
ferencd@0
|
192
|
|
ferencd@0
|
193 class template_special_parameter
|
|
ferencd@0
|
194 {
|
|
ferencd@0
|
195 public:
|
|
ferencd@0
|
196 template_special_parameter() = default;
|
|
ferencd@0
|
197 virtual ~template_special_parameter() = default;
|
|
ferencd@0
|
198
|
|
ferencd@0
|
199 template_special_parameter(const std::string& pname,
|
|
ferencd@0
|
200 const std::string& ptype,
|
|
ferencd@0
|
201 bool piterable) :
|
|
ferencd@0
|
202 iterable(piterable), name(pname), type(ptype) {}
|
|
ferencd@0
|
203
|
|
ferencd@0
|
204 private:
|
|
ferencd@0
|
205 bool iterable;
|
|
ferencd@0
|
206 std::string name;
|
|
ferencd@0
|
207 std::string type;
|
|
ferencd@0
|
208 };
|
|
ferencd@0
|
209
|
|
ferencd@0
|
210
|
|
ferencd@0
|
211 /**
|
|
ferencd@0
|
212 * This is a wrapper class for a string that is used to do the actual replacing of strings
|
|
ferencd@0
|
213 * in the context of a template
|
|
ferencd@0
|
214 **/
|
|
ferencd@0
|
215 class stringholder
|
|
ferencd@0
|
216 {
|
|
ferencd@0
|
217 public:
|
|
ferencd@0
|
218
|
|
ferencd@0
|
219 stringholder(const std::string& d) : str(d)
|
|
ferencd@0
|
220 {}
|
|
ferencd@0
|
221
|
|
ferencd@0
|
222 void replace_all(const std::string& from, const std::string& to);
|
|
ferencd@0
|
223
|
|
ferencd@0
|
224 std::string get() const
|
|
ferencd@0
|
225 {
|
|
ferencd@0
|
226 return str;
|
|
ferencd@0
|
227 }
|
|
ferencd@0
|
228
|
|
ferencd@0
|
229 stringholder& templatize(const std::map<std::string, std::string>& m);
|
|
ferencd@0
|
230
|
|
ferencd@0
|
231 private:
|
|
ferencd@0
|
232
|
|
ferencd@0
|
233 std::string str;
|
|
ferencd@0
|
234 };
|
|
ferencd@0
|
235
|
|
ferencd@0
|
236 /**
|
|
ferencd@0
|
237 * The template parameter class, holds a classical template parameter
|
|
ferencd@0
|
238 **/
|
|
ferencd@0
|
239 template <class T>
|
|
ferencd@0
|
240 class template_par : public template_pair_base
|
|
ferencd@0
|
241 {
|
|
ferencd@0
|
242 public:
|
|
ferencd@0
|
243
|
|
ferencd@0
|
244 template_par(const std::string& name, const T& value) : m_key(name), m_value(unafrog::utils::to_string(value))
|
|
ferencd@0
|
245 {
|
|
ferencd@0
|
246 }
|
|
ferencd@0
|
247
|
|
ferencd@0
|
248 template_par(const char* name, const T& value) : template_par(std::string(name), value)
|
|
ferencd@0
|
249 {
|
|
ferencd@0
|
250 }
|
|
ferencd@0
|
251
|
|
ferencd@0
|
252 std::string value() const
|
|
ferencd@0
|
253 {
|
|
ferencd@0
|
254 return m_value;
|
|
ferencd@0
|
255 }
|
|
ferencd@0
|
256
|
|
ferencd@0
|
257 std::string key() const
|
|
ferencd@0
|
258 {
|
|
ferencd@0
|
259 return m_key;
|
|
ferencd@0
|
260 }
|
|
ferencd@0
|
261
|
|
ferencd@0
|
262 void set_value(const std::string& v)
|
|
ferencd@0
|
263 {
|
|
ferencd@0
|
264 m_value = v;
|
|
ferencd@0
|
265 }
|
|
ferencd@0
|
266
|
|
ferencd@0
|
267 private:
|
|
ferencd@0
|
268 template_pair_base* child;
|
|
ferencd@0
|
269 std::string m_key;
|
|
ferencd@0
|
270 std::string m_value;
|
|
ferencd@0
|
271 };
|
|
ferencd@0
|
272
|
|
ferencd@0
|
273 class template_vector_par : public template_pair_base
|
|
ferencd@0
|
274 {
|
|
ferencd@0
|
275 public:
|
|
ferencd@0
|
276 template_vector_par() = default;
|
|
ferencd@0
|
277
|
|
ferencd@0
|
278 template_vector_par(const char* name, const std::vector<template_struct>& value) : mname(name), mvalue(value)
|
|
ferencd@0
|
279 {
|
|
ferencd@0
|
280 }
|
|
ferencd@0
|
281
|
|
ferencd@0
|
282 template_vector_par(const std::string& name, const std::vector<template_struct>& value) : mname(name), mvalue(value)
|
|
ferencd@0
|
283 {
|
|
ferencd@0
|
284 }
|
|
ferencd@0
|
285
|
|
ferencd@0
|
286 const std::vector<template_struct>& value() const
|
|
ferencd@0
|
287 {
|
|
ferencd@0
|
288 return mvalue;
|
|
ferencd@0
|
289 }
|
|
ferencd@0
|
290
|
|
ferencd@0
|
291 std::string name() const
|
|
ferencd@0
|
292 {
|
|
ferencd@0
|
293 return mname;
|
|
ferencd@0
|
294 }
|
|
ferencd@0
|
295
|
|
ferencd@0
|
296 auto begin() { return mvalue.begin(); }
|
|
ferencd@0
|
297 auto end() { return mvalue.end(); }
|
|
ferencd@0
|
298 std::vector<template_struct>::const_iterator begin() const { return mvalue.begin(); }
|
|
ferencd@0
|
299 std::vector<template_struct>::const_iterator end() const { return mvalue.end(); }
|
|
ferencd@0
|
300
|
|
ferencd@0
|
301 private:
|
|
ferencd@0
|
302 std::string mname = "";
|
|
ferencd@0
|
303 std::vector<template_struct> mvalue = {};
|
|
ferencd@0
|
304 };
|
|
ferencd@0
|
305
|
|
ferencd@0
|
306 namespace op
|
|
ferencd@0
|
307 {
|
|
ferencd@0
|
308 struct is
|
|
ferencd@0
|
309 {
|
|
ferencd@0
|
310 template <typename T>
|
|
ferencd@0
|
311 template_par<T> operator ()(std::string const& vs, T const& v) const
|
|
ferencd@0
|
312 {
|
|
ferencd@0
|
313 return template_par<T>(vs, v);
|
|
ferencd@0
|
314 }
|
|
ferencd@0
|
315
|
|
ferencd@0
|
316 };
|
|
ferencd@0
|
317 }
|
|
ferencd@0
|
318 [[maybe_unused]] static auto is = base::make_named_operator(op::is());
|
|
ferencd@0
|
319
|
|
ferencd@0
|
320 /**
|
|
ferencd@0
|
321 * @brief The templater_base class is the basic class for a templater engine
|
|
ferencd@0
|
322 */
|
|
ferencd@0
|
323 class templater_base
|
|
ferencd@0
|
324 {
|
|
ferencd@0
|
325
|
|
ferencd@0
|
326 public:
|
|
ferencd@0
|
327 virtual ~templater_base() = default;
|
|
ferencd@0
|
328
|
|
ferencd@0
|
329 std::map<std::string, std::string> pairs() const
|
|
ferencd@0
|
330 {
|
|
ferencd@0
|
331 return kps;
|
|
ferencd@0
|
332 }
|
|
ferencd@0
|
333
|
|
ferencd@0
|
334 void add_structure_decl(const std::string& name, const std::string& type)
|
|
ferencd@0
|
335 {
|
|
ferencd@0
|
336 structures[name] = template_struct(name, type);
|
|
ferencd@0
|
337 }
|
|
ferencd@0
|
338
|
|
ferencd@0
|
339 template_struct& get_structure(const std::string& name)
|
|
ferencd@0
|
340 {
|
|
ferencd@0
|
341 return structures[name];
|
|
ferencd@0
|
342 }
|
|
ferencd@0
|
343
|
|
ferencd@0
|
344 void add_parameter(const std::string& name, const std::string& type, bool iterable = false)
|
|
ferencd@0
|
345 {
|
|
ferencd@0
|
346 m_parameters[name] = {name, type, iterable};
|
|
ferencd@0
|
347 }
|
|
ferencd@0
|
348
|
|
ferencd@0
|
349 templater_base& templatize(const template_struct& s);
|
|
ferencd@0
|
350
|
|
ferencd@0
|
351 templater_base& templatize(const template_vector_par& v);
|
|
ferencd@0
|
352
|
|
ferencd@0
|
353 virtual std::string get() = 0;
|
|
ferencd@0
|
354 virtual void do_not_resolve_in_get() = 0;
|
|
ferencd@0
|
355 virtual void do_resolve_in_get() = 0;
|
|
ferencd@0
|
356 virtual std::string name() const = 0;
|
|
ferencd@0
|
357
|
|
ferencd@0
|
358 void skip_whitespace(const std::string &templatized, size_t &i);
|
|
ferencd@0
|
359 std::string extract_identifier_word(const std::string &input, size_t &i, std::vector<char> separators = {},
|
|
ferencd@0
|
360 std::set<char> extra_allowed_chars = {}, char &&c = 0);
|
|
ferencd@0
|
361 bool check_opening_parenthesis(const std::string &input, size_t &i);
|
|
ferencd@0
|
362 bool check_closing_comment(const std::string &templatized, size_t &i, std::size_t &include_tag_end_position);
|
|
ferencd@0
|
363
|
|
ferencd@0
|
364 template <typename... Args>
|
|
ferencd@0
|
365 void set_error(Args&&... args)
|
|
ferencd@0
|
366 {
|
|
ferencd@0
|
367 std::string terr = unafrog::utils::join_string(' ', std::forward<Args>(args)...);
|
|
ferencd@0
|
368 error += unafrog::utils::trim(terr) + "\n";
|
|
ferencd@0
|
369
|
|
ferencd@0
|
370 }
|
|
ferencd@0
|
371
|
|
ferencd@0
|
372 std::string get_error() const;
|
|
ferencd@0
|
373
|
|
ferencd@0
|
374 /**
|
|
ferencd@0
|
375 * @brief variables will return all the variables that can be replaced in the template
|
|
ferencd@0
|
376 * @return
|
|
ferencd@0
|
377 */
|
|
ferencd@0
|
378 std::vector<std::string> variables(bool resolve_includes_too);
|
|
ferencd@0
|
379
|
|
ferencd@0
|
380
|
|
ferencd@0
|
381 protected:
|
|
ferencd@0
|
382
|
|
ferencd@0
|
383 std::string get(const std::string& template_name);
|
|
ferencd@0
|
384 void resolve_all_includes(std::string &templatized, bool do_replace = true);
|
|
ferencd@0
|
385
|
|
ferencd@0
|
386 /**
|
|
ferencd@0
|
387 * @brief resolve_includes Resolves the template including other templates.
|
|
ferencd@0
|
388 *
|
|
ferencd@0
|
389 * The included template name can have parameters too: <!--#include IncludeableTemplate(str="blaa")#-->" meaning
|
|
ferencd@0
|
390 * that when the IncludeableTemplate is included its variables (specified in the list only) are exchhanged to the
|
|
ferencd@0
|
391 * ones with values from the parameters.
|
|
ferencd@0
|
392 *
|
|
ferencd@0
|
393 * @param templatized - the actual content of the template string
|
|
ferencd@0
|
394 * @param inc_pos - the start position
|
|
ferencd@0
|
395 * @param do_variable_replacement - whether wer should replace the variables after including
|
|
ferencd@0
|
396 *
|
|
ferencd@0
|
397 * @return the templated string, where the includes were resolved and eventually the variables were replaced
|
|
ferencd@0
|
398 */
|
|
ferencd@0
|
399 std::string resolve_includes(std::string templatized, size_t inc_pos, bool do_variable_replacement = true);
|
|
ferencd@0
|
400
|
|
ferencd@0
|
401 std::string resolve_structure_declaration(size_t struct_pos, std::string templatized);
|
|
ferencd@0
|
402 std::string resolve_parameters(size_t parameters_pos, std::string templatized);
|
|
ferencd@0
|
403 std::string resolve_ifs(size_t if_pos, std::string templatized);
|
|
ferencd@0
|
404 std::string resolve_ifeq(size_t if_pos, std::string templatized);
|
|
ferencd@0
|
405 std::string resolve_defines(std::string content);
|
|
ferencd@0
|
406 std::string resolve_script(size_t pos, const std::string &content, const std::string& tag);
|
|
ferencd@0
|
407 std::string resolve_scripts(std::string templatized, const std::string& tag);
|
|
ferencd@0
|
408 std::string resolve_loops(std::string templatized, const template_vector_par &v);
|
|
ferencd@0
|
409 std::string resolve_ifeqs(std::string templatized);
|
|
ferencd@0
|
410
|
|
ferencd@0
|
411 /**
|
|
ferencd@0
|
412 * @brief resolve_translations resolves all the translations
|
|
ferencd@0
|
413 * @param templatized
|
|
ferencd@0
|
414 * @param target_language
|
|
ferencd@0
|
415 * @param generate_span - whether to generate HTML spans for the translated elements
|
|
ferencd@0
|
416 * @param translations - a map with the span ID's and their corresponding translations
|
|
ferencd@0
|
417 * @return
|
|
ferencd@0
|
418 */
|
|
ferencd@0
|
419 std::string resolve_translations(std::string templatized, const std::string& target_language, bool generate_span, std::map<std::string, std::map<std::string, std::string> > &translations);
|
|
ferencd@0
|
420
|
|
ferencd@0
|
421 /**
|
|
ferencd@0
|
422 * @brief resolve_translation resolves one translation
|
|
ferencd@0
|
423 * @param if_pos
|
|
ferencd@0
|
424 * @param templatized
|
|
ferencd@0
|
425 * @param target_language
|
|
ferencd@0
|
426 * @param generate_span - whether to generate a span HTML element for this translation
|
|
ferencd@0
|
427 * @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
|
428 * @param translations - a map of translations for this given translation, for each language (key) the corresponding translated text (value)
|
|
ferencd@0
|
429 * @return
|
|
ferencd@0
|
430 */
|
|
ferencd@0
|
431 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<std::string, std::string> &translations);
|
|
ferencd@0
|
432 std::string resolve_dynamic_section(std::string templatized, const template_vector_par &v);
|
|
ferencd@0
|
433
|
|
ferencd@0
|
434 protected:
|
|
ferencd@0
|
435
|
|
ferencd@0
|
436 // the string representation of the key/value pairs of the template that will be worked with
|
|
ferencd@0
|
437 std::map<std::string, std::string> kps;
|
|
ferencd@0
|
438
|
|
ferencd@0
|
439 // the structures that are defined in this template are populated from this map of key/structure paris
|
|
ferencd@0
|
440 std::map<std::string, template_struct> structures;
|
|
ferencd@0
|
441
|
|
ferencd@0
|
442 // the parameters of te template
|
|
ferencd@0
|
443 std::map<std::string, template_special_parameter> m_parameters;
|
|
ferencd@0
|
444
|
|
ferencd@0
|
445 // working data
|
|
ferencd@0
|
446 std::string precalculated = "";
|
|
ferencd@0
|
447 std::string error = "";
|
|
ferencd@0
|
448 };
|
|
ferencd@0
|
449
|
|
ferencd@0
|
450 template<class T>
|
|
ferencd@0
|
451 class templater : public templater_base
|
|
ferencd@0
|
452 {
|
|
ferencd@0
|
453 protected:
|
|
ferencd@0
|
454 bool resolve_in_get = true;
|
|
ferencd@0
|
455 bool external_content_set = false;
|
|
ferencd@0
|
456 std::string external_content = "";
|
|
ferencd@0
|
457 std::map<std::string, std::map<std::string, std::string> > m_translation_map;
|
|
ferencd@0
|
458 public:
|
|
ferencd@0
|
459
|
|
ferencd@0
|
460 const std::map<std::string, std::map<std::string, std::string> >& get_translations()
|
|
ferencd@0
|
461 {
|
|
ferencd@0
|
462 return m_translation_map;
|
|
ferencd@0
|
463 }
|
|
ferencd@0
|
464
|
|
ferencd@0
|
465 templater& templatize()
|
|
ferencd@0
|
466 {
|
|
ferencd@0
|
467 return *this;
|
|
ferencd@0
|
468 }
|
|
ferencd@0
|
469
|
|
ferencd@0
|
470 templater& templatize(const template_vector_par& v)
|
|
ferencd@0
|
471 {
|
|
ferencd@0
|
472 return dynamic_cast<templater&>(templater_base::templatize(v));
|
|
ferencd@0
|
473 }
|
|
ferencd@0
|
474
|
|
ferencd@0
|
475 template <typename T1>
|
|
ferencd@0
|
476 templater& templatize(const template_par<T1>& b)
|
|
ferencd@0
|
477 {
|
|
ferencd@0
|
478 precalculated = "";
|
|
ferencd@0
|
479 kps.insert(make_pair(b.key(), unafrog::utils::to_string(b.value())));
|
|
ferencd@0
|
480
|
|
ferencd@0
|
481 return *this;
|
|
ferencd@0
|
482 }
|
|
ferencd@0
|
483
|
|
ferencd@0
|
484 templater& templatize(const nlohmann::json& j)
|
|
ferencd@0
|
485 {
|
|
ferencd@0
|
486 precalculated = "";
|
|
ferencd@0
|
487 for (const auto& [k, v] : j.items())
|
|
ferencd@0
|
488 {
|
|
ferencd@0
|
489 if(v.is_string())
|
|
ferencd@0
|
490 {
|
|
ferencd@0
|
491 std::string s = unafrog::utils::to_string(v);
|
|
ferencd@0
|
492 remove_quotes(s);
|
|
ferencd@0
|
493 kps.insert(make_pair(unafrog::utils::to_string(k), s));
|
|
ferencd@0
|
494 }
|
|
ferencd@0
|
495 }
|
|
ferencd@0
|
496 return *this;
|
|
ferencd@0
|
497 }
|
|
ferencd@0
|
498
|
|
ferencd@0
|
499 templater& templatize(const template_struct& s)
|
|
ferencd@0
|
500 {
|
|
ferencd@0
|
501 return dynamic_cast<templater&>(templater_base::templatize(s));
|
|
ferencd@0
|
502 }
|
|
ferencd@0
|
503
|
|
ferencd@0
|
504 template<typename... Args1>
|
|
ferencd@0
|
505 templater& templatize(const template_struct& s, Args1... args)
|
|
ferencd@0
|
506 {
|
|
ferencd@0
|
507 precalculated = "";
|
|
ferencd@0
|
508 templatize(s);
|
|
ferencd@0
|
509 return templatize(args...);
|
|
ferencd@0
|
510 }
|
|
ferencd@0
|
511
|
|
ferencd@0
|
512 template<typename... Args1>
|
|
ferencd@0
|
513 templater& templatize(const template_vector_par& v, Args1... args)
|
|
ferencd@0
|
514 {
|
|
ferencd@0
|
515 dynamic_cast<templater&>(templater_base::templatize(v));
|
|
ferencd@0
|
516 return templatize(args...);
|
|
ferencd@0
|
517 }
|
|
ferencd@0
|
518
|
|
ferencd@0
|
519 template<typename T1, typename... Args1>
|
|
ferencd@0
|
520 templater& templatize(const template_par<T1>& first, Args1... args)
|
|
ferencd@0
|
521 {
|
|
ferencd@0
|
522 precalculated = "";
|
|
ferencd@0
|
523 kps.insert(make_pair(first.key(), unafrog::utils::to_string(first.value())));
|
|
ferencd@0
|
524 return templatize(args...);
|
|
ferencd@0
|
525 }
|
|
ferencd@0
|
526
|
|
ferencd@0
|
527 void do_not_resolve_in_get() override
|
|
ferencd@0
|
528 {
|
|
ferencd@0
|
529 resolve_in_get = false;
|
|
ferencd@0
|
530 }
|
|
ferencd@0
|
531 void do_resolve_in_get() override
|
|
ferencd@0
|
532 {
|
|
ferencd@0
|
533 resolve_in_get = true;
|
|
ferencd@0
|
534 }
|
|
ferencd@0
|
535
|
|
ferencd@0
|
536 templater& set(const std::string& ec)
|
|
ferencd@0
|
537 {
|
|
ferencd@0
|
538 external_content = ec;
|
|
ferencd@0
|
539 external_content_set = true;
|
|
ferencd@0
|
540 return *this;
|
|
ferencd@0
|
541 }
|
|
ferencd@0
|
542
|
|
ferencd@0
|
543 std::string get() override
|
|
ferencd@0
|
544 {
|
|
ferencd@0
|
545 if(precalculated.empty())
|
|
ferencd@0
|
546 {
|
|
ferencd@0
|
547 std::string templatized = (external_content_set && external_content.size() > 0) ? external_content : templater_base::get(name());
|
|
ferencd@0
|
548 if(resolve_in_get)
|
|
ferencd@0
|
549 {
|
|
ferencd@0
|
550 templatized = resolve_ifeqs(templatized);
|
|
ferencd@0
|
551 templatized = resolve_scripts(templatized, SCRIPT_TAG);
|
|
ferencd@0
|
552 precalculated = templatized;
|
|
ferencd@0
|
553 }
|
|
ferencd@0
|
554 else
|
|
ferencd@0
|
555 {
|
|
ferencd@0
|
556 precalculated = templatized;
|
|
ferencd@0
|
557 }
|
|
ferencd@0
|
558
|
|
ferencd@0
|
559 if(kps.count("target_language"))
|
|
ferencd@0
|
560 {
|
|
ferencd@0
|
561 precalculated = resolve_translations(precalculated, kps["target_language"], true, m_translation_map);
|
|
ferencd@0
|
562 }
|
|
ferencd@0
|
563
|
|
ferencd@0
|
564 return precalculated;
|
|
ferencd@0
|
565 }
|
|
ferencd@0
|
566 else
|
|
ferencd@0
|
567 {
|
|
ferencd@0
|
568 return precalculated;
|
|
ferencd@0
|
569 }
|
|
ferencd@0
|
570 }
|
|
ferencd@0
|
571
|
|
ferencd@0
|
572 std::string name() const override
|
|
ferencd@0
|
573 {
|
|
ferencd@0
|
574 return T::name();
|
|
ferencd@0
|
575 }
|
|
ferencd@0
|
576
|
|
ferencd@0
|
577
|
|
ferencd@0
|
578 };
|
|
ferencd@0
|
579
|
|
ferencd@0
|
580 template <class T>
|
|
ferencd@0
|
581 std::ostream& operator << (std::ostream& os, const templater<T>& t)
|
|
ferencd@0
|
582 {
|
|
ferencd@0
|
583 os << t.get();
|
|
ferencd@0
|
584 return os;
|
|
ferencd@0
|
585 }
|
|
ferencd@0
|
586
|
|
ferencd@0
|
587
|
|
ferencd@0
|
588 template<class T>
|
|
ferencd@0
|
589 struct translator : public templater<T>
|
|
ferencd@0
|
590 {
|
|
ferencd@0
|
591 translator& templatize()
|
|
ferencd@0
|
592 {
|
|
ferencd@0
|
593 return *this;
|
|
ferencd@0
|
594 }
|
|
ferencd@0
|
595
|
|
ferencd@0
|
596 translator& templatize(const template_vector_par& v)
|
|
ferencd@0
|
597 {
|
|
ferencd@0
|
598 return dynamic_cast<translator&>(templater_base::templatize(v));
|
|
ferencd@0
|
599 }
|
|
ferencd@0
|
600
|
|
ferencd@0
|
601 template <typename T1>
|
|
ferencd@0
|
602 translator& templatize(const template_par<T1>& b)
|
|
ferencd@0
|
603 {
|
|
ferencd@0
|
604 templater<T>::precalculated = "";
|
|
ferencd@0
|
605 templater<T>::kps.insert(make_pair(b.key(), unafrog::utils::to_string(b.value())));
|
|
ferencd@0
|
606
|
|
ferencd@0
|
607 return *this;
|
|
ferencd@0
|
608 }
|
|
ferencd@0
|
609
|
|
ferencd@0
|
610 translator& templatize(const nlohmann::json& j)
|
|
ferencd@0
|
611 {
|
|
ferencd@0
|
612 templater<T>::precalculated = "";
|
|
ferencd@0
|
613 for (const auto& [k, v] : j.items())
|
|
ferencd@0
|
614 {
|
|
ferencd@0
|
615 if(v.is_string())
|
|
ferencd@0
|
616 {
|
|
ferencd@0
|
617 std::string s = unafrog::utils::to_string(v);
|
|
ferencd@0
|
618 remove_quotes(s);
|
|
ferencd@0
|
619 templater<T>::kps.insert(make_pair(unafrog::utils::to_string(k), s));
|
|
ferencd@0
|
620 }
|
|
ferencd@0
|
621 }
|
|
ferencd@0
|
622 return *this;
|
|
ferencd@0
|
623 }
|
|
ferencd@0
|
624
|
|
ferencd@0
|
625 translator& templatize(const template_struct& s)
|
|
ferencd@0
|
626 {
|
|
ferencd@0
|
627 return dynamic_cast<translator&>(templater_base::templatize(s));
|
|
ferencd@0
|
628 }
|
|
ferencd@0
|
629
|
|
ferencd@0
|
630 template<typename... Args1>
|
|
ferencd@0
|
631 translator& templatize(const template_struct& s, Args1... args)
|
|
ferencd@0
|
632 {
|
|
ferencd@0
|
633 templater<T>::precalculated = "";
|
|
ferencd@0
|
634 templatize(s);
|
|
ferencd@0
|
635 return templatize(args...);
|
|
ferencd@0
|
636 }
|
|
ferencd@0
|
637
|
|
ferencd@0
|
638 template<typename T1, typename... Args1>
|
|
ferencd@0
|
639 translator& templatize(const template_par<T1>& first, Args1... args)
|
|
ferencd@0
|
640 {
|
|
ferencd@0
|
641 templater<T>::precalculated = "";
|
|
ferencd@0
|
642 templater<T>::kps.insert(make_pair(first.key(), unafrog::utils::to_string(first.value())));
|
|
ferencd@0
|
643 return templatize(args...);
|
|
ferencd@0
|
644 }
|
|
ferencd@0
|
645
|
|
ferencd@0
|
646 translator& set()
|
|
ferencd@0
|
647 {
|
|
ferencd@0
|
648 templater<T>::get();
|
|
ferencd@0
|
649 templater<T>::external_content = templater<T>::precalculated;
|
|
ferencd@0
|
650 templater<T>::external_content_set = true;
|
|
ferencd@0
|
651 return *this;
|
|
ferencd@0
|
652 }
|
|
ferencd@0
|
653
|
|
ferencd@0
|
654
|
|
ferencd@0
|
655 std::string translate(const std::string& target_language)
|
|
ferencd@0
|
656 {
|
|
ferencd@0
|
657 if(templater<T>::external_content_set && templater<T>::external_content.length() > 0)
|
|
ferencd@0
|
658 {
|
|
ferencd@0
|
659 return translate(templater<T>::external_content, target_language, this->m_translation_map);
|
|
ferencd@0
|
660 }
|
|
ferencd@0
|
661 else
|
|
ferencd@0
|
662 {
|
|
ferencd@0
|
663 std::string s = templater<T>().templatize().get();
|
|
ferencd@0
|
664 return translate(s, target_language, this->m_translation_map);
|
|
ferencd@0
|
665 }
|
|
ferencd@0
|
666 }
|
|
ferencd@0
|
667
|
|
ferencd@0
|
668 static std::string translate(const std::string& in, const std::string& target_language, std::map<std::string, std::map<std::string, std::string> >& translation_map)
|
|
ferencd@0
|
669 {
|
|
ferencd@0
|
670 //TODO mutex
|
|
ferencd@0
|
671 GENERIC_STRING_TEMPLATE(Translateable);
|
|
ferencd@0
|
672 auto t = templater<Translateable>();
|
|
ferencd@0
|
673 std::string res = t.set(in).templatize("target_language" <is> target_language).get();
|
|
ferencd@0
|
674 translation_map = t.get_translations();
|
|
ferencd@0
|
675 return res;
|
|
ferencd@0
|
676 }
|
|
ferencd@0
|
677 };
|
|
ferencd@0
|
678
|
|
ferencd@0
|
679 HTML_TEMPLATE(mainpage);
|
|
ferencd@0
|
680 HTML_TEMPLATE(category_list);
|
|
ferencd@0
|
681 HTML_TEMPLATE(recipe);
|
|
ferencd@0
|
682 HTML_TEMPLATE(footer);
|
|
ferencd@0
|
683 HTML_TEMPLATE(languages);
|
|
ferencd@0
|
684
|
|
ferencd@0
|
685 #endif // TEMPLATER_H
|