File: example.html

package info (click to toggle)
ctemplate 2.4-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,352 kB
  • sloc: cpp: 15,200; ansic: 1,058; sh: 592; makefile: 458; python: 205; lisp: 197; perl: 86
file content (345 lines) | stat: -rw-r--r-- 12,144 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Template Examples</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="designstyle.css" type="text/css" rel="stylesheet">
<style type="text/css">
  ol.bluelist li {
    color: #3366ff;
    font-family: sans-serif;
  }
  ol.bluelist li p {
    color: #000;
    font-family: "Times Roman", times, serif;
  }
  ul.blacklist li {  
    color: #000;
    font-family: "Times Roman", times, serif;
  }
</style>
</head>

<body>

<h1>Template Examples</h1>


<h2> Simple Example </h2>

<p>One reason this example is so simple is that it doesn't even
require a separate template file, but instead uses
<code>StringToTemplateCache()</code>.  It also doesn't use sections or
template-includes.</p>

<pre class=example>

int main() {
  static const char template_text[] =
    "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
  ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP);
  FILE* fp = fopen(argv[1], "r");
  if (fp == NULL) {
    int err_no = errno;   // squirrel this away
    ctemplate::TemplateDictionary dict("error_msg: fopen()");
    dict.SetValue("FUNCTION", "fopen");
    dict.SetValue("ARGS", argv[1]);
    dict.SetIntValue("ERROR_CODE", err_no);
    dict.SetValue("ERROR_MESSAGE", strerror(err_no));

    string error_text;
    ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text);
    puts(error_text.c_str());
  }
}

</pre>

Note: If this template was intended to run in a web application, you can 
leverage the functionality provided by the auto-escape mode. Simply add
the AUTOESCAPE pragma directive at the top of the template text and your
variables will be automatically escaped for the context you specify.

For example, if your template is returned in an HTML context,
change the <code>template_text</code> declaration as follows:

<pre class=example>
  static const char template_text[] =
    "{{%AUTOESCAPE context=\"HTML\"}}"
    "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
</pre>

<p>This example is only slightly more complicated: we only print the
": &lt;error message&gt;" part when the error message isn't the empty
string.</p>

<pre class=example>

int main() {
  static const char template_text[] =
     "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}"
     "{{#MSG_SECTION}}: {{ERROR_MESSAGE}}{{/MSG_SECTION}}\n";
  ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP);
  FILE* fp = fopen(argv[1], "r");
  if (fp == NULL) {
    int err_no = errno;   // squirrel this away
    ctemplate::TemplateDictionary dict("file_error_message");
    dict.SetValue("FUNCTION", "fopen");
    dict.SetValue("ARGS", argv[1]);
    dict.SetIntValue("ERROR_CODE", err_no);
    if (err_no > 0)
      dict.SetValueAndShowSection("ERROR_MESSAGE", strerror(err_no),
                                  "MSG_SECTION");

    string error_text;
    ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text);
    puts(error_text.c_str());
  }
  delete tpl;
}

</pre>

<p>This maybe-show-text functionality is one way the template
machinery is more powerful than just using <code>printf</code>.
Another nice property of templates is you can reuse the same variable
multiple times in your template string.  You can also define the
variable values in any order.</p>


<h2> Search Results Page </h2>

<p>Here is an example template that could be used to format a Google
search results page:</p>

<pre class=example>

{{>HEADER}}
&lt;body bgcolor=white>

{{>PAGE_HEADING}}{{!The following div must be on the same line}}&lt;div>

{{!The ONE_RESULT section displays a single search item}}
{{#ONE_RESULT}}
    {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
    {{#SUBITEM_SECTION}}&lt;blockquote>{{/SUBITEM_SECTION}}
    {{! LEAD_LINE is received HTML-escaped from the backend.}}
    &lt;p>&lt;a href="{{JUMP_TO_URL:html_escape}}"  target=nw>{{LEAD_LINE}}&lt;/a>&lt;font size=-1>

    {{! SNIPPET1, SNIPPET2 are HTML-escaped in the snippet generator.}}
    {{#SNIPPET1_SECTION}}
        &lt;br>{{SNIPPET1}}
    {{/SNIPPET1_SECTION}}

    {{#SNIPPET2_SECTION}}
        &lt;br>{{SNIPPET2}}
    {{/SNIPPET2_SECTION}}

    {{#DESCRIPTION_SECTION}}
        {{! DESC is received HTML-escaped from the backend.}}
        &lt;br>&lt;span class=f>Description:&lt;/span> {{DESC}}
    {{/DESCRIPTION_SECTION}}

    {{#CATEGORY_SECTION}}
        &lt;br>&lt;span class=f>Category:&lt;/span> &lt;a href="{{CAT_URL:html_escape}}" class=f>
        {{CATEGORY:html_escape}}&lt;/a>
    {{/CATEGORY_SECTION}}

    {{#LASTLINE_SECTION}}
        &lt;br>&lt;font color="{{ALT_TEXT_COLOR:h}}">{{URL:h}}
        {{#KS_SECTION}}} - {{KSIZE:h}}{{/KS_SECTION}}}
        {{#CACHE_SECTION}}} - &lt;a href="{{CACHE_URL:h}}" class=f>Cached&lt;/A>
        {{/CACHE_SECTION}}}
        {{#SIM_SECTION}}} - &lt;a href="{{SIM_PAGES_URL:h}}" class=f>Similar pages&lt;/A>
        {{/SIM_SECTION}}}

        {{#STOCK_SECTION}}
             -  &lt;a href="{{STOCK_URL:h}}" class=f>Stock quotes: {{STOCK_SYMBOL:h}}&lt;/a>
        {{/STOCK_SECTION}}
        &lt;/font>
    {{/LASTLINE_SECTION}}           

    {{#MORE_SECTION}}
        &lt;br>[ &lt;a href="{{MORE_URL:h}}" class=f>More results from {{MORE_LABEL:h}}&lt;/a> ]
    {{/MORE_SECTION}}

    &lt;/font>&lt;br>
    {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
    {{#SUBITEM_SECTION}}&lt;/blockquote>{{/SUBITEM_SECTION}}
{{/ONE_RESULT}}
&lt;/div> {{! this /div closes the div at the top of this file}}
{{>PAGE_FOOTING}}

</pre>

<p> Here is a sample procedure that could populate a dictionary for
expanding that template. The "one procedure" entry point is
<code>fill_search_results_dictionary</code>.  The
<code>SetTemplateValues</code> function is a separate entry point for
initializing each top-level template with some standard values.</p>

<pre class=example>
#include "template.h"

RegisterTemplateFilename(SEARCH_RESULTS_FN, "search_results.tpl");
#include "search_results.tpl.varnames.h"  // defines ksr_HEADER, etc.

using ctemplate::TemplateDictionary;
using ctemplate::ExpandTemplate;
using ctemplate::STRIP_WHITESPACE;

// IsEmpty
//    A simple utility function
static bool IsEmpty(const string &amp;str) {
  return str.empty();
}

// SetTemplateValues
//   Use the TemplateDictionary object to set template-wide values that
//   may be used in the top-level template and all its sub-sections
//   and included templates. The template-wide values are all
//   colors from the Palette object
void SetTemplateValues(TemplateDictionary *dictionary, const Palette* colors) {
  // better would be to use ksr_LINK_COLOR, etc, assuming those are
  // defined in search_results.tpl.varnames.h.  But using literal
  // text, as here, is legal as well.
  dictionary->SetValue("LINK_COLOR", colors->link_color);
  dictionary->SetValue("BAR_TEXT_COLOR", colors->bar_text_color);
  dictionary->SetValue("TEXT_COLOR", colors->text_color);
  dictionary->SetValue("FAINT_COLOR", colors->faint_color);
  dictionary->SetValue("IMPORTANT_COLOR", colors->important_color);
  dictionary->SetValue("BAR_COLOR", colors->bar_color);
  dictionary->SetValue("ALT_TEXT_COLOR", colors->alt_text_color);
  dictionary->SetValue("ALINK_COLOR", colors->alink_color);
  dictionary->SetValue("VLINK_COLOR", colors->vlink_color);
}

// fill_search_results_dictionary
//   Iterates through all the QueryResults contained in the Query object.
//   For each one, it sets corresponding template dictionary values
//   (or hides sections containing their variables, if appropriate) in
//   a sub-dictionary and then adds that dictionary to the parent
void fill_search_results_dictionary(TemplateDictionary *dictionary,
                                    const Query *query) {
  dictionary->SetFilename(SEARCH_RESULTS_FN);

  // These two functions are defined elsewhere
  fill_header_dictionary(dictionary->AddIncludeDictionary(ksr_HEADER));
  fill_page_heading_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_HEADING),
                               query);

  ResultsList *results = query->GetResults();
  int resCount = 0;

  for (ResultsList::const_iterator iter = results->begin();
       iter != results->end();
       ++iter) {
    QueryResult *qr = (*iter);

    // Create a new sub-dictionary named "Result Dict &lt;n>" for this entry

    ++resCount;

    TemplateDictionary *result_dictionary =
      dictionary->AddSectionDictionary(ksr_ONE_RESULT);

    result_dictionary->SetValue(ksr_JUMP_TO_URL, qr->GetUrl());

    if (qr->IsSubItem()) {
      result_dictionary->ShowSection(ksr_SUBITEM_SECTION);
    }

    result_dictionary->SetValue(ksr_LEAD_LINE, qr->GetLeadLine());

    result_dictionary->SetValueAndShowSection(ksr_SNIPPET1, qr->GetSnippet1(),
                                              ksr_SNIPPET1_SECTION);
    
    result_dictionary->SetValueAndShowSection(ksr_SNIPPET2, qr->GetSnippet2(),
                                              ksr_SNIPPET2_SECTION);
    
    result_dictionary->SetValueAndShowSection(ksr_DESC, qr->GetDescription(),
                                              ksr_DESCRIPTION_SECTION);

    result_dictionary->SetValueAndShowSection(ksr_CAT_URL, qr->GetCategoryUrl(),
                                              ksr_CATEGORY_SECTION);

    result_dictionary->SetValueAndShowSection("CATEGORY", qr->GetCategoryName(),
                                              "CATEGORY_SECTION");


    if (IsEmpty(qr->GetDisplayUrl()) &amp;&amp;
        IsEmpty(qr->GetPageSize()) &amp;&amp;
        IsEmpty(qr->GetCachedUrl()) &amp;&amp;
        IsEmpty(qr->GetSimilarPagesUrl()) &amp;&amp;
        (IsEmpty(qr->GetStockUrl()) ||
         IsEmpty(qr->GetStockSymbol())) ) {
      // there is nothing on the last line, so hide it altogether
    } else {
      result_dictionary->ShowSection("LASTLINE_SECTION");

      result_dictionary->SetValue(ksr_URL, qr->GetDisplayUrl());

      result_dictionary->SetValueAndShowSection(ksr_KSIZE, qr->GetPageSize(),
                                                ksr_KS_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_CACHE_URL, qr->GetCachedUrl(),
                                                ksr_CACHE_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_SIM_PAGES_URL,
                                                qr->GetSimilarPagesUrl(),
                                                ksr_SIM_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_STOCK_URL, qr->GetStockUrl(),
                                                ksr_STOCK_SECTION);

      result_dictionary->SetValueAndShowSection(ksr_STOCK_SYMBOL,
                                                qr->GetStockSymbol(),
                                                ksr_STOCK_SECTION);
    }

    result_dictionary->SetValueAndShowSection(ksr_MORE_URL, qr->GetMoreUrl(),
                                              ksr_MORE_SECTION);

    result_dictionary->SetValueAndShowSection(ksr_MORE_LABEL, qr->GetMoreLabel(),
                                              ksr_MORE_SECTION);

  }    

  fill_page_footing_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_FOOTING),
                               query);
}        

void output_page(const Query* query) {
  TemplateDictionary dict("search-results dict");
  string output;
  fill_search_results_dictionary(&amp;dict, query);
  ctemplate::ExpandTemplate(SEARCH_RESULTS_FN, STRIP_WHITESPACE, &amp;dict, &amp;output);
  // output now holds the expanded template
}

</pre>


<hr>
<ul>
  <li> <A HREF="guide.html">User's Guide</A> </li>
  <li> <A HREF="reference.html">Reference Manual</A> </li>
  <li> <A HREF="auto_escape.html">Auto Escape</A> </li>
  <li> <A HREF="tips.html">Tips</A> </li>
<!--
  <li> <A HREF="example.html">Example</A> </li>
-->
</ul>

<hr>
<address>
Craig Silverstein<br>
<script type=text/javascript>
  var lm = new Date(document.lastModified);
  document.write(lm.toDateString());
</script>
</address>

</body>
</html>