1 /*
2     SPDX-FileCopyrightText: 2012 Miha Čančula <miha@noughmad.eu>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #ifndef KDEVPLATFORM_TEMPLATERENDERER_H
8 #define KDEVPLATFORM_TEMPLATERENDERER_H
9 
10 #include <QVariantHash>
11 
12 #include <language/languageexport.h>
13 
14 class QUrl;
15 
16 namespace KDevelop {
17 class SourceFileTemplate;
18 
19 class DocumentChangeSet;
20 class TemplateRendererPrivate;
21 
22 /**
23  * @brief Convenience class for rendering multiple templates with the same context
24  *
25  * The TemplateRenderer provides easy access to common template operations.
26  * Internally, it encapsulates a Grantlee::Engine and a Grantlee::Context.
27  *
28  * It is used by adding a set of variables, and then renderering a template string
29  * @code
30  * TemplateRenderer renderer;
31  * renderer.addVariable("greeting", "Hello");
32  * renderer.addVariable("target", "World");
33  * QString text = renderer.render("{{ greeting }}, {{ target }}!");
34  * // text == "Hello, World!"
35  * @endcode
36  *
37  * If you wish to include other templates using the Grantlee {% include %} tag,
38  * make sure TemplateRenderer can find those template by using
39  * addTemplateDirectories() and addArchive(). This adds everything in the specified
40  * directories or archive files to the list of files search for inclusion.
41  *
42  * Directories named "kdevcodegen/templates" in the "data" resource type are always included in the search path,
43  * there is no need to add them explicitly. Additionally, TemplateRenderer adds the "lib" resource directories
44  * to the Grantlee plugin search path, so plugins installed there will be available to templates.
45  *
46  **/
47 class KDEVPLATFORMLANGUAGE_EXPORT TemplateRenderer
48 {
49 public:
50     /**
51      * Policy for working with empty lines
52      **/
53     enum EmptyLinesPolicy
54     {
55         /**
56          * Keep empty lines as they are in the rendered output.
57          * The output from the template is returned unmodified.
58          */
59         KeepEmptyLines,
60         /**
61          * If the template output has more than one line, the renderer
62          * performs a smart trim on the rendered output.
63          * @li single empty lines are removed
64          * @li two or more consecutive empty lines are compressed into a single empty line
65          * @li a single empty line is kept at the end
66          */
67         TrimEmptyLines,
68         /**
69          * Removes all empty lines from the template output, and appends a newline at the end if needed.
70          */
71         RemoveEmptyLines
72     };
73 
74     TemplateRenderer();
75     virtual ~TemplateRenderer();
76 
77     /**
78      * Adds @p variables to the Grantlee::Context passed to each template.
79      *
80      * If the context already contains a variables with the same name as a key in @p variables,
81      * it is overwritten.
82      *
83      **/
84     void addVariables(const QVariantHash& variables);
85 
86     /**
87      * Adds variable with name @p name and value @p value to the Grantlee::Context passed to each template.
88      *
89      * If the context already contains a variables with the same @p name, it is overwritten.
90      *
91      **/
92     void addVariable(const QString& name, const QVariant& value);
93 
94     /**
95      * Returns the current variables defined for this renderer
96      *
97      * @sa addVariable(), addVariables()
98      */
99     QVariantHash variables() const;
100 
101     /**
102      * @brief Renders a single template
103      *
104      * Any rendering errors are reported by errorString().
105      * If there were no errors, errorString() will return an empty string.
106      *
107      * @param content the template content
108      * @param name (optional) the name of this template
109      * @return the rendered template
110      **/
111     QString render(const QString& content, const QString& name = QString());
112 
113     /**
114      * @brief Renders a single template from a file
115      *
116      * Any rendering errors are reported by errorString().
117      * If there were no errors, errorString() will return an empty string.
118      *
119      * @param url the URL of the file from which to load the template
120      * @param name (optional) the name of this template
121      * @return the rendered template
122      **/
123     QString renderFile(const QUrl& url, const QString& name = QString());
124 
125     /**
126      * @brief Renders a list of templates
127      *
128      * This is a convenience method, suitable if you have to render a large number of templates
129      * with the same context.
130      *
131      * @param contents the template contents
132      * @return the rendered templates
133      **/
134     QStringList render(const QStringList& contents);
135 
136     /**
137      * @brief Sets the policy for empty lines in the rendered output
138      *
139      * The default is KeepEmptyLines, where the template output is return unmodified.
140      *
141      * @param policy policy for empty lines in the rendered output
142      * @sa EmptyLinesPolicy
143      */
144     void setEmptyLinesPolicy(EmptyLinesPolicy policy);
145 
146     /**
147      * Returns the currently set policy for empty lines in the rendered output
148      * @sa EmptyLinesPolicy, setEmptyLinesPolicy()
149      */
150     EmptyLinesPolicy emptyLinesPolicy() const;
151 
152     /**
153      * @brief Renders all templates in the archive represented by @p fileTemplate
154      *
155      * Output files are saved to corresponding URLs in @p fileUrls
156      *
157      * For each output file, TemplateRenderer add two variables named @c output_file_x
158      * and @c output_file_x_absolute, where @c x is replaced
159      * with the file name specified in the template description file.
160      * The variable name is entirely lowercase and cleaned by replacing
161      * all non-alphanumerical characters with underscores.
162      * For example, if the file is named "Public Header" in
163      * the description file, the variable will be @c output_file_public_heder.
164      *
165      * As their name suggests, @c output_file_x contains the relative path from baseUrl() to the URL of the
166      * x's output location, while @c output_file_x_absolute contains x's absolute output URL.
167      * Both are available to templates as strings.
168      *
169      * @param fileTemplate the source file template to render
170      * @param baseUrl the base URL used for calculating relative output file URLs
171      * @param fileUrls maps output file identifiers to desired destination URLs
172      * @return KDevelop::DocumentChangeSet
173      */
174     DocumentChangeSet renderFileTemplate(const KDevelop::SourceFileTemplate& fileTemplate,
175                                          const QUrl& baseUrl, const QHash<QString, QUrl>& fileUrls);
176 
177     /**
178      * Returns the error string from the last call to render(), renderFile() or renderFileTemplate().
179      * If the last render was successful and produced no errors, this function returns an empty string.
180      *
181      * @return the last error string
182      **/
183     QString errorString() const;
184 
185 private:
186     const QScopedPointer<class TemplateRendererPrivate> d_ptr;
187     Q_DECLARE_PRIVATE(TemplateRenderer)
188 };
189 }
190 
191 #endif // KDEVPLATFORM_TEMPLATERENDERER_H
192