UNPKG

closure-builder

Version:

Simple Closure, Soy and JavaScript Build system

425 lines (330 loc) 12.5 kB
# Types `Closure Templates` supports a basic type system. Parameters can be strictly typed to: * enable compile time type checking of template calls * allow access to protocol buffer fields * generate smaller/faster code [TOC] ## Primitive types ### `any` {#any} The any type can only be printed, or coerced to a string. ### `?` {#unknown} The unknown type disables type checking. It is useful if you don't care, or are migrating templates from not using types to using types (this way you can migrate one parameter at a time). ### `null` {#null} The `null` type is not very useful on its own, but can be as part of [composite types](#composite). Backend | type in host language ---------- | ---------------------------------------------------------- JavaScript | `null`, `undefined` SoySauce | `com.google.template.soy.data.restricted.NullData`, `null` Tofu | `com.google.template.soy.data.restricted.NullData` Python | `NoneType` ### `bool` {#bool} Takes on a boolean value. Backend | type in host language ---------- | ---------------------------------------------------------------- JavaScript | `boolean` SoySauce | `boolean`, `com.google.template.soy.data.restricted.BooleanData` Tofu | `com.google.template.soy.data.restricted.BooleanData` Python | `bool` ### `int` {#int} An integer. Due to limitations of JavaScript this type is only guaranteed to have 52 bit of precision. Backend | type in host language ---------- | ---------------------------------------------------------- JavaScript | `number` SoySauce | `long`, `com.google.template.soy.data.restricted.LongData` Tofu | `com.google.template.soy.data.restricted.LongData` Python | `long` ### `float` {#float} A floating point number with 64 bits of precision. Backend | type in host language ---------- | --------------------- JavaScript | `number` SoySauce | `double`, `FloatData` Tofu | `FloatData` Python | `float` ### `number` {#number} An alias for `int|float`. (Technically a [composite type](#union), not a primitive.) ### `string` {#string} `string` is one of the most common types in `Closure Templates`. In addition to plain strings there are a number of safe subtypes. <table> <thead> <tr> <th>Backend</th> <th>type in host language</th> </tr> </thead> <tbody> <tr> <td>JavaScript </td> <td><code>string</code>, <code>goog.soy.data.UnsanitizedText</code>, (all safe string subtypes)</td> </tr> <tr> <td>SoySauce </td> <td><code>string</code>, <code>com.google.template.soy.data.restricted.StringData</code>, <code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Tofu </td> <td><code>com.google.template.soy.data.restricted.StringData</code>, <code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Python </td> <td><code>string</code>, <code>UnsanitizedText</code> (all safe string subtypes)</td> </tr> </tbody> </table> ### `html` {#html} `html` is for a string that contains safe HTML content. Safe html is HTML that comes from a trusted source, typically another `Closure Templates` template. Backend | type in host language ---------- | --------------------------------------------------------- JavaScript | `goog.soy.data.SanitizedHtml` SoySauce | `string`, `com.google.template.soy.data.SanitizedContent` Tofu | `com.google.template.soy.data.SanitizedContent` : Python | `sanitize.SanitizedHtml` ### `js` {#js} `js` is for a string that contains safe JavaScript code. Safe JavaScript is a string that comes from a trusted source, typically another `Closure Templates` template. Backend | type in host language ---------- | --------------------------------------------------------- JavaScript | `goog.soy.data.SanitizedJs`, `goog.html.SafeScript`: SoySauce | `string`, `com.google.template.soy.data.SanitizedContent` Tofu | `com.google.template.soy.data.SanitizedContent` : Python | `sanitize.SanitizedJs` ### `uri` {#uri} `uri` is for a string that contains a URI that came from a trusted source. <table> <thead> <tr> <th>Backend</th> <th>type in host language</th> </tr> </thead> <tbody> <tr> <td>JavaScript </td> <td><code>goog.soy.data.SanitizedUri</code>, <code>goog.Uri</code>, <code>goog.html.SafeUrl</code>, <code>goog.html.TrustedResourceUrl</code></td> </tr> <tr> <td>SoySauce </td> <td><code>string</code>, <code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Tofu</td> <td><code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Python</td> <td><code>sanitize.SanitizedUri</code></td> </tr> </tbody> </table> Additionally, all backends have support for coercing `webutil.html.types.SafeUrlProto` to a `uri` object. ### `trusted_resource_uri` {#trusted_resource_uri} `uri` is for a string that contains a URI that came from a trusted source and additionally can be used as a Script `src` or in other sensitive contexts. <table> <thead> <tr> <th>Backend</th> <th>type in host language</th> </tr> </thead> <tbody> <tr> <td>JavaScript </td> <td><code>goog.soy.data.SanitizedTrustedResourceUri</code>, : <code>goog.html.TrustedResourceUrl</code></td> </tr> <tr> <td>SoySauce </td> <td><code>string</code>, <code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Tofu</td> <td><code>com.google.template.soy.data.SanitizedContent</code></td> </tr> <tr> <td>Python</td> <td><code>sanitize.TrustedResourceUri</code></td> </tr> </tbody> </table> Additionally, all backends have support for coercing `webutil.html.types.TrustedResourceUrlProto` to a `trusted_resource_uri` object. ### `attributes` {#attributes} `attributes` is for a string that contains 0 or more HTML attribute value pairs. Backend | type in host language ---------- | --------------------------------------------------------- JavaScript | `goog.soy.data.SanitizedAttributes` SoySauce | `string`, `com.google.template.soy.data.SanitizedContent` Tofu | `com.google.template.soy.data.SanitizedContent` Python | `sanitize.SanitizedAttributes` Unlike the other safe string types there is no equivalent for attributes. ### `css` {#css} `css` is for a string that contains CSS that comes from a trusted source. NOTE: currently css contains either a set of CSS rules or a set of css attributes and the compiler does not make any distinction. This will likely change in the future. Backend | type in host language ---------- | --------------------------------------------------------- JavaScript | `goog.soy.data.SanitizedCss`, `goog.html.SafeStyle` SoySauce | `string`, `com.google.template.soy.data.SanitizedContent` Tofu | `com.google.template.soy.data.SanitizedContent` Python | `sanitize.SanitizedCss` Additionally, all backends have support for coercing `webutil.html.types.SafeStyleSheetProto` and `webutil.html.types.SafeStyleProto` to a `css` object. ## Composite types {#composite} ### Union types: `A|B` {#union} An `A|B` union type can contain either a value of type `A` or a value of type `B`. ### `list<T>` {#list} A list can contain any type as an element. Lists can be accessed using the [indexed operators](expressions.md#indexing-operators). For example, ```soy {template .foo} {@param l: list<string>} {$l[0]}, {$l[1]}, {$l[2]} {/template} ``` The most common thing to do with a list is to iterate over it, using the for loop: ```soy {template .foo} {@param l: list<string>} <ul> {for $el in $l} <li>{$el} {/for} </ul> {/template} ``` Backend | type in host language ---------- | -------------------------------------------------------- JavaScript | `Array` SoySauce | `java.util.List`, `com.google.template.soy.data.SoyList` Tofu | `com.google.template.soy.data.SoyList` Python | `list` ### `map<K, V>` {#map} A map takes two parameters for the key and value types. Maps are accessed using the [indexed operators](expressions.md#indexing-operators). For example, ```soy {template .foo} {@param m: map<int, string>} <ul> {for $key in mapKeys($m)} <li>{$key}: {$m[$key]} <li>{$key} * 2 = {$key * 2} // arithmetic on numeric keys in map {/for} {/template} ``` Maps have several advantages over [legacy object maps](#legacy_object_map): * Maps can contain non-string keys. The declared type of the key, `K`, must be [bool](#bool), [string](#string), [int](#int), [float](#float), [number](#number) (While it is possible to declare a legacy object map with a non-string key type, the behavior of non-string keys in legacy object maps is undefined and buggy.) * There is a syntax for creating a [map literal](expressions.md#map): `map(...)`. By contrast, there is no syntax to create a `legacy_object_map` literal from inside a Soy template. (Legacy object maps can only be passed in from host environments during rendering.) * Legacy object maps are not supported if you are compiling to Python. (Declaring a `legacy_object_map` param is a compilation error in the Python backend.) Maps and legacy object maps are distinct types. You cannot pass a legacy object map to a template expecting a map, and vice versa. If you need to convert from one map type to the other, use the [mapToLegacyObjectMap](functions.md#mapToLegacyObjectMap) and [legacyObjectMapToMap](functions.md#legacyObjectMapToMap) functions. Use `map` instead of `legacy_object_map` for all new `Closure Templates` code. Backend | type in host language ---------- | --------------------- JavaScript | `Map` SoySauce | `java.util.Map` Tofu | `java.util.Map` Python | `dict` ### `legacy_object_map<K, V>` {#legacy_object_map} A legacy object map takes two parameters for the key and value types. Legacy object maps are accessed using the [indexed operators](expressions.md#indexing-operators). For example, ```soy {template .foo} {@param m: legacy_object_map<string, string>} <ul> {for $key in keys($m)} <li>{$key}: {$m[$key]} {/for} </ul> {/template} ``` NOTE: only `string` is well supported for key types. The behavior for key types other than string is undefined. WARNING: legacy object maps have [several disadvantages](#map) compared to maps. Use `map` instead of `legacy_object_map` for all new `Closure Templates` code. See go/soy-map-faq for details. Backend | type in host language ---------- | ------------------------------------------------------------------ JavaScript | `Object` SoySauce | `java.util.Map`, `com.google.template.soy.data.SoyLegacyObjectMap` Tofu | `java.util.Map`, `com.google.template.soy.data.SoyLegacyObjectMap` Python | not supported ### records: `[<prop-name>: <prop-type>,...]` {#record} Record types define an object with a given set of properties. The properties can be accessed using the [data access operators](expressions.md#data-access) For example, ```soy {template .foo} {@param person: [age:int, name:string]} Name: {$person.name} Age: {$person.age} {/template} ``` In many cases, defining a protocol buffer is superior to using records since it is less verbose Backend | type in host language ---------- | --------------------------------------------------------- JavaScript | `Object`[^1] SoySauce | `java.util.Map`, `com.google.template.soy.data.SoyRecord` Tofu | `com.google.template.soy.data.SoyRecord` Python | `dict` ### protos: `foo.bar.BazProto` {#proto} Protocol buffers in `Closure Templates` are referenced by their fully qualified proto name. They can be accessed as though they were `record` types with the `.` operator. Protocol Buffers in `Closure Templates` have the same semantics as `JSPB`, not `Java` protos. See the [dev guide](../dev/protos.md) for more information on how protos work. TIP: You can use the [`{alias ...}`](file-declarations.md#alias) directive to abbreviate proto type names. NOTE: currently, protos are _not supported_ in the Python backend. <br> [^1]: The difference between map and record for JavaScript is simply whether the keys are strings or symbols.