1
0
mirror of https://github.com/OlafvdSpek/ctemplate.git synced 2025-09-28 19:05:49 +08:00
ctemplate/doc/example.html
csilvers 71afde04df Thu May 7 11:27:28 2009 Google Inc. <opensource@google.com>
* ctemplate: version 0.94 release
	* Use arena for all memory allocations: 3-4% speedup (csilvers)
	* Add the ability to hook the annotation system (ryoji)
	* Expose Expand(ExpandEmitter*,...) to allow custom emitters (csilvers)
	* Add RemoveStringFromTemplateCache (csilvers)
	* Add new :url_escape_with_arg=css modifier for urls in CSS (jad)
	* Support tr1's unordered_map in preference to hash_map (csilvers)
	* Use Murmurhash for all string hashing, rather than hash<> (csilvers)
	* Better parsing of meta tags and dangling < for auto-escape (falmeida)
	* Add AddXssSafeModifier (jad)
	* Allow disabling auto-escape for 'trusted' vars (jad)
	* BUGFIX: resolve possible memory-leaks in CopyDictionary (csilvers)
	* BUGFIX: fix bug when reloading with AUTOESCAPE pragma (jad)
	* Updated autoconf version to 2.61 and libtool version to 1.5.26
2009-05-07 15:35:04 +00:00

350 lines
12 KiB
HTML

<!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="http://www.google.com/favicon.ico" type="image/x-icon"
rel="shortcut icon">
<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>
<small>(as of 1 September 2006)</small>
<br>
<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>TemplateFromString</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";
Template* tpl = TemplateFromString::GetTemplate("error_msg_tpl", template_text,
DO_NOT_STRIP);
FILE* fp = fopen(argv[1], "r");
if (fp == NULL) {
int err_no = errno; // squirrel this away
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;
tpl->Expand(&error_text, &dict);
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";
Template* tpl = TemplateFromString::GetTemplate("error_msg", template_text,
DO_NOT_STRIP);
FILE* fp = fopen(argv[1], "r");
if (fp == NULL) {
int err_no = errno; // squirrel this away
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;
tpl->Expand(&error_text, &dict);
puts(error_text.c_str());
}
}
</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 google::Template;
using google::TemplateDictionary;
using google::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) {
Template* tpl = Template::GetTemplate(SEARCH_RESULTS_FN, STRIP_WHITESPACE);
TemplateDictionary dict("search-results dict");
string output;
fill_search_results_dictionary(&amp;dict, query);
tpl->Expand(&amp;output, &amp;dict);
// output now holds the expanded template
}
</pre>
<hr>
<ul>
<li> <A HREF="howto.html">Howto</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>
27 February 2006
</address>
</body>
</html>