1
0
mirror of https://github.com/OlafvdSpek/ctemplate.git synced 2025-09-28 19:05:49 +08:00

docs/ directory is now called doc/, to keep consistent with the p4 tree

This commit is contained in:
csilvers 2007-03-21 23:25:48 +00:00
parent 4a61bf4e95
commit 1c6d2fd4cb
5 changed files with 0 additions and 1889 deletions

View File

@ -1,119 +0,0 @@
/* This file is duplicated at http://www.corp.google.com/css/designstyle.css
* If you change this file, copy it to ~web/html/css/designstyle.css
*/
body {
background-color: #ffffff;
color: black;
margin-right: 1in;
margin-left: 1in;
}
h1, h2, h3, h4, h5, h6 {
color: #3366ff;
font-family: sans-serif;
}
@media print {
/* Darker version for printing */
h1, h2, h3, h4, h5, h6 {
color: #000080;
font-family: helvetica, sans-serif;
}
}
h1 {
text-align: center;
font-size: 18pt;
}
h2 {
margin-left: -0.5in;
}
h3 {
margin-left: -0.25in;
}
h4 {
margin-left: -0.125in;
}
hr {
margin-left: -1in;
}
/* Definition lists: definition term bold */
dt {
font-weight: bold;
}
address {
text-align: right;
}
/* Use the <code> tag for bits of code and <var> for variables and objects. */
code,pre,samp,var {
color: #006000;
}
/* Use the <file> tag for file and directory paths and names. */
file {
color: #905050;
font-family: monospace;
}
/* Use the <kbd> tag for stuff the user should type. */
kbd {
color: #600000;
}
div.note p {
float: right;
width: 3in;
margin-right: 0%;
padding: 1px;
border: 2px solid #6060a0;
background-color: #fffff0;
}
UL.nobullets {
list-style-type: none;
list-style-image: none;
margin-left: -1em;
}
/*
body:after {
content: "Google Confidential";
}
*/
/* pretty printing styles. See prettify.js */
.str { color: #080; }
.kwd { color: #008; }
.com { color: #800; }
.typ { color: #606; }
.lit { color: #066; }
.pun { color: #660; }
.pln { color: #000; }
.tag { color: #008; }
.atn { color: #606; }
.atv { color: #080; }
pre.prettyprint { padding: 2px; border: 1px solid #888; }
.embsrc { background: #eee; }
@media print {
.str { color: #060; }
.kwd { color: #006; font-weight: bold; }
.com { color: #600; font-style: italic; }
.typ { color: #404; font-weight: bold; }
.lit { color: #044; }
.pun { color: #440; }
.pln { color: #000; }
.tag { color: #006; font-weight: bold; }
.atn { color: #404; }
.atv { color: #060; }
}
/* Table Column Headers */
.hdr {
color: #006;
font-weight: bold;
background-color: #dddddd; }
.hdr2 {
color: #006;
background-color: #eeeeee; }

View File

@ -1,262 +0,0 @@
<!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>
<!--
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 27 February 2006)</small></center>
<br>
<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}}
&lt;p>&lt;a href={{JUMP_TO_URL:html_escape}} target=nw>{{LEAD_LINE}}&lt;/a>&lt;font size=-1>
{{#SNIPPET1_SECTION}}
&lt;br>{{SNIPPET1}}
{{/SNIPPET1_SECTION}}
{{#SNIPPET2_SECTION}}
&lt;br>{{SNIPPET2}}
{{/SNIPPET2_SECTION}}
{{#DESCRIPTION_SECTION}}
&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}}&lt;/a>
{{/CATEGORY_SECTION}}
{{#LASTLINE_SECTION}}
&lt;br>&lt;font color={{ALT_TEXT_COLOR}}>{{URL}}
{{#KS_SECTION}}} - {{KSIZE}}{{/KS_SECTION}}}
{{#CACHE_SECTION}}} - &lt;a href={{CACHE_URL:html_escape}} class=f>Cached&lt;/A>
{{/CACHE_SECTION}}}
{{#SIM_SECTION}}} - &lt;a href={{SIM_PAGES_URL:html_escape}} class=f>Similar pages&lt;/A>
{{/SIM_SECTION}}}
{{#STOCK_SECTION}}
- &lt;a href={{STOCK_URL:html_escape}} class=f>Stock quotes: {{STOCK_SYMBOL}}&lt;/a>
{{/STOCK_SECTION}}
&lt;/font>
{{/LASTLINE_SECTION}}
{{#MORE_SECTION}}
&lt;br>[ &lt;a href={{MORE_URL:html_escape}} class=f>More results from {{MORE_LABEL}}&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 &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 <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()) &&
IsEmpty(qr->GetPageSize()) &&
IsEmpty(qr->GetCachedUrl()) &&
IsEmpty(qr->GetSimilarPagesUrl()) &&
(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(&dict, query);
tpl->Expand(&output, &dict);
// output now holds the expanded template
}
</pre>
<hr>
<ul>
<li> <A HREF="howto.html">Howto</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>

View File

@ -1,946 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>How To Use the Google Template System</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>
<!--
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>How To Use the Google Template System</h1>
<small>(as of 27 February 2006)</small></center>
<br>
<h2> Motivation </h2>
<p>A template system can be used to separate output formatting
specifications, which govern the appearance and location of output
text and data elements, from the executable logic which prepares the
data and makes decisions about what appears in the output.</p>
<p>Template systems lie along a continuum of power versus separation.
"Powerful" constructs like variable assignment or conditional
statements make it easy to modify the look of an application within
the template system exclusively, without having to modify any of the
underlying "application logic". They do so, however, at the cost of
separation, turning the templates themselves into part of the
application logic.</p>
<p>This template system leans strongly towards preserving the
separation of logic and presentation. It is intentionally constrained
in the features it supports and, as a result, applications tend to
require quite a bit of code to instantiate a template. This may not
be to everybody's tastes. However, while this design limits the power
of the template <i>language</i>, it does not limit the power or
flexibility of the template <i>system</i>. This system supports
arbitrarily complex text formatting. Many Google applications,
including the "main" Google web search, use this system exclusively
for formatting output.</p>
<p>Finally, this system is designed with an eye towards efficiency.
Template instantiation is very quick, with an eye towards minimizing
both memory use and memory fragmentation.</p>
<h2> Overview </h2>
<p>There are two parts to the Google Template System:</p>
<ul>
<li> Templates
<li> Data dictionaries
</ul>
<p>The templates are text files that contain the format specification
for the formatted output, i.e, the template language. The data
dictionaries contain the mappings from the template elements (markers)
embedded in the templates to the data that they will format. Here's
a simple template:</p>
<pre>
&lt;html>&lt;head>&lt;title>{{TITLE}}&lt;/title>{{META_TAGS}}&lt;/head>
&lt;body>{{BODY}}&lt;/body></html>
</pre>
<p>Here's a dictionary that one could use to instantiate the template:</p>
<pre>
{"TITLE": "Template example",
"BODY": "This is a simple template example.\nIt's boring",
"DATE": "11/20/2005"}
</pre>
<p>If we instantiated the template with this dictionary, here's the
output we would get:</p>
<pre>
&lt;html>&lt;head>&lt;title>Template example&lt;/title>&lt;/head>
&lt;body>This is a simple template example.
It's boring&lt;/body>&lt;/html>
</pre>
<p><code>{{TITLE}}</code> and <code>{{{BODY}}</code> are <b>template
elements</b>, also called <b>markers</b>. In the dictionary,
<code>TITLE</code>, <code>BODY</code>, and <code>DATE</code> are
<b>dictionary names</b>, and the values associated with each one, such
as <code>11/20/2005</code>, are <b>dictionary values</b>.</p>
<p>A few points are clear even from this simple example:</p>
<ol>
<li> Dictionary keys and values are strings; the Google template
system is not typed. </li>
<li> Dictionary values come already formatted. It was up to the
application code to decide how to format the value for
<code>DATE</code>, and to insert the date into the dictionary
already formatted. </li>
<li> Not all dictionary values must be used by a templete.
<code>DATE</code> is entirely ignored. </li>
<li> Not all template elements may exist in the dictionary. In this
example, <code>{{META_TAGS}}</code> is not found in the
dictionary. This is perfectly legal; missing variable markers
evaluate to the empty string. </li>
</ol>
<h3> Templates </h3>
<p> The template language has four types of markers:</p>
<ol>
<li> VARIABLE markers, which are replaced by text based on
dictionary values. All markers in the above example are
variable markers. Variable markers look like this:
<code>{{VARIABLE}}</code></li>
<li> START SECTION and END SECTION markers, which delimit
sections which may appear zero, one, or N times in
the output. The number of times a section appears is
determined by the data dictionaries, as explained below.
Each time a section is expanded, it uses a different
dictionary, so that the output values may be different from one
iteration of a section expansion to another. Note that the
specification of how sections expand is entirely dependent on
the dictionary, as set up by the application; there is no way
to specify a repeat rate in the template language itself.
Section markers look like this:
<code>{{#SECTION_NAME}}...{{/SECTION_NAME}}</code></li>
<li> TEMPLATE-INCLUDE markers, which designate other templates to be
expanded and inserted at the location where the marker appears.
These are treated much like sections -- one may think of them
as sections whose content is specified in a
different file instead of inline -- and just like sections, can
be expanded zero, one or N times in the output, each with a
different dictionary. Template-include markers look like this:
<code>{{&gt;FILENAME}}</code></li>
<li> COMMENT markers, which may annotate the template
structure but drop completely out of the expanded
output. Comment markers look like this:
<code>{{!&nbsp;comment&nbsp;lives&nbsp;here -- cool, no?}}</code></li>
</ol>
<p>These marker types each have their own namespace. For readability,
however, it is best to not overuse a single name.</p>
<p>Anything found in a template of the form <code>{{...}}</code> is
interpreted as a template marker. All other text is considered
formatting text and is output verbatim at template expansion time.
Formatting text may consist of HTML tags, XML tags, linefeeds and
other spacing characters, constant text, etc.</p>
<h3> Data Dictionaries </h3>
<p>A data dictionary is a map from keys to values. The keys are
always strings, each string representing either a variable, a section,
or a template-include file. (Comments are not stored in the data
dictionary!) These values correspond to the name of the associated
template marker: a section <code>{{#FOO}}</code> in the template text
is matched to the key <code>"FOO"</code> in the dictionary, if it
exists. Note the case must match as well.</p>
<p>The value associated with a key differs according to key type. The
value associated with a <i>variable</i> is simple: it's the value for
that variable. (Niggly implementation note: this value may not have
internal NUL -- that is, \0 -- characters. It's a TODO to allow this
one day.)</p>
<p>The value associated with a <i>section</i> is more complicated, and
somewhat recursive: it's a list of data dictionaries. Come
template-expansion time, the section is expanded once for each
dictionary in the list, so if there are two dictionaries in the list,
then the section text will occur in the output twice. The first time,
all variables/etc. in the section will be evaluated taking into
account the first dictionary. The second time, all
variables/etc. will be evaluated taking into account the second
dictionary. (See <A HREF="#inheritence">below</A> for a definition of
"taking into account.")</p>
<p>A <i>template-include</i> is a special type of section, so the
associated value is the same: a list of dictionaries.
Template-includes also have one other, mandatory associated piece of
information: the filename of the template to include. This filename
may be specified either as an absolute path, or as a relative path.
(In the latter case, the path is taken relative to the
<i>template_root</i>, as <A HREF="#managing">set by the
application</A>.)</p>
<p>The application program is responsible for building this data
dictionary, including all nesting. It then applies this dictionary to
a single template to produce formatted output.</p>
<h3>Expanding a Template</h3>
<p>A program using Google Templates typically reads in templates at
load time. During the course of program execution, the program will
repeatedly perform the following two steps: first, instantiate a data
dictionary, and second, apply the dictionary to the template to
produce output.</p>
<p>The template system applies a dictionary to a template by finding
all template markers in the template, and replacing them with the
appropriate dictionary values. It matches template markers to
dictionary keys in the obvious way. For instance, a template marker
<code>{{FOO}}</code> matches the dictionary key <code>FOO</code>.
<code>{{FOO:html_escape}}</code> matches <code>FOO</code> as well. The
marker <code>{{#BAR}}</code> matches the dictionary key
<code>BAR</code>, as does the marker <code>{{/BAR}}</code>. The
marker <code>{{&gt;BAZ}}</code> matches the dictionary key
<code>BAZ</code>. (And of course, the marker <code>{{!
comment}}</code> doesn't match any dictionary key at all.)</p>
<p>Template-variables can also have <A
HREF="#modifiers">modifiers</A>. In that case, the template-system
starts by finding the appropriate value for that variable in the
dictionary, just like normal. Then it applies each modifier to the
variable, left to right. Finally, it emits the modified value to the
output.</p>
<p>If no dictionary key is found for a given template marker, then the
template marker is ignored: if a variable, it expands to the empty
string; if a section or include-template, the section or
include-template is expanded zero times.</p>
<p>All names are case sensitive. Names -- that is, variable keys and,
as a result, template markers -- must be made of (7-bit ascii)
alphanumeric characters and the underscore. The commment marker,
which does not map to dictionary keys, may contain any chararacters
whatsoever except <code>}</code>, the close-curly brace. It's a
syntax error for any template marker to violate this rule.</p>
<p>Outside of the template markers, templates may contain any text
whatsoever, including (single) curly braces and NUL characters.</p>
<h3><A NAME="modifiers">Variable Modifiers</A></h3>
<p>Recall that variables look like this: <code>{{VARNAME}}</code>. We
actually allow a more generic form: the variable name may be followed
by one or more <b>modifiers</b>. A modifier is a filter that's
applied at template-expand time, that munges the value of the variable
before it's output. For instance, consider a template that looks like
this:</p>
<pre>
&lt;html>&lt;body>{{NAME:html_escape}}&lt;/body>&lt;/html>
</pre>
<p>This asks the template system to apply the built-in
<code>html_escape</code> modifier when expanding
<code>{{NAME}}</code>. If you set <code>NAME</code> in your
dictionary to be <code>Jim &amp; Bob</code>, what will actually be
emitted in the template is <code>Jim &amp;amp; Bob</code>.</p>
<p>You can chain modifiers together. This template first html-escapes
<code>NAME</code>, and then javascript-escapes that result:</p>
<pre>
&lt;html>&lt;body>{{NAME:html_escape:javascript_escape}}&lt;/body>&lt;/html>
</pre>
<p>Modifiers typically have a long, descriptive name and also a
one-letter abbreviation. So this example is equivalent to the
previous one:</p>
<pre>
&lt;html>&lt;body>{{NAME:h:j}}&lt;/body>&lt;/html>
</pre>
<p>Only the modifiers built in to the template system may be used:
It is not possible at the time for users to register modifiers. Here
are the modifiers that are supported:</p>
<table border=1 cellpadding=3>
<tr><th>long name</th><th>short name</th><th>description</th></tr>
<tr><td><code>:html_escape<code></td><td><code>:h</code></td>
<td>html-escapes the variable before output
(eg <code>&amp</code> -> <code>&amp;amp</code>)</td>
</tr>
<tr><td><code>:javascript_escape<code></td><td><code>:j</code></td>
<td>javascript-escapes the variable before output
(eg <code>"</code> -> <code>\"</code>)</td>
</tr>
</table>
<h3> <A NAME="inheritence">Details on Dictionary Lookup</A> </h3>
<p>The dictionary structure is a tree: there's a 'main' dictionary,
and then sub-dictionaries for each section or include-template. Even
with all this complexity, the lookup rules are mostly straightforward:
when looking up a marker -- be it a variable, section, or
include-template marker -- the system looks in the currently
applicable dictionary. If it's found there, great. If not, and the
parent dictionary is not an include-template, it continues the look in
the parent dictionary, and possibly the grandparent, etc. That is,
lookup has <i>static scoping</i>: you look in your dictionary and any
parent dictionary that is associated with the same template-file. As
soon as continuing the lookup would require you to jump to a new
template-file (which is what include-template would do), we stop the
lookup.</p>
<p>For instance, for a template that says
<code>{{#RESULTS}}{{RESULTNUM}}. {{>ONE_RESULT}}{{#RESULTS}}</code>,
<code>"ONE_RESULT"</code> is looked for in the "RESULTS" dictionary,
and if not found there, is looked for in the main, top-level
dictionary. Likewise, the variable <code>"RESULTNUM"</code> is looked
for first in the "RESULTS" dictionary, then in the main dictionary if
necessary. However, "ONE_RESULT" will not do equivalent cascading
lookups. In fact, it will have no parent dictionaries at all, because
it's a different template file and thus in a different scope.</p>
<p>Because of these scoping rules, it's perfectly reasonable to set
all variables that are needed in a given template file, in the
top-level dictionary for that template. In fact, the <code><A
HREF="#sections">ShowSection()</A></code> function is provided to
support just this idiom. To avoid confusion in such a usage mode,
it's strongly encouraged that you give unique names to all sections
and include-templates in a single template file. (It's no problem,
given the template scoping rules, for a single section or
include-template name to be repeated across different template
files.)</p>
<p>There's a single special case: the <b>global variable
dictionary</b>. Every dictionary inherits its initial set of values
from the global dictionary. Clients can <A HREF="#variables">set
variables in the global dictionary</A> just like they can in normal
template dictionaries they create.</p>
<p>The system initializes the global dictionary with a few useful
values for your convenience. All system variables are prefixed with
<code>BI</code>, to emphasize they are "built in" variables.</p>
<ul>
<li> <code>BI_SPACE</code>, which has the value
<code>&lt;space&gt;</code>. It is used to force a space
at the beginning or end of a line in the template,
where it would normally be suppressed. (See below.) </li>
<li><code>BI_NEWLINE</code>, which has the value
<code>&lt;newline&gt;</code> It is used to force a
newline at the end of a line, where it would normally
be suppressed. (See below.) </li>
</ul>
<p>As is usual for inheritence, if a user explicitly assigns a value
to these variable-names in its own dictionary, this overrides the
inherited value. So, <code>dict->SetValue("BI_SPACE",
"&amp;nbsp;")</code> causes <code>BI_SPACE</code> to have the value
<code>&amp;nbsp;</code>, rather than <code>&lt;space&gt;</code>, when
expanding <code>dict</code>.</p>
<p>Note that only variables can be inherited from the global
dictionary, not section dictionaries or include-file dictionaries.</p>
<p>A couple of small implementation notes: global inheritence is "last
chance", so if a section's parent dictionary redefined
<code>BI_SPACE</code>, say, the section dictionary inherits the
parent-dict value, not the global-dict value. Second, variable
inheritence happens at expand time, not at dictionary-create time. So
if you create a section dictionary, and then afterwards set a variable
in its parent dictionary (or in the global dictionary), the section
<i>will</i> inherit that variable value, if it doesn't define the
value itself.</p>
<h2> Writing Application Code To Use Templates </h2>
<p>Most application code concerns filling a template dictionary, but
there is also code for loading templates themselves from disk. A
final category of code lets you inspect and control the template
system.</p>
<p>The code below assumes the default configuration option of putting
all template code in namespace <code>google</code>.
<h3> Loading A Template </h3>
<p>The main routine to load a template is
<code>google::Template::GetTemplate()</code>, defined in
<code>template.h</code>. This is a static, factory method, that loads
a template from either disk or from an internal template cache, and
returns a pointer to a <code>Template</code> object. Besides a
filename to load from, this routine takes a 'strip' argument which
defines how to expand whitespace found in a template file. It can
have one of the following values:</p>
<ul>
<li> <code>google::DO_NOT_STRIP</code>: do nothing. This expands the
template file verbatim.
<li> <code>google::STRIP_BLANK_LINES</code>: remove all blank
lines when expanding. This ignores any blank lines found in
the template file when expanding. When the template is html,
this reduces the size of the output text without requiring a
sacrifice of readability for the input file.
<li> <code>google::STRIP_WHITESPACE</code>: remove not only blank lines when
expanding, but also whitespace at the beginning and end of each
line. It also removes any linefeed (possibly following
whitespace) that follows a closing '}}' of any kind of template
marker <i>except</i> a template variable. (This means a
linefeed may be removed anywhere by simply placing a comment
marker as the last element on the line.) When the template is
html, this reduces the size of the output html without changing
the way it renders (except in a few special cases). When using
this flag, the built-in template variables
<code>BI_NEWLINE</code> and <code>BI_SPACE</code> can be useful
to force a space or newline in a particular situation.
</ul>
<p>This factory method returns NULL if the template cannot be found,
or if there is a syntax error trying to load it.</p>
<p>Besides loading templates, the application can also ask the
template system to <i>reload</i> a template, via
<code>template->ReloadIfChanged()</code>. (You can also reload all
templates at once via <code>google::Template::ReloadAllIfChanged()</code>.)
<code>ReloadIfChanged()</code> looks on disk, and if it notices the
template file has changed since the last load, it will reload the
template from disk, replacing the old contents. Actually, the reload
is done lazily: <code>ReloadIfChanged</code> just sets a bit that
causes the template to be reloaded next time <code>GetTemplate</code>
is called.</p>
<h3> Creating A Template Dictionary </h3>
<p>The class <code>google::TemplateDictionary</code> is used for all template
dictionary operations. <code>new google::TemplateDictionary(name)</code> is
used to create a new top-level dictionary.
<code>dict->AddSectionDictionary(name)</code> and
<code>dict->AddIncludeDictionary(name)</code> are used to create
sub-dictionaries for sections or include-files. After
creating a dictionary, the application should call one or more
functions for each marker in the template. As an example, consider
the following template:
<pre>
&lt;html>&lt;body> {{! This page has no head section.}}
{{#CHANGE_USER}}
&lt;A HREF="/login">Click here&lt;/A> if you are not {{USERNAME}}&lt;br>
{{/CHANGE_USER}}
Last five searches:&lt;ol>
{{#PREV_SEARCHES}
&lt;li> {{PREV_SEARCH}}
{{/PREV_SEARCH}}
&lt;/ol>
{{>RESULT_TEMPLATE}}
{{FOOTER}}
&lt;/body>&lt;/html>
</pre>
<p>To instantiate the template, the user should call a function to set
up <code>FOOTER</code>, and a function to say what to do for the
sections <code>CHANGE_USER</code> and <code>PREV_SEARCHES</code>, and
for the include-template <code>RESULT_TEMPLATE</code>. Quite likely,
the application will also want to create a sub-dictionary for
<code>CHANGE_USER</code>, and in that sub-dictionary call a function
to set up <code>USERNAME</code>. There will also be sub-dictionaries
for <code>PREV_SEARCHES</code>, each of which will need to set
<code>PREV_SEARCH</code>. Only when this is all set up will the
application be able to apply the dictionary to the template to get
output.</p>
<p>The appropriate function to call for a given template marker
depends on its type.</p>
<h4> <A NAME="variables">Variables</A> </h4>
<p>For variables, the only interesting action is to set the variable's
value. For most variables, the right method to call is
<code>dict->SetValue(name, value)</code>. (The name and value
can be specified as strings in a variety of ways: C++ strings, char
*'s, or char *'s plus length.) You can also call
<code>google::TemplateDictionary::SetGlobalValue(name, value)</code> -- no
<code>TemplateDictionary</code> instance needed here -- to set a
variable that can be used by all templates in an applications. This is
quite rare.</p>
<p>In addition to <code>SetValue()</code>, there are a few helper
routines to help setting values of a few special forms.</p>
<ul>
<li> <code>SetIntValue(name, int)</code>: takes an int as the value. </li>
<li> <code>SetEscapedValue(name, value, escape_functor)</code>:
escapes the value, using the escape-functor, which takes a
string as input and gives a "munged" string as output.
<code>TemplateDictionary</code> has a few escape-functors built
in, including <code>html_escape</code>, which replaces
<code>&lt;</code>, <code>&gt;</code>, <code>&amp;</code>, and
<code>"</code> with the appropriate html entity;
<code>xml_escape</code>, which deals with the
<code>&amp;nbsp;</code> entity; and
<code>javascript_escape</code>, which escapes quotes and other
characters that are meaningful to javascript. These are
helpful in avoiding security holes when the template is
html/xml/javascript. You can also define your own functor; see
the example below. </li>
<li> <code>SetFormattedValue(name, fmt, ...)</code>: the
<code>fmt</code> and <code>...</code> work just like in
<code>printf</code>: <code>SetFormattedValue("HOMEPAGE",
"http://%s/", hostname)</code>. </li>
<li> <code>SetEscapedFormattedValue(name, escape_functor, fmt,
...)</code>: formats the value just like <code>printf</code>,
and then escapes the result using the given functor. </li>
</ul>
<p>Example:</p>
<pre>
google::TemplateDictionary* dict = new google::TemplateDictionary("var example");
dict->SetValue("FOOTER", "Aren't these great results?");
class StarEscape { string operator()(const string& in) const { return string("*") + in + string("*"); } };
dict->SetEscapedValue("USERNAME", username, StarEscape());
</pre>
<p>Note that the template itself can also specify escaping via <A
HREF="#modifiers">variable modifiers</A>! It's very possible for you
to escape the value when setting it in the dictionary, and then have
the template escape it again when outputting, so be careful you escape
only as much as you need to.</p>
<h4> <A NAME="sections">Sections</A> </h4>
<p>Sections are used in two ways in templates. One is to expand some
text multiple times. This is how <code>PREV_SEARCHES</code> is used
in the example above. In this case we'll have one small
sub-dictionary for each of the five previous searches the user did.
To do this, call <code>AddSectionDictionary(section_name)</code>
to create the sub-dictionary. It returns a
<code>TemplateDictionary*</code> that you can use to fill the
sub-dictionary.
<p>The other use of sections is to conditionally show or hide a block
of text at template-expand time. This is how <code>CHANGE_USER</code>
is used in the example template: if the user is logged in, we show the
section with the user's username, otherwise we choose not to show the
section.</p>
<p>This second case is a special case of the first, and the "standard"
way to show a section is to expand it exactly one time, by calling
<code>AddSectionDictionary()</code> once, and then setting
<code>USERNAME</code> in the sub-dictionary.</p>
<p>However, the hide/show idiom is so common there are a few
convenience methods to make it simpler. The first takes advantage of
the fact sections inherit variables from their parent: you set
<code>USERNAME</code> in the parent dictionary, rather than a section
sub-dictionary, and then call <code>ShowSection()</code>, which adds a
single, empty dictionary for that section. This causes the section to
be shown once, and to inherit <i>all</i> its variable values from its
parent.</p>
<p>A second convenience method is written for the particular case we
have with <code>USERNAME</code>: if the user's username is non-empty,
we wish to
show the section with <code>USERNAME</code> set to the username,
otherwise we wish to hide the section and show neither
<code>USERNAME</code> nor the text around it. The method
<code>SetValueAndShowSection(name, value, section_name)</code> does
exactly that: if value is non-empty, add a single single dictionary to
<code>section_name</code> and call <code>section_dict->AddValue(name,
value)</code>. There's also <code>SetEscapedValueAndShowSection(name,
value, escape_functor, section_name)</code>, which lets you escape
<code>value</code>.</p>
<p>Example:</p>
<pre>
using google::TemplateDictionary;
TemplateDictionary* dict = new TemplateDictionary("section example");
const char* username = GetUsername(); // returns "" for no user
if (username[0] != '\0') {
TemplateDictionary* sub_dict = dict->AddSectionDictionary("CHANGE_USER");
sub_dict->SetValue("USERNAME", username);
} else {
// don't need to do anything; we want a hidden section, which is the default
}
// Instead of the above 'if' statement, we could have done this:
if (username[0] != '\0') {
dict->ShowSection("CHANGE_USER"); // adds a single, empty dictionary
dict->SetValue("USERNAME", username); // take advantage of inheritence
} else {
// don't need to do anything; we want a hidden section, which is the default
}
// Or we could have done this:
dict->SetValueAndShowSection("USERNAME", username, "CHANGE_USER");
// Moving on...
GetPrevSearches(prev_searches, &num_prev_searches);
if (num_prev_searches > 0) {
for (int i = 0; i < num_prev_searches; ++i) {
TemplateDictionary* sub_dict = dict->AddSectionDictionary("CHANGE_USER");
sub_dict->SetEscapedValue("PREV_SEARCH", prev_searches[i],
TemplateDictionary::html_escape);
}
}
</pre>
<h4> Template-includes </h4>
<p>Template-include markers are much like section markers, so
<code>SetIncludeDictionary(name)</code> acts, not surprisingly,
exactly like <code>SetSectionDictionary(name)</code>. However, since
variable inheritence doesn't work across include boundaries, there is
no template-include equivalent to <code>ShowSection()</code> or
<code>SetValueAndShowSection()</code>.<p>
<p>One difference bewteen template-includes and sections is that for a
sub-dictionary that you create via
<code>SetIncludeDictionary()</code>, you <i>must</i> call
<code>subdict->SetFilename()</code> to indicate the name of the
template to include. If you do not set this, the sub-dictionary will
be ignored. The filename may be absolute, or relative, in which case
it's relative to <A HREF="#managing">template_root</A>.</p>
<p>Example:</p>
<pre>
using google::TemplateDictionary;
TemplateDictionary* dict = new TemplateDictionary("include example");
GetResults(results, &num_results);
for (int i = 0; i < num_results; ++i) {
TemplateDictionary* sub_dict = dict->AddIncludeDictionary("RESULT_TEMPLATE");
sub_dict->SetFilename("results.tpl");
FillResultsTemplate(sub_dict, results[i]);
}
</pre>
<p>In practice, it's much more likely that
<code>FillResultsTemplate()</code> will be the one to call
<code>SetFilename()</code>. Note that it's not an error to call
<code>SetFilename()</code> on a dictionary even if the dictionary is
not being used for a template-include; in that case, the function is a
no-op, but is perhaps still useful as self-documenting code.</p>
<h3> <A name="expand">Expanding a Template</A> </h3>
<p>Once you have a template and a template dictionary, it's simplicity
itself to expand the template with those dictionary values, putting
the output in a string:</p>
<pre>
google::Template* tpl = google::Template::GetTemplate(&lt;filename&gt;, google::STRIP_WHITESPACE);
google::TemplateDictionary dict("debug-name");
FillDictionary(&dict, ...);
string output;
<font color=red>tpl->Expand(&output, &dict);</font>
// output now holds the expanded template
</pre>
<p>The expanded template is written to the string <code>output</code>.
If <code>output</code> was not empty before calling
<code>Expand()</code>, the expanded template is appended to the end of
<code>output</code>.
<h3> Getting a Template From a String Rather Than a File </h3>
<p>The <code>TemplateFromString</code> class, in
<code>template_from_string.h</code>, is an alternative to the
<code>Template</code> class when you really want your template to be
built in to the executable rather than read from a file. It's a
drop-in replacement, that takes an extra argument which is the
template contents.</p>
<p>Prefer <code>Template</code> to <code>TemplateFromString</code>,
for several reasons. For one, updating the template requires merely a
data push, rather than pushing the new executable. Also, you can load
the new template without needing to restart the binary. It also makes
it easier for non-programmers to modify the template. Finally,
string-templates cannot be included by other
templates, since <code>{{>include}}</code> takes a filename.</p>
<p>One reason to use <code>TemplateFromString</code> is if you are in
an environment where having data files could be dangerous -- for
instance, you work on a disk that is usually full, or need the
template to work even in the face of disk I/O errors.</p>
<p>This package comes with a script, <A
HREF="#converter">template-converter</A>, that takes a template file
as input and emits a C++ code snippet (an .h file) that defines a
string with those template contents. This makes it easy to start by
using a normal, file-based template, and then switch to
template-from-string later if you so desire.</p>
<h2> Working Effectively with Templates </h2>
<h3> <A name="register">Registering Template Strings</A> </h3>
<p>Both dictionary keys and template filenames are strings. Instead
of using raw strings, we encourage you to use a bit of machinery to
help protect against various types of errors.</p>
<p>For dictionary keys, you can use the <A
HREF="#make_tpl_varnames_h">make_tpl_varnames_h</A> tool to create
static string variables to use instead of a string constant. This
will protect against typos, as the <A
HREF="#make_tpl_varnames_h">make_tpl_varnames_h</A> documentation
describes.</p>
<p>For template filenames that a program uses -- including
sub-templates -- we suggest the following idiom:</p>
<pre>
#include "example.tpl.varnames.h" // defines 1 string per dictionary key
RegisterTemplateFilename(EXAMPLE_FN, "example.tpl"); // defines template
...
google::Template* tpl = google::Template::GetTemplate(EXAMPLE_FN, ...);
...
include_dict->SetFilename(EXAMPLE_FN);
</pre>
<p>By registering the filename, you can <A HREF="#managing">query</A>
the template system to detect syntax errors, reload-status, and so
forth.</p>
<h3> <A NAME="managing">Managing Templates</A> </h3>
<p>The following functions affect the global state of the template
system.</p>
<ul>
<li> <code>google::Template::SetTemplateRootDirectory(root)</code>: when
<code>GetTemplate()</code> is called with a relative filename,
the template system will try to load the template from
<code>root/file</code>. This defaults to <code>./</code>. </li>
</ul>
<p>There are some administrative tools that can help with tweaking
template performance and debugging template problems. The following
functions work on <A HREF="#register">registered</A> templates.</p>
<ul>
<li> <code>google::TemplateNameList::GetMissingList()</code>: returns a list
of all registered templates where the file could not be found
on disk. </li>
<li> <code>google::TemplateNameList::AllDoExist()</code>: true iff the
missing-list is empty. </li>
<li> <code>google::TemplateNameList::GetBadSyntaxList()</code>: returns a
list of all registered templates where the template contains a
syntax error, and thus cannot be used. </li>
<li> <code>google::TemplateNameList::IsAllSyntaxOkay()</code>: true iff the
bad-syntax list is emtpy. </li>
<li> <code>google::TemplateNameList::GetLastmodTime()</code>: the latest
last-modified time for any registered template-file. </li>
</ul>
<p>The following functions help with debugging, by allowing you to
examine the template dictionaries and expanded templates in
more detail.</p>
<ul>
<li> <code>dict->Dump()</code>: dumps the contents of the dictionary
(and any sub-dictionaries) to stderr. </li>
<li> <code>dict->DumpToString()</code>: dumps the contents of the
dictionary (and sub-dictionaries) to the given string. </li>
<li> <code>dict->SetAnnotateOutput()</code>: when applying this
dictionary to a template, add marker-strings to the output to
indicate what template-substitutions the system was making.
This takes a string argument which can be used to shorten the
filenames printed in the annotations: any filename that starts
with the string you give, that string is elided from the
filename before printing. It's confusing, but fear not: it's
safe to just always pass in the empty string. </li>
</ul>
<p>Finally, <code>ClearCache()</code> removes all template objects
from the cache used by <code>GetTemplate()</code>. Typically, this is
only used in environments that check for memory leaks: calling this at
the end of the program will clean up all memory that the template
system uses.</p>
<h3> Template and Threads </h3>
<p>All static methods on <code>Template</code> and
<code>TemplateDictionary</code> objects are threadsafe: you can safely
call <code>google::TemplateDictionary::SetGlobalValue()</code> without needing
to worry about locking.</p>
<p>Non-static methods are not thread-safe. It is not safe for two
threads to assign values to the same template-dictionary without doing
their own locking. Note that this is expected to be quite rare:
usually only one thread will care about a given
template-dictionary.</p>
<p>For <code>Template</code> objects, the most common idiom is that a
template is loaded via <code>GetTemplate()</code>, and after that only
const methods like <code>Expand()</code> are called on the template.
With such usage, it's safe to use the same <code>Template</code>
object in multiple threads without locking. Be careful, however, if
you also call functions like <code>ReloadIfChanged()</code>.</p>
<h2> Development Tools </h2>
<p>This package includes several tools to make it easier to use write
and use templates.</p>
<h3> <A name="make_tpl_varnames_h">make_tpl_varnames_h:
Template Syntax Checker and Header File Generator</A> </h3>
<p><code>make_tpl_varnames_h</code> is a "lint" style syntax checker
and header file generator. It takes the names of template files as
command line arguments and loads each file into a Template object by
retrieving the file via the Template factory method. The loading of
the file does pure syntax checking and reports such errors as
mis-matched section start/end markers, mis-matched open/close
double-curly braces, such as <code>"{{VAR}"</code>, or invalid characters
in template variables/names/comments.</p>
<p>If the template passes the syntax check, by default the utility
then creates a header file for use in the executable code that fills
the dictionary for the template. If the developer includes this
header file, then constants in the header file may be referenced in
the dictionary building function, rather than hard-coding strings as
variable and section names. By using these constants, the compiler
can notify the developer of spelling errors and mismatched names.
Here's an example of how this is used, and how it helps prevent
errors:</p>
<pre>
const char * const kosr_RESULT_NUMBER = "RESULT_NUMBER"; // script output
dict.SetValue("RESSULT_NUMBER", "4"); // typo is silently missed
dict.SetValue(kosr_RESSULT_NUMBER, "4"); // compiler catches typo
</pre>
<p>Each constant is named as follows:</p>
<ul>
<li> The initial letter 'k', indicating a defined constant. </li>
<li> One or more prefix letters which are derived from the
template file name. These prefix letters consist of the first
letter of the file name, followed by the first letter following
each underscore in the name, with the exception of the letter
'p' when it is followed by the letters "ost", as is a <A
HREF="tips.html#versioning">recommended convention</A> for
template versioning. For example, the prefix letters for the
file <code>one_search_result_post20020815.tpl</code> are
<code>osr</code>. </li>
<li> An underscore. </li>
<li> The varible or section name itself, same casing. </li>
</ul>
<p>As an example, the section name "RESULT_NUMBER" in the file
one_search_result_post20020815.tpl would be given the constant name
<code>kosr_RESULT_NUMBER</code> and would appear in the header file as
<code>const char * const kosr_RESULT_NUMBER = "RESULT_NUMBER";</code>
-- as in the example above.</p>
<p>By default, the header file is produced in the current directory.
An alternate output directory may be specified
by the command line flag <code>--header_dir</code>.
<p>The name of the generated header file is the same as the name of
the template file with an extension added to the name. By default,
that extension is <code>.varnames.h</code>. In the above example, the
header file containing the constant declarations would be named
<code>one_search_result_post20020815.tpl.varnames.h</code>. An
alternate extension may be provided via the command line flag
<code>--outputfile_suffix</code>.
<p>Important command line flags:</p>
<ul>
<li> <code>--noheader</code> -- Indicates that a header file
should not be generated; only syntax checking should be done. </li>
<li> <code>--header_dir</code> -- sets the directory where the header
is written. Default: "./" </li>
<li> <code>--template_dir</code> -- sets the template root
directory. Default: <code>./</code> which is the correct
specification when it is run from the directory where the templates
are located. This is only used if the input template filenames
are specified as relative paths rather than absolute
paths. </li>
<li> <code>--outputfile_suffix</code> -- the extension added to the
name of the template file to create the name of the generated
header file. Default: <code>.varnames.h</code>.
</ul>
<p>For a full list of command line flags, run
<code>make_tpl_varnames_h --help</code>.</p>
<h3> <A name="converter">template-converter: convert a template to a C++ string</A> </h3>
<p>The <code>TemplateFromString</code> class lets you load a template
from a string instead of a file. Applications may prefer this option
to reduce the dependencies of the executable, or use it in
environments where data files are not practical. In such cases,
<code>template-converter</code> can be used as a template "compiler",
letting the developer write a template file as a data file in the
normal way, and then "compiling" it to a C++ string to be included in
the executable.</p>
<p>Usage is <code>template-converter &lt;template filename&gt;</code>.
C++ code is output is to stdout; it can be stored in a .h file or
included directly into a C++ file. Perl must be installed to use this
script.<p>
<hr>
<ul>
<!--
<li> <A HREF="howto.html">Howto</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>

View File

@ -1,94 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Google Template System</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>
<!--
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> <a name="Google_Template_System"></a>Google Template System </h1>
<center><strong>Status: Current</strong> &nbsp;
<small>(as of 16 February 2006)</small></center>
<br>
Welcome to the Google C++ template system! As a quick start, here's a
small but complete program that uses this template library. For more
details see, the links below.
<h3>Template file <code>example.tpl</code></h3>
<pre>
Hello {{NAME}},
You have just won ${{VALUE}}!
{{#IN_CA}}Well, ${{TAXED_VALUE}}, after taxes.{{/IN_CA}}
</pre>
<h3>C++ program <code>example.cc</code></h3>
<pre>
#include &lt;stdlib.h>
#include &lt;string>
#include &lt;iostream>
#include &lt;google/template.h>
int main(int argc, char** argv) {
google::TemplateDictionary dict("example");
dict.SetValue("NAME", "John Smith");
int winnings = random() % 100000;
dict.SetIntValue("VALUE", winnings);
dict.SetFormattedValue("TAXED_VALUE", "%.2f", winnings * 0.83);
// For now, assume everyone lives in CA.
// (Try running the program with a 0 here instead!)
if (1) {
dict.ShowSection("IN_CA");
}
google::Template* tpl = google::Template::GetTemplate("example.tpl",
google::DO_NOT_STRIP);
std::string output;
tpl->Expand(&output, &dict);
std::cout &lt;&lt; output;
return 0;
}
</pre>
<h2>In-depth Documentation</h2>
<ol>
<li> <A HREF="howto.html">Howto</A>: Introduction to the Google
Template system, and a tutorial for using it. </li>
<li> <A HREF="tips.html">Tips</A>: Advice, tips, and recommendations
for best practices with templates, to make them easier to write
and maintain, and to avoid common template mistakes. </li>
<li> <A HREF="example.html">Examples</A>: Some example templates and
application code that uses them. These are taken from actual
Google applications. </li>
</ol>
<hr>
<address>
Craig Silverstein<br>
Last modified: Wed Feb 15 23:21:42 PST 2006
</address>
</body>
</html>

View File

@ -1,468 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Tips and Guidelines for Using the Google Template System</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>
<!--
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>Tips and Guidelines for Using the Google Template System</h1>
<small>(as of 27 February 2006)</small></center>
<br>
<p>The <A HREF="howto.html">basic rules</A> of the template system are
enough to use it, but over time, we at Google have developed some
tips, guidelines, and best practices that make it easier to use
templates effectively, and to avoid common template errors.</p>
<h2> Program Design Considerations </h2>
<h3> <a name=versioning>Template naming and versioning</a> </h3>
<p> Early in Google's use of templates, we noticed a problem: if a
binary that uses a template and its corresponding template were both
modified, particularly if the change were such that the old binary
could not work with the new template or the new binary cannot work
with the old template, then somehow they both had to be deployed at
the same instant to not present errors to our users. This was hard to
do. The solution was to adopt a template naming and versioning
convention. The procedure to use it follows:</p>
<ul>
<li> Each template name ends with <code>_postYYYYMMDD.tpl</code>,
where YYYMMDD is the date of this version's initial
creation. </li>
<li> Before making (non-backward-compatible) modifications to a
template, copy the template to a new name, incorporating a
later date than the original one being copied. </li>
<li> Edit the new file, and push it to the production server. </li>
<li> Finally, update the code to refer to the new template-name
(ideally, using the <A
HREF="howto.html#register"><code>RegisterTemplateFilename</code>
idiom</A>), and push the new executable to the production
server. </li>
</ul>
<p>When this convention is followed, the new template file does not
overwrite the old one when it is deployed, because it is a new file
with a new name. The old template file is still there to be used as
long as the old binary is still in production and the new template
file just sits there being ignored. Then when the new binary finally
gets deployed, it immediately starts using the new template file,
because it is coded (in <code>RegisterTemplateFilename</code>) to do
so. After that, it is the old template file that continues to sit
there ignored.</p>
<p>The <A
HREF="howto.html#make_tpl_varnames_h"><code>make_tpl_varnames_h</code>
utility</A> knows about the "_postYYYYMMDD" naming convention, so it
is important that you use that convention exactly if you use the
<code>make_tpl_varnames_h</code>.</p>
<h3> Processing Phases </h3>
<p>Typically a program using the Google Template System will
perform the following phases, usually in this order:</p>
<ol>
<li> Retrieve and prepare the data used to fill a dictionary. </li>
<li> Build the data dictionary, including all its
sub-dictionaries, that will supply the values to the
designated template object, its sections, and its
included templates. </li>
<li> Retrieve the top-level template object required to
format the data. (This may or may
not involve reading and parsing a template file,
depending on whether the requested file has already
been read and parsed by the running program or
whether that file has been marked "reload if changed"
and was in fact changed.) </li>
<li> Expand the template object into an output buffer
using the completed data dictionary. </li>
<li> Output the buffer. </li>
<li> Clean up: Destroy the top-level data dictionary
whenever it is no longer needed. </li>
<li> Optionally, clear the cache at the end of program
execution. </li>
</ol>
<h3> <A NAME="oneone">One template / One procedure call</A> </h3>
<p> Most of the code of the program will be in Phases 1 and
2. Clearly, Phase 1 is outside the scope of the template system. But
in designing the code for Phase 2 (building the data dictionary), it
is wise to have the structure of the program reflect the structure of
the templates being used. Specifically, there should be a single
procedure call to build the dictionary for a single template. That
procedure call should take parameters that include all the data
required to populate the data dictionary for that template and all the
templates it includes. Following this "one template/one procedure
call" guideline further, for each included template, another procedure
should be called to populate the (or <i>each</i>) data dictionary for
that included template. This maintains the "one template/one procedure
call" principle in a nested fashion that reflects the nesting of the
templates.</p>
<p> This is not to imply that the "one procedure call" for a template
should not be modularized into sub-procedures for readability and
maintainability, or that it should not call other auxilliary
procedures for such things as formatting the data and converting it to
the appropriate strings, etc. But it does mean that there should be
one entry point for building the dictionary tree for one template and
that entry point should show the data dependencies of that template
through its parameter list. This code for populating the data
dictionary should <i>NOT</i> be intermingled with data gathering code
that should have been done in Phase 1.</p>
<p>(Inside Google, the convention has been used to name the dictionary
building procedure using the pattern <code>fill_..._dictionary</code>
where the dots are related to the name of the template the data is
being prepared for. For instance, the data for the template named
one_search_result.tpl might be placed in a dictionary via a function
named <code>fill_one_search_result_dictionary</code>.)
<h2> <A name=tips>Tips, Idioms, and Conventions</a> </h2>
<ol class=bluelist>
<li> Choose template names to create unique constant prefixes.
<p>Template names should contain <em>at least two words</em>
to avoid constant prefix clashes (e.g. <code>kxy_</code>
instead of <code>kx_</code> ) The name of a new template
should be checked against the existing names before
proceeding. If your new template name produces a prefix that
conflicts with an already existing template, you should change
the name of your new template, even though it may be the only
perfect name you can come up with. You'll have to use a less
than perfect name in that case. (See "Template Syntax Checker
and Header File Generator" below for more explanation about
constant prefixes.)</p> </li>
<li> Use SetFormattedValue discriminately.
<p> This method should never be used to sneak HTML into the
executable as in</p>
<pre>
dictionary->SetFormattedValue(kxy_VAR,
"&lt;b&gt;%s&lt;/b&gt;",
some_const_char_string);
</pre>
<p>In that case, the <code>&lt;b&gt;</code> and
<code>&lt;/b&gt;</code> should be moved into the template.</p>
<li> Never have a section encompass an entire template.
<p>If the first line of a template is a start section marker
and the last line is its matching end section marker, then
those markers are unnecessary in almost all cases. They are
usually put there to allow the entire template to be hidden or
iterated, but since it encompasses the entire file, the
section may be hidden by not expanding the file (or by hiding
the template-include section that includes the file) and it
may be iterated by iterating the template-include marker of
the including template. (The only exception might be if the
entire page is to be iterated, but this seems a bit of a
stretch.)</p> </li>
<li> An included template is just a section whose contents are
located in a separate file. You may iterate over it just
like you do sections.
<p>For example, if your template has the following
template-include marker:</p>
<pre>
{{>MY_INCLUDED_TEMPLATE}}
</pre>
<p>you may call</p>
<pre>
google::TemplateDictionary *child_dict =
dictionary->AddIncludeDictionary(kxy_MY_INCLUDED_TEMPLATE);
</pre>
<p>to iterate that section. (Note: Make sure you call
<code>child_dict->SetFilename()</code>! If your included
template is not showing in the output, this is the first thing
you should check.)</p> </li>
<li> The recommended idiom to fill an include-template dictionary is
like this:
<pre>
fill_include_template_dictionary(dict->AddIncludeDictionary(name), ...);
</pre>
<p>But what do you do if you decide, in
<code>fill_include_template_dictionary</code>, that you don't
want to display anything for this include-template after all? It
seems like it's too late: you've already created the
sub-dictionary. The solution is simple: just be sure that
<code>fill_include_template_dictionary()</code> doesn't call
<code>SetFilename()</code> in that case.</p>
<li> Never have a section which only contains another section.
<p>For example, don't do this:</p>
<pre>
{{#OUTER_SECTION}}
{{#INNER_SECTION}}
section contents here
{{/INNER_SECTION}}
{{/OUTER_SECTION}}
</pre>
<p>or this equivalent template code (see the previous item):</p>
<pre>
{{#OUTER_SECTION}}
{{>INCLUDED_SECTION}}
{{/OUTER_SECTION}}
</pre>
<p>This is usually done because the developer thinks the outer
section must be used to hide the section when the inner
section, intended for iteration, has no iterations. In both
cases, you should only have one section (either
<code>INNER_SECTION</code> or <code>INCLUDED_SECTION</code> in
the examples) and iterate that section either 0 times or more
than 0 times. It's the wonder of the dual use of sections,
i.e. that they may be conditional or iterative or, in this case,
both.</p>
<p>A related suggestion: Do not have a section whose entire
contents is one variable marker with nothing else, unless you
need to iterate over that section with multiple values of that
variable. You don't need the surrounding section just to hide
the marker. A variable marker that is not set, does not
produce output. By convention, we set such variables to the
empty string. But in neither case do you need to hide it by
hiding a surrounding section that contains nothing else.</p>
<li> Use this hide/show idiom for <code>if-else</code> blocks.
<p>Since sections are hidden by default, you can use represent
if-else logic in your code via <code>ShowSection</code>. For
example:</p>
<pre>
if ( my_test ) {
dict->ShowSection(kxyz_TRUE_BLOCK);
[ more code to fill the values for that section]
} else {
dict->ShowSection(kxyz_FALSE_BLOCK);
[ more code to fill the values for that section]
}
</pre>
<li> <code>Write...</code> vs. <code>Fill...Dictionary</code> methods
- Observe the proper division of labor, don't mix them.
<p>The output (or write) function should create the top level
template dictionary, call one or more fill-dictionary routines
with it, then get the template and expand it. It should not call
dictionary modifying methods, like <code>ShowSection</code>
and <code>SetValue</code>. By keeping these separated into
their own fill-dictionary routine, the code is more modular and
lends itself to template re-use. If you maintain the proper
division of labor, the template you are filling and outputting
may be filled and included in a larger template by someone
else.</p> </li>
<li> Use <code>AddSectionDictionary</code> only when you want to
iterate over a section or, secondarily, if you need to avoid name
conflicts.
<p>Sometimes developers get the idea that every section requires
its own child dictionary created by an
<code>AddSectionDictionary</code> call. Because of variable
inheritence, this isn't usually so. The intended purpose of
<code>AddSectionDictionary</code> is to enable iteration over a
section. Secondarily, if the section contains generic names that
may conflict with the same name in other parts of the template,
it may be safer to call <code>AddSectionDictionary</code> to
create a separate namespace. In any case, do not assume you must
call <code>AddSectionDictionary</code> just because you are
working within a section. The main dictionary can be used for all
levels of conditional sections as long as you avoid name
conflicts by keeping the marker names unique.</p> </li>
<li> Do not place <code>RegisterTemplateFilename</code>
statements in header (<code>.h</code>) files.
<p><code>RegisterTemplateFilename</code> is a macro that
instantiates a <code>TemplateNamelist</code> object. If you place
it in a header file, a different object will get created each time
it is included in another <code>.cc</code> file.
<p>The <code>RegisterTemplateFilename</code> statement and its
associated <code>#include</code> of the <code>varnames.h</code>
file should occur only in the <code>.cc</code> file that
implements the fill-dictionary routine for that template. You
should never have more than one
<code>RegisterTemplateFilename</code> for a single template and
you should try hard not to copy the <code>#include</code> file to
other files as well. The template versioning makes this more
important because a developer may not know that the template name
with included version number needs to be updated in more than one
file when versioning occurs. [Also see above for more information
about what routine uses the filename declared by the
<code>RegisterTemplateFilename</code> statement.]</p> </li>
<li> Never reference more than one template in a
fill...dictionary method.
<p>Each template should have its own fill-dictionary
routine. That routine should only reference marker names defined
in that template. If this convention is followed, then all the
prefixes in a fill-dictionary routine will be the same. [Note
that an implication of this convention is that if the template
includes another template, via a template-include marker, then
containing template's fill-dictionary routine should call the
included template's fill-dictionary routine (being careful to
observe the convention described above). But
then, this is merely a restatement of <A HREF="#oneone">"One
template / One procedure call"</A>.]</p> </li>
<li> Have fill...dictionary call <code>SetFilename</code> even if the
dictionary is never used for a template-include.
<p>SetFilename() is required when a dictionary is created via
<code>AddIncludeDictionary()</code>. However, it's safe to set
all the time. By setting it always, you make the code work
properly if this dictionary ever changes to be template-included
after all. Even if not, by saying what template file the
dictionary is intended to go with, you are self-documenting your
code.</p> </li>
<li> Do not call <code>c_str()</code> on strings to pass them to
<code>TemplateDictionary</code> methods.
<p>Note that all the TemplateDictionary methods are defined to
take <code>TemplateString</code> objects. These are created
automatically from both strings and char*'s (and can be created
manually if you have a char* and a length). So if you have a
string, it's safe and efficient to just pass it in directly; you
do not need to extract the const char * from your string object
to pass it to these methods. For some reason, this is a common
error of noviced template coders.</p>
<p>The one exception to this rule is when using the method
<code>SetFormattedValue</code>. When calling that
method, you must call <code>c_str()</code> on strings that are to
be inserted
into the format string, just as you would when providing data for
any other printf format string.</p> </li>
<li> Do not use <code>SetGlobalValue</code> when you could use
<code>SetValue</code>.
<p><code>SetGlobalValue</code> should be used quite rarely, for
constants that really are consistent across all your templates.
It's slower to look up a value in the global dictionary than it
is in the template-specific dictionary.</p> </li>
<li> Do not use <code>TemplateFromString</code> unless you have
a specific need for its non-file-based attributes.
<p><code>TemplateFromString</code> was created for use in highly
constrained cases where file I/O may be impaired or
undesirable, for instance to produce a server error message
where there may be disk problems or to produce formatted
output where there are processes that do not have a facility
for updating data files dynamically. It is not recommended for
ordinary use as it is limited in functionality in at least the
following ways:</p>
<ul class=blacklist>
<li> It can neither include nor be included from
another template.
<li> It cannot be updated dynamically via a
data-push; changes always require a binary push.
</ul>
</li>
<li> Use variable-modifiers (eg <code>{{VAR:html_escape}}</code>) or
<code>SetEscapedValue</code> when necessary to prevent security
violations.
<p>Variable-modifiers make it very easy to html-escape (or
otherwise escape) text that needs to be escaped for safety. Use
<code>:h</code>, <code>:j</code> and friends liberally.</p>
<p>For situations where you need to provisionally escape, or use
an escape routine other than the built-in ones, the
<code>Escaped</code> versions of the set-value methods
are useful utility functions to use.</p>
<p>As a guide for when to use this: every value accepted
from a user must be HTML-escaped before redisplaying it on
another page. The escaping
prevents the user from executing scripts or displaying raw HTML
via their input values. These methods make it simple to prevent
scripting security violations when used where necessary.</p> </li>
<li> Do not leave an extra space when using <code>{{BI_SPACE}}</code>
<p>The built-in template variable <code>BI_SPACE</code> is itself
replaced by a single space. It is used where you need to make
sure a space is preserved at the end of a line. It is a common
mistake to leave an extra space before this marker, which results
in not one, but two, spaces created in the document.</p> </li>
<p>Incorrect:<pre>
&lt;table border=0 {{BI_SPACE}}
align=center></pre></p>
<p>Correct:<pre>
&lt;table border=0{{BI_SPACE}}
align=center></pre></p>
<hr>
<ul>
<li> <A HREF="howto.html">Howto</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>