Closure Tools

Closure Template Commands

Table of Contents

  1. Overview
  2. delpackage
  3. namespace
  4. alias
  5. template, /template
  6. Special Characters
  7. literal, /literal
  8. print
  9. msg, /msg
  10. let, /let
  11. if, elseif, else, /if
  12. switch, case, default, /switch
  13. foreach, ifempty, /foreach
  14. for, /for
  15. call, /call, param, /param
  16. Delegate Templates (with delpackage)
  17. Delegate Templates (with variant)
  18. css

Overview

Commands are instructions that you give the template compiler to create templates and add custom logic to templates. Put commands within Closure Template tags, which are delimited by braces ({}). Specify the command name as the first token in the tag (except the print command, which is implied if no command is specified), and add additional tokens to form the command text. For example, to create a template, use the tag {template ...}. Within the template you can enclose other commands to evaluate conditional expressions, iterate over data objects, or print messages.

A few of the tags below belong at the top of a Closure Template file, while most of them belong within a template. Within the body of a template, any text within Closure Template tags is parsed and understood by the compiler, while anything outside of Closure Template tags is raw text that is output as-is. The syntax for command text varies depending on the specific command. This chapter describes all of the template commands that you can use.

delpackage

Syntax:
{delpackage <delegate_package_name>}

This tag belongs at the start of a template file, before the namespace tag. It must appear at the start of its own line. It is associated with one of the two ways to use delegate templates. For details, please see the section on using delegate templates with delpackage.

namespace

Syntax (basic form):
{namespace <namespace>}
With all optional attributes:
{namespace <namespace> autoescape="<contextual/true/false>"}

This tag is required at the start of every template file. It must appear at the start of its own line. It declares the namespace for the file, which serves as the common prefix for the full name of every template in the file. You can optionally declare the default autoescape mode for every template in the file (recommended value is contextual). You can override this default in the template tag.

Closure Templates allows multiple files to have the same namespace. However, note that Closure Library and Closure Compiler do not allow it, so if you're using Closure Templates in JavaScript together with other Closure technologies, then it's recommended to avoid having the same namespace in multiple template files.

alias

Syntax:
{alias <namespace>}

This tag belongs at the start of a template file, after the namespace tag. It must appear at the start of its own line. You can include any number of alias declarations. Each declaration will alias the given namespace to its last identifier, so that when you call a template in that namespace, you don't need to type the whole namespace, but only the last identifier plus the template's partial name.

For example, if you declare
{alias my.long.namespace.root.myproject.mymodule.myfeature}
then you can replace the call
{call my.long.namespace.root.myproject.mymodule.myfeature.myTemplate /}
with
{call myfeature.myTemplate /}

Note that delegate templates have their own full names (not a partial name prefixed by the namespace), so the alias command currently does not affect delegate calls (delcall).

template, /template

Syntax (basic form):
{template <template_name>}
  ...
{/template}
With all optional attributes:
{template <template_name> private="<true/false>" autoescape="<true/false/contextual>"}
  ...
{/template}

These tags must appear at the start of their own lines.

The template name must be a dot followed by an identifier because it is a partial name relative to the file's namespace. For example, if the file's namespace is ui.settings.login and the template's partial name is .newPassword, then the full template name would be ui.settings.login.newPassword.

These are the template tag's attributes:

  • private: Optional. Default false. Set this to true if you want this to be a private template. A private template can be called by other templates, including templates from other .soy files, as long as the callers are all within the bundle of .soy files that is compiled together. When you set private to true, the template compiler can optimize calls to that template in various ways, including inlining all calls of that template and removing that template altogether.

  • autoescape: Optional. Affects the encoding of print commands and is set according to these rules:
    • If there is an autoescape value specified in the template tag, use that value.
    • Else if there is an autoescape value specified in the file's namespace declaration, use that value.
    • Else default to the value true, which means that the outputs from all print commands are HTML-escaped by default as a safeguard against cross-site scripting vulnerabilities.
    HTML-escaping is not always ideal, so templates with autoescape="contextual" (as described in the Security chapter) use an escaping convention that is appropriate to the context in which a print command appears. You have two options for turning off autoescaping for data that is known to be safe:
    • Recommended: Mark the value as sanitized content.
    • Use the |noAutoescape print directive. For example, {$userName} is autoescaped while {$productNameHtml |noAutoescape} is not autoescaped. Note that this example also demonstrates the convention that known-to-be-safe HTML data values should have keys whose names end in Html.
    You can set autoescape to false for a whole template if you know that every template input is safe and you'd rather not add |noAutoescape to every print tag. But this may cause cross-site scripting errors later when unsafe content is added by someone who doesn't notice the autoescape="false" in the template tag. The decision is up to you, and it is a per-template decision.

    Warning: If you use autoescape="false" for a template, you must sanitize all the HTML content in that template, or else risk cross-site scripting vulnerabilities.

Special Characters

Use the following special character commands to add raw text characters:

Special Character Equivalent Raw Text
{sp} space
{nil} empty string
{\r} carriage return
{\n} new line (line feed)
{\t} tab
{lb} left brace
{rb} right brace

Follow these heuristics when deciding when use {sp} and {nil}:

  • {sp}: Use {sp} to insert a space character at the beginning or end of a line, in situations where the line-joining algorithm would not normally insert a space (specifically, at line-joining locations bordered by an HTML or template tag on either side).

  • {nil}: If a line joining location normally adds a space, but you want to make the lines join without a space, then add {nil} at the end of the first line (most common) or the beginning of the second line. While the {nil} itself turns into an empty string, it adds a template tag at the line-joining location, which eliminates the default single space.

literal, /literal

Syntax:
{literal} ... {/literal}

This command allows you to include a literal block of raw text, possibly including special characters like braces. The rendered output is exactly what appears in the literal block. Note that this means that absolutely no processing happens within a literal block, e.g. no HTML escaping, no line joining, no removal of indentation, no parsing for template commands, and no parsing for comments.

print

Syntax (without directives):
{<expression>}
{print <expression>}
With directives:
{<expression> |<directive1> |<directive2> |...}
{print <expression> |<directive1> |<directive2> |...}

The print command is the most common command in Closure Templates, so it merits a short syntax in which you can omit the command name print. When Closure Templates encounters a print tag, it simply inserts the result of the expression, coerced to a string if necessary, into the rendered output.

Note: The command name print is optional.

Print directives

Print directives are post-processing on the output of a print command. For a list of print directives, please see the section Print Directives in Functions and Print Directives.

msg, /msg

Syntax (basic form):
{msg desc="<help_text_for_translators>"}
  ...
{/msg}
With all optional attributes:
{msg meaning="<differentiator>" desc="<help_text_for_translators>"}
  ...
{/msg}

Use the msg tag to mark a section of the template as a message that needs to be translated. You must provide the required desc attribute, which provides explanation text to the (human) translators.

Note: You should never break up a sentence or phrase into multiple messages because translation is most effective with the context of the entire sentence or phrase.

Within a msg block, the template compiler turns HTML tags and template tags into placeholders, with the exception of template tags that generate raw text (e.g. special character commands and literal blocks), which are simply substituted. Messages that contain placeholders might be confusing to translators, so you should consider providing (in the desc attribute) an example of how the message looks to the user.

Here are details on how Closure Templates generate placeholders in messages:

  • The template compiler uses fixed names for common HTML placeholders, e.g. <a ...> becomes {START_LINK} and <br /> becomes {BREAK}.

  • A simple print tag that prints a data reference turns into a placeholder that's named according to the last key name, by default. For example, {$user.emailAddress} turns into the placeholder {EMAIL_ADDRESS}.

  • A complete call block (up to the closing /call) turns into a single placeholder. The placeholder is named {XXX} by default, so if you put a call inside a msg, please be sure to provide a clear example of what the message might look like in the desc attribute.

  • If you find a need to specify a placeholder name for a print or call instead of allowing the compiler generate the default name, you can add the phname attribute. The value can either be camel case or upper underscore. For example, {call .emailAddr phname="emailAddress" /} causes the placeholder name to be EMAIL_ADDRESS instead of XXX. Note that changing a placeholder name changes the message id, causing retranslation.

  • If a message contains multiple placeholders that would result in the same placeholder name, then the template compiler appends number suffixes to distinguish them, e.g. START_LINK_1, START_LINK_2.

  • Template commands for control-flow (if, switch, foreach, for) are not permitted within msg blocks. However, you can put them in a let block and then print the resulting reference from a within a msg block. If you do this, make sure the let block has absolutely no translatable content.

Example message:
{msg desc="Says hello and tells user to click a link."}
  Hello {$userName}! Please click <a href="{$url}">here</a>.
{/msg}
Example of what the translators see:
Hello {USER_NAME}! Please click {START_LINK}here{END_LINK}.
Example translation that one translator might give us:
{START_LINK}Zhere{END_LINK} zclick zplease. {USER_NAME} zhello!
Example output (for userName = 'Jess' and url = 'http://www.google.com/'):
<a href="http://www.google.com/">Zhere</a> zclick zplease. Jess zhello!

Use the meaning attribute when you have two messages that are exactly the same string in English, but might be translated to different strings in other languages. The meaning should then be a short string that distinguishes the two messages, and is used for generating different message ids. Translators do not see the meaning attribute, so you must still communicate all the details in the desc. For example:
{msg meaning="noun" desc="The word 'Archive' used as a noun, i.e. an information store."}
  Archive
{/msg}
{msg meaning="verb" desc="The word 'Archive' used as a verb, i.e. to store information."}
  Archive
{/msg}

See more information about translating messages in the Translation chapter.

let, /let

Syntax for arbitrary values:
{let $<identifier>: <expression> /}
Syntax for rendering to string:
{let $<identifier>}...{/let}

Use the let command to define an alias for an intermediate value (not to be confused with the alias command, which declares an alias for a namespace). The local variable defined by let is not modifiable. You might use let because you'll need to reuse the intermediate value multiple times, or you'll need to print a rendered value using a directive, or you feel it improves the readability of your template code.

Example:
{let $isEnabled: $isAaa and not $isBbb and $ccc == $ddd + $eee /}
{if $isEnabled and $isXxx}
  ...
{elseif not $isEnabled and $isYyy}
  ...
{/if}

The second syntax form listed above renders the contents of the let block to a string, including applying autoescaping. It is sometimes needed, but should be used sparingly.

Note: The alias is only defined within the immediate code block containing the let command. I.e., the alias is not necessarily defined for the rest of the template.

if, elseif, else, /if

Syntax:
{if <expression>}
  ...
{elseif <expression>}
  ...
{else}
  ...
{/if}

Use the if command for conditional output. The section starting from if and ending in /if is called an if statement. The template compiler evaluates the expressions for if and optional elseif clauses in a boolean context. As soon one expression evaluates to true, the compiler processes that sub-block and skips the rest of the if statement is skipped. Any elseif clauses that appear after the one that evaluates to true are never evaluated. The compiler only processes the optional else command when none of the if and elseif conditions are true.

For example:

{if round($pi, 2) == 3.14}
  {$pi} is a good approximation of pi.
{elseif round($pi) == 3}
  {$pi} is a bad approximation of pi.
{else}
  {$pi} is nowhere near the value of pi.
{/if}

Example output (for pi = 2.71828):

2.71828 is a bad approximation of pi.

switch, case, default, /switch

Syntax:
{switch <expression>}
  {case <expression_list>}
    ...
  {case <expression_list>}
    ...
  {default}
    ...
{/switch}

Use the switch command for conditional output based on the value of an expression. The section starting from switch and ending in /switch is called a switch statement. Each case can have one or more expressions (use a comma-separated list if you have more than one), and the case matches when any one of its expressions matches the value of the switch expression. When a case matches, the template compiler process that sub-block and the skips the remainder of the switch statement. The compiler processes the optional {default} command if none of the expressions from the case statements match the switch expression.

For example:

{switch $numMarbles}
  {case 0}
    You have no marbles.
  {case 1, 2, 3}
    You have a normal number of marbles.
  {default}  // 4 or more
    You have more marbles than you know what to do with.
{/switch}

Example output (for numMarbles = 2):

You have a normal number of marbles.

foreach, ifempty, /foreach

Syntax:
{foreach <local_var> in <data_ref>}
  ...
{ifempty}
  ...
{/foreach}

Use the foreach command to iterate over a list. The iterator local_var is a local variable that is defined only in the block. Within the block, you can also use three built-in functions that only take foreach variables as arguments:

  • isFirst($var) returns true only on the first iteration.
  • isLast($var) returns true only on the last iteration.
  • index($var) returns the current index in the list. List indices are 0-based.

The optional ifempty command is for a fallback section that the template compiler processes when the list is empty.

For example:

{foreach $operand in $operands}
  {if not isFirst($operand)} + {/if}
  {$operand}
{ifempty}
  0
{/foreach}

Example output (for operands = ['alpha', 'beta', 'gamma']):

alpha + beta + gamma

for, /for

Syntax:
{for <local_var> in range(<expression1>, <expression2>, <expression3>)}
  ...
{/for}

Use the for command to generate a simple numerical loop. Set the name for a local variable, which is a loop iterator that is defined only in the block. The range() function can take 1, 2, or 3 arguments. With 3 arguments, the 1st is the initial value, the 2nd is the limit (note that the loop only continues if the loop variable's value is strictly less than the limit), and the 3rd is the increment. With 2 arguments, the increment is assumed to be 1. With only 1 argument, the initial value is assumed to be 0. For example:

range(10)        →  0 1 2 3 4 5 6 7 8 9
range(4, 10)     →          4 5 6 7 8 9
range(4, 10, 2)  →          4   6   8

For example:

{for $i in range($numLines)}
  Line {$i + 1} of {$numLines}.<br>
{/for}

Example output (for numLines = 3):

Line 1 of 3.<br>Line 2 of 3.<br>Line 3 of 3.<br>

call, /call, param, /param

Syntax (basic form):
{call <template_name> data="<data_to_pass>" /}
With enclosed parameters:
{call <template_name> data="<data_to_pass>"}
  {param <key1>: <expression> /}
  {param <key2>}
    ...
  {/param}
{/call}

Use the call command to call another template and insert its output into the current template. To provide the parameters of the callee template, you can pass all or part of the caller template's data, construct values to pass using param commands, or use a combination of the two. The following sections discuss these three options in turn, using this example callee template:

/**
 * @param largerNum An integer larger than 'smallerNum'.
 * @param smallerNum An integer smaller than 'largerNum'.
 */
{template .exampleCallee}
  {$largerNum} is greater than {$smallerNum}.
{/template}

Pass all or part of the caller's data to the callee

If you want to pass all or part of the caller's data to the callee, you must make sure that the keys are exactly the same names as the callee's parameters. For example, if the caller's data includes a list pairs where each element is a map containing keys largerNum, and smallerNum, then you can use the following:

{foreach $pair in $pairs}
  {call .exampleCallee data="$pair" /}
{/foreach}

In addition to any data or variable reference, you can use the special value data="all" to denote that all of the caller's data should be passed. This of course means that the callee's parameters must be a subset of the caller's parameters, and have the same names. In such cases, it's good practice to use data="all" instead of re-listing the parameters. For example, if the caller's data contains two parameters aaa and bbb, and you want to pass both to the callee (with the same parameter names), it would be extra work and unnecessary to re-list each parameter like this:

// Unnecessary.
{call .mySubtemplate}
  {param aaa: $aaa /}
  {param bbb: $bbb /}
{/call}

Instead, simply set data="all", like this:

// Recommended.
{call .mySubtemplate data="all" /}

Currently, the compiler will actually rewrite instances of the "unnecessary" example above to the "recommended" example. This may occasionally cause surprising behavior, where both the caller and callee also share an optional param ccc that is now passed due to the rewrite. So far, we've decided that the trade-off is worth it for the smaller/faster resulting code.

Finally, you can omit the data attribute (it is optional) if there are no parameters to be passed in this manner.

Construct values to pass

If you need to construct values to pass to the callee, use the param command. There are two forms of this command.

Syntax for arbitrary values:
{param <key>: <expression> /}
Syntax for rendering to string:
{param <key>}...{/param}

The first form is for arbitrary values and should be used in most cases.

The second form renders the contents of the param block to a string, including applying autoescaping. It is needed in some situations, but it's usually an error to use it when the first form would suffice.

In particular, a common heuristic is that if you're using the second form with a param block that contains a single print tag:
{param aaa}{$bbb}{/param}
then it's usually an error, and should be replaced with:
{param aaa: $bbb /}

Back to our example, assume that the caller's data includes a list pairs where each element is a map containing key largerInt (note the name change) and only sometimes contains the key smallerInt (otherwise undefined). Use this to make the call:
{foreach $pair in $pairs}
  {call .exampleCallee}
    {param largerNum: $pair.largerInt /}
    {param smallerNum}
      {if $pair.smallerInt}
        {$pair.smallerInt}  // if defined, pass it
      {else}
        {$pair.largerInt - 100}
      {/if}
    {/param}
  {/call}
{/foreach}

The above example demonstrates the two forms of the param command. The first form evaluates an expression and passes the result as the parameter. The second form renders an arbitrary section of Soy code and passes the result as the parameter.

If you're observant, you've probably noticed two issues. The first issue is the value passed for smallerNum is now a string, not an integer (fortunately in this case the callee only uses the parameter in a string context). If you noticed this issue, then perhaps you also noticed that the computation for smallerNum can be put into an expression so that indeed it can be passed as an integer:
{param smallerNum: $pair.smallerInt ? $pair.smallerInt : $pair.largerInt - 100 /}
The second issue is if $pair.smallerInt == 0, then it would be falsy and so $largerInt - 100 would be passed even though $pair.smallerInt is defined and should be passed. This is why you should generally avoid using sometimes-defined map keys. If you do use them, please consider the possibility of falsy values. In this example, if there's a possibility that $pair.smallerInt == 0, you could correct the bug by rewriting the expression using the function isNonnull:
{param smallerNum: isNonnull($pair.smallerInt) ? $pair.smallerInt : $pair.largerInt - 100 /}
or better yet, use the null-coalescing operator:
{param smallerNum: $pair.smallerInt ?: $pair.largerInt - 100 /}

Use a combination of the two

Finally, you can mix the two options above: you can pass some of the callee's parameters directly from the caller's data, and pass the rest of the parameters using param commands. For example, if the caller's data includes an integer largerNum and a list of integers smallerNums that are all smaller than largerNum, you could use the following template:

{foreach $smallerNum in $smallerNums}
  {call .exampleCallee data="all"}
    {param smallerNum: $smallerNum /}
  {/call}
{/foreach}

Here, the data="all" attribute passes in the callee's original template data largerNum and the list smallerNums. However, because data="all" does not pass in the variable smallerNum, you must pass it explicitly using the param command.

Note: The data attribute of a call tag can only be used to pass all or part of the callee's original template data.

Calling a template in a different namespace

All of the above examples demonstrate calling a template in the same namespace, hence the partial template name (beginning with a dot) used in the call command text. To call a template from a different namespace, use the full template name including namespace. For example:
{call myproject.mymodule.myfeature.exampleCallee data="$pair" /}
Or, if you've aliased the namespace of the template you're calling to its last identifier, then
{call myfeature.exampleCallee data="$pair" /}

Delegate Templates (with delpackage)

The delegates feature allows you to write multiple implementations of a subtemplate and choose among them at a later time, such as on a per-user basis. Delegate templates are defined and called using commands deltemplate and delcall, which have syntax similar to template and call. There are two independent ways to use delegates, differing in how you control which delegate implementation is called. This section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, e.g. an experiment whose code is only sent to a small subset of users. The next section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

Syntax:
main.soy
{namespace ...}

/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton allowemptydefault="false" data="..." /}
{/template}

/** Default implementation. */
{deltemplate aaa.bbb.myButton}
  ...
{/deltemplate}
experiment.soy
{delpackage MyExperiment}
{namespace ...}

/** My experiment's implementation. */
{deltemplate aaa.bbb.myButton}
  ...
{/deltemplate}

The multiple implementations must appear in different template files, and each file other than the default implementation must declare a delegate package name (delpackage). This is the identifier used to select the desired implementation at usage time.

Note that the delegate template names are not within the file's namespace. The file's namespace is only prepended to basic template names (i.e. not delegate). Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

Template files can have an optional delpackage declaration at the top, just above the namespace declaration. Also, multiple template files can have the same delpackage name, putting them all within the same delegate package. If a delegate template is defined in a file without delpackage, then it is considered a default implementation. If a delegate template is defined in a file with delpackage, then it is a non-default implementation. When selecting a delegate implementation to use for handling a delegate call, a non-default implementation has higher priority (priority 1) than a default implementation (priority 0).

At render time (whether in JS or Java), when a delegate call needs to be resolved, we look at all the "active" implementations of that delegate template name and use the implementation with the highest priority. Basically, this means:

  • If there's an active non-default implementation, it is used.
  • Else, if there's an active default implementation, it is used.
  • Else, if allowemptydefault is true, then the delegate call renders to the empty string.
  • Else, a run-time error occurs.

Due to the third case, it is legal to delcall a template that has no default implementation, as long as you specify the allowemptydefault attribute. The current recommendation is to always specify the allowemptydefault attribute, because its default value will change. (The current default is true, but will be changed to false in the future.)

An "active" implementation is one that is available for this particular render call (see below in JS and Java specific notes). Rendering a delcall for which there is more than one active implementation with the same priority is a run-time error.

JS usage

In JS, an "active" implementation is simply an implementation that is defined in the JS files loaded. Ship only the generated JS files corresponding to active delpackages. If there is more than one implementation of a delegate template at the same priority, then a run-time error is generated at JS load time for that user.

Java usage

The Tofu rendering API in class SoyTofu.Renderer now includes a new method for optionally specifying the set of "active" delegate packages for the render:
SoyTofu.Renderer.setActiveDelegatePackageNames(Set<String>)
For example, with our example template code above, you can call
myTofu.newRenderer(...)
    .setActiveDelegatePackageNames(ImmutableSet.of("MyExperiment"))
    .setData(...)
    .render()

This will result in using the non-default implementation of aaa.bbb.myButton from the MyExperiment delegate package. On the other hand, if you leave out the call to setActiveDelegatePackageNames() or if you pass a set not including "MyExperiment", then you'll be using the default implementation of aaa.bbb.myButton. If there's more than one active implementation of a delegate template at the same priority, then a render-time exception is thrown.

Delegate Templates (with variant)

The delegates feature allows you to write multiple implementations of a subtemplate and choose among them at a later time, such as on a per-user basis. Delegate templates are defined and called using commands deltemplate and delcall, which have syntax similar to template and call. There are two independent ways to use delegates, differing in how you control which delegate implementation is called. The previous section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, e.g. an experiment whose code is only sent to a small subset of users. This section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

Syntax:
/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton variant="$variantToUse" /}
{/template}

/** Implementation 'alpha'. */
{deltemplate aaa.bbb.myButton variant="'alpha'"}
  ...
{/deltemplate}

/** Implementation 'beta'. */
{deltemplate aaa.bbb.myButton variant="'beta'"}
  ...
{/deltemplate}

Note: The variant feature is relatively new and may be subject to modifications.

Note that the delegate template names are not within the file's namespace. The file's namespace is only prepended to basic template names (i.e. not delegate). Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

The variant is currently always a string. The variant in a deltemplate tag currently must be a string literal containing a valid identifier. If no variant is specified, then it defaults to the empty string. The variant in a delcall tag can be an arbitrary expression, as long as it evaluates to a string at render time.

At render time, when a delegate call needs to be resolved,

  • If there's a delegate implementation with matching variant, it is used.
  • Else, if there's a delegate implementation with no variant, it is used.
  • Else, a run-time error occurs.

css

Syntax:

{css <command_text>}

The css command is useful if you're not sure how your mapping from CSS variable names to actual CSS class names will be provided. This command allows the decision to be changed on a per-compile basis. The SoyFileSet.Builder.setCssHandlingScheme() option (or --cssHandlingScheme for SoyToJsSrcCompiler) indicates how to interpret css commands. The options are:

  • LITERAL: Insert command text as literal text.
  • REFERENCE: Evaluate command text as a data or global reference.
  • BACKEND_SPECIFIC (or GOOG for SoyToJsSrcCompiler): For the JavaScript Source backend, generates a call to the Closure Library function goog.getCssName. This option is not applicable for the Tofu backend.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.