HTML Template Language (HTL) Specification

repository·master·Indexed 43 days ago

https://github.com/adobe/htl-spec

The formal specification for HTML Template Language (HTL), formerly known as Sightly. Used primarily in Adobe Experience Manager (AEM), HTL is a server-side templating language designed to replace JSP. This documentation covers syntax, grammar, XSS protection via display contexts, logical operators, i18n, and block statements such as data-sly-use, data-sly-test, and data-sly-list.

Tokens
7.7K
Snippets
21
Records
25
Agent score
5%

What's inside HTL

  1. Overview of HTML Template Language (HTL)

    master
    HTML Template Language (HTL), formerly known as Sightly, is the preferred and recommended server-side template system for HTML in Adobe Experience Manager (AEM). It is designed to replace JSP (JavaServer Pages). HTL defines a syntax and behavior for templating that is used to generate HTML on the server side.
  2. Understand Object Resolution for properties and methods

    master

    When accessing properties or methods on a Use-API object in HTL (e.g., expression.identifier), the implementation follows a specific resolution algorithm:

    1. Bracket Notation: expression.identifier is treated identically to expression["identifier"] or expression['identifier'].
    2. Resolution Algorithm:
      • Fields: First, try to resolve the identifier as a publicly accessible field of the object.
      • Methods: If no field is found, try to resolve it as a publicly accessible method without formal parameters:
        1. Look for a method named exactly identifier.
        2. Look for a getter named getIdentifier (camelCase).
        3. Look for a boolean check named isIdentifier (camelCase).
      • Fallback: If none of the above are found, return null.
  3. Block Statement Evaluation Priority

    master

    When multiple data-sly-* block statements are applied to the same HTML element, they are evaluated in a specific order of priority. If two statements have the same priority, they are evaluated from left to right.

    Priority Order (Highest to Lowest):

    1. data-sly-template
    2. data-sly-set, data-sly-test, data-sly-use
    3. data-sly-call
    4. data-sly-text
    5. data-sly-element, data-sly-include, data-sly-resource
    6. data-sly-unwrap
    7. data-sly-list, data-sly-repeat
    8. data-sly-attribute
  4. Use Display Context for XSS Protection

    master

    HTL provides automatic context-aware XSS protection. When outputting values into HTML attributes that represent URIs (like href, src, action), HTL defaults to the uri context.

    For style and script contexts, you must explicitly set a context, otherwise the expression will output nothing. Use the context option to specify the required protection level.

    <!--/* Scripts */-->
    <a href="#whatever" onclick="${myFunctionName @ context='scriptToken'}()">Link</a>
    <script>var ${myVarName @ context="scriptToken"}="Bar";</script>
    <script>var bar='${someText @ context="scriptString"}';</script>
     
    <!--/* Styles */-->
    <a href="#whatever" style="color: ${colorName @ context='styleToken'};">Link</a>
    <style>
        a.${className @ context="styleToken"} {
            font-family: '${fontFamily @ context="styleString"}', sans-serif;
            color: #${colorHashValue @ context="styleToken"};
        }
    </style>
  5. Syntax of HTL Block Statements

    master

    HTL block plugins are implemented using data-sly-* attributes on HTML elements.

    Key syntax rules:

    • Element types: Elements can have a closing tag or be self-closing (use a trailing slash for empty elements).
    • Attribute values: Can be static strings, expressions (using ${...}), or boolean attributes (no value).
    • Quoting: Values can be single-quoted, double-quoted, or unquoted.
    • Parametric expressions: You can pass arguments to a block using the @ syntax within an expression.
    • Multiple blocks: Several different data-sly-* statements can be applied to the same element.
    • Cleanup: All data-sly-* attributes are automatically removed from the final generated markup.

    Note on Identifiers: A block statement can be followed by an identifier (e.g., data-sly-BLOCK.IDENTIFIER="value") to assign the result to a specific variable name. Top-level identifiers are case-insensitive, but their properties are case-sensitive.

    <tag data-sly-BLOCK></tag>                                 <!--/* Standard block */-->
    <tag data-sly-BLOCK/>                                      <!--/* Self-closing */-->
    <tag data-sly-BLOCK="string value"/>                       <!--/* With static value */-->
    <tag data-sly-BLOCK="${expression}"/>                      <!--/* With expression */-->
    <tag data-sly-BLOCK='${expression}'/>                      <!--/* Single quoted expression */-->
    <tag data-sly-BLOCK=${expression}/>                         <!--/* Unquoted expression */-->
    <tag data-sly-BLOCK="${@ myArg='foo'}"/>                 <!--/* Parametric expression */-->
    <tag data-sly-BLOCKONE="value" data-sly-BLOCKTWO="value"/> <!--/* Multiple blocks */-->
    
    <!--/* Using an identifier */-->
    <tag data-sly-BLOCK.IDENTIFIER="value"></tag>
  6. HTL Expression Syntax and Grammar

    master

    HTL expressions are enclosed in ${ ... }. The grammar supports identifiers, literals (strings, integers, floats, booleans), property access via dot notation (obj.key) or bracket notation (obj['key']), and array indexing.

    Key Syntax Rules:

    • Escaping Expressions: To output a literal ${, use a backslash: \${.
    • String Escaping: Use backslashes for single-character escapes (\t, \n, \r, \f, \', \", \\) or Unicode escapes (\uXXXX).
    • Comments: HTL comments use the syntax <!--/* comment content */-->. Expressions inside HTML comments are evaluated, but block statements are not.
    <!--/* Identifiers: */-->
    ${myVar}
    
    <!--/* Accesses a member of an object: */-->
    ${myObject.key}
    ${myObject['key']}
    ${myObject[keyVar]}
    
    <!--/* Accesses an index of an array: */-->
    ${myArray[1]}
    ${myArray[indexVar]}
    
    <!--/* Literals: */-->
    ${true}
    ${42}
    ${'string'}
    ${[1, 2, 3, true, 'string']}
  7. Logical and Comparison Operators

    master

    HTL supports standard logical and strict comparison operators.

    Logical Operators:

    • ! (NOT)
    • && (AND)
    • || (OR)
    • ? : (Ternary/Conditional) - Note: The : separator must be surrounded by whitespace.

    Comparison Operators (Strict): HTL uses strict comparison; no type conversion is applied. Equality operators (==, !=) behave like JavaScript's === and !==.

    • <, <=, ==, >=, >, !=

    Relational Operator:

    • in: Checks if a String is contained in another String, if an Array/List contains an object, or if an object has a property/Map key.
    ${varOne && !(varTwo || varThree)} <!--/* Grouping */-->
    ${!myVar}                          <!--/* Logical NOT */-->
    ${varOne && varTwo}                <!--/* Logical AND */-->
    ${varOne || varTwo}                <!--/* Logical OR */-->
    ${varChoice ? varOne : varTwo}     <!--/* Conditional (ternary) */-->
    
    ${'a' in 'abc'}                   <!--/* String containment */-->
    ${100 in [100, 200]}              <!--/* Array containment */-->
    ${'a' in logic}                   <!--/* Property/Key check */-->
  8. Use the `<sly>` tag to unwrap elements

    master

    The <sly> tag is a special HTML tag used to remove the tag itself from the final output while allowing its children (or the results of HTL attributes) to be displayed. This is useful for including resources or logic without adding unnecessary markup to the DOM.

    Note: While <sly> is not a valid HTML5 tag, you can force it to appear in the final output by using data-sly-unwrap="${false}".

    <!--/* This will display only the output of the 'header' resource, without the wrapping <sly> tag */-->
    <sly data-sly-resource="./header"></sly>
  9. Find HTL implementations and compliance tools

    master

    If you are looking to use or implement HTL, there are several key resources available:

    • Reference Implementation: A Java-based reference implementation is available via the Apache Sling project. You can find it in the Apache Sling repository under bundles/scripting/sightly.
    • Compliance Testing: To verify if an implementation adheres to the HTL specification, use the Technology Compatibility Kit (TCK).
    • Version Support: Version 1.4 of the specification is implemented in AEM 6.3 SP3 and AEM 6.4 SP1.
  10. Define variables with `data-sly-set`

    master

    The data-sly-set block defines a new identifier (variable) with a specific value.

    • Element: Always rendered.
    • Attribute identifier: Required; the name of the variable.
    • Attribute value: Optional; the value to store.
    • Scope: The identifier is global to the script and available after its declaration.

    Example: Storing a property in a variable

    <span data-sly-set.profile="${user.profile}">Hello, ${profile.firstName}</span>
    <a href="${profile.url}">Edit Profile</a>
  11. Use the `data-sly-use` block to expose logic

    master

    The data-sly-use block is used to instantiate logic (like a JavaScript file or an object) and make it available to the template.

    • Element: Always rendered (the attribute is removed).
    • Attribute value: Required; a String representing the object to instantiate.
    • Attribute identifier: Optional; the name used to access the logic. If omitted, the identifier defaults to useBean.
    • Scope: The identifier is global to the script and can be used anywhere after its declaration.
    • Parameters: You can pass parameters to the logic using expression options.
    • Usage: Can also be used to load external templates.

    Example: Instantiating a JS file and passing parameters

    <!--/* Basic usage with custom identifier */}
    <div data-sly-use.page="customPage.js">${page.foo}</div>
    
    <!--/* Usage with parameters */}
    <div data-sly-use.nav="${'Navigation' @ depth=1, showVisible=!wcmmode.edit}">${nav.foo}</div>
  12. Iterate with `data-sly-list` and `data-sly-repeat`

    master

    Both data-sly-list and data-sly-repeat are used for iteration, but they behave differently regarding the containing element.

    data-sly-list (Iterate inside element)

    • Behavior: The element is shown once. Its content is repeated for each item in the collection.
    • Element visibility: Shown only if the collection has > 0 items (or is a string/number).
    • Identifier: Defaults to item. Can be customized via data-sly-list.name.

    data-sly-repeat (Iterate the element itself)

    • Behavior: The element itself is repeated for each item in the collection.
    • Identifier: Defaults to item. Can be customized via data-sly-repeat.name.

    Shared Iteration Options and Helpers

    • Options: begin (start index), step (increment), end (inclusive end index).
    • itemList (or <variable>List): An object available in the loop containing:
      • index: 0-based counter.
      • count: 1-based counter.
      • first, middle, last: Boolean flags for position.
      • odd, even: Boolean flags based on count.

    Example: Using data-sly-list to build a list

    <!--/* data-sly-list: repeats content inside the <ul> */}
    <ul data-sly-list.childPage="${currentPage.listChildren}">
        <li>${childPage.title}</li>
    </ul>
    
    <!--/* data-sly-repeat: repeats the <p> tag itself */}
    <p data-sly-repeat.article="${articlesCollection}">${article.excerpt}</p>