Showing posts with label Sightly. Show all posts
Showing posts with label Sightly. Show all posts

Tuesday, August 9, 2016

HTL (Sightly) Chit Note - Part 1

In this article, I am going to create a chit note for frequently used HTL syntax that will come handy while working with AEM.

1. HTL does not support JSP tag libraries.


2. Including a script: data-sly-include instead of cq:include

<cq:include script="template.html"/> //Including a HTL file in JSP
<sly data-sly-include="template.jsp"/> //Including a JSP file in HTL

The element on which a data-sly-include has been set is ignored and not displayed.

3. Including a Resource: data-sly-resource

Includes the result of rendering the indicated resource through the sling resolution and rendering process. Basic syntax-

<article data-sly-resource="path/to/resource"></article>

Override resourceType of an include-
<article data-sly-resource="${'path/to/resource' @ resourceType='my/resource/type'}"></article>

Change the wcmmode-
<article data-sly-resource="${'path/to/resource' @ wcmmode='disabled'}"></article>

Include resource parent div


<sly data-sly-resource="${'btn1' @ resourceType='my/components/content/button', decoration=true}"></sly>

4. Changing element tag: data-sly-element

This replaces the element name of the host element-
<h1 data-sly-element="${titleLevel}">text</h1>

Replaces the h1 with the value of titleLevel.

For security reasons, data-sly-element accepts only limited element names.

5. Including clientlibs: data-sly-use and data-sly-call 

In a single statement-

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"
     data-sly-call="${clientlib.all @ categories=['myCategory1', 'myCategory2']}"/>

In Separate statements-

<!doctype html>
<html data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
    <head>
        <!-- HTML meta-data -->
        <css data-sly-call="${clientlib.css @ categories='myCategory'}"/>
    </head>
    <body>
        <!-- page content -->
        <js data-sly-call="${clientlib.js @ categories='myCategory'}"/>
    </body>
</html>


6. If Statement: data-sly-test

HTL uses data-sly-test block statement to implement "if" behavior. There is no direct if-else implementation. You need to utilize data-sly-test in an efficient manner to achieve this.

A). Positive condition: if
<h1 data-sly-test="${properties.jcr:title}"> ${properties.jcr:title}</h1>
Negative condition: else
<h1 data-sly-test="${!properties.jcr:title}"> ${pageProperties.name | "Untitled" }</h1>

You can also use relational operators i.e.- "<=", ">=", "==" etc. in your test condition.

B). Always cache test block statement results in an identifier if it repeats itself

<h1 data-sly-test.hasTitle="${properties.jcr:title}"> ${properties.jcr:title}</h1> //if
<h1 data-sly-test="${!hasTitle}"> ${pageProperties.name | "Untitled" }</h1> //else

7. data-sly-unwrap/ sly Element

AEM 6.0 (HTL1.0) has an attribute "data-sly-unwrap" to avoid rendering of referenced HTML tag in context. 

<!-- /* This */ -->
<p data-sly-use.nav="navigation.js" data-sly-unwrap>Hello World</p>

<!-- /* Produces */ -->
Hello World

<!-- /* you can also put condition in data-sly-unwrap */ -->

<p data-sly-unwrap="${someCondition}">Hello World</p>

The above statement will render the hosting element only when the condition evaluates to false. 

AEM 6.1 (HTL1.1) has introduced a new element- "sly" to achieve this. So it is suggested to use sly statement instead of data-sly-unwrap in HTL 1.1 onwards.

<sly data-sly-test="${someCondition}">Hello World</sly>

8. Iterating through a list: data-sly-list Element

<ul data-sly-list="${listObject}">
    <li>Index: ${itemList.index}, Value: ${item}</li>
</ul>

Here itemList provides following properties-
  • index : counter (0-n)
  • count : counter (1-n)
  • first : if the current item is the first item
  • middle: if the current item is neither the first nor the last item
  • last: if the current item is the last item
  • odd: if index is odd
  • even: if index is even
You can also rename the item/ itemList variable name (This is suggested approach to use identifiers instead of using default item naming)-

<dl data-sly-list.child="${currentPage.listChildren}">
    <dt>index: ${childList.index}</dt>
    <dd>value: ${child.title}</dd>
</dl>

9. Use of Display Context

To protect against cross-site scripting (XSS) vulnerabilities, HTL automatically recognises the context within which an output string is to be displayed within the final HTML output, and escapes that string appropriately.

<p style="color: ${properties.color @ context='styleToken'};"></p>
<p>URL: ${teaser.link @ context = 'uri'}</p>

${properties.jcr:title @ context='html'}    <!--/* Use for HTML output. Removes markup posing XSS risks */-->
${properties.jcr:title @ context='text'}     <!--/* Use for plain text content - Encodes all HTML */-->
${properties.jcr:title @ context='elementName'}   <!--/* Allows only white-listed element names, outputs 'div' otherwise */-->
${properties.jcr:title @ context='attributeName'} <!--/* Outputs nothing if the value doesn't map to a valid HTML attribute; Doesn't allow 'style' and 'on*' attributes */-->
${properties.jcr:title @ context='attribute'}     <!--/* Applies HTML attribute escaping */-->
${properties.jcr:title @ context='uri'}     <!--/* Outputs nothing if the value contains XSS risks */-->
${properties.jcr:title @ context='scriptToken'}   <!--/* Outputs nothing if value doesn't correspond to the JavaScript token syntax */-->
${properties.jcr:title @ context='scriptString'}  <!--/* Applies JavaScript string escaping */-->
${properties.jcr:title @ context='scriptComment'} <!--/* Context for Javascript block comments. Outputs nothing if value break out of the comment context */-->
${properties.jcr:title @ context='scriptRegExp'}  <!--/* Applies JavaScript Regex escaping */-->
${properties.jcr:title @ context='styleToken'}    <!--/* Outputs nothing if the value doesn't correspond to the CSS token syntax */-->
${properties.jcr:title @ context='styleString'}   <!--/* Applies CSS string escaping */-->
${properties.jcr:title @ context='styleComment'}  <!--/* Context for CSS comments. Outputs nothing if value break out of the comment context */-->
${properties.jcr:title @ context='comment'}       <!--/* Applies HTML comment escaping */-->
${properties.jcr:title @ context='number'}        <!--/* Outputs zero if the value is not a number */-->
${properties.jcr:title @ context='unsafe'}  <!--/* Use at your risk, this disables XSS protection */-->

10. HTL Comments:

<!--/* An HTL Comment */-->


11. Formatting in Expression:

To format string, you can use Numbered parameters for injecting variables:

${'Assets {0}' @ format=properties.assetName}   <!--/* A shortcut of the array notation, useful when it has one element */-->
${'Assets {0}' @ format=[properties.assetName]}
${'Assets {0} - {1} of {2}' @ format=[properties.first, properties.last, properties.total]}

12. i18n: Internationalization

Following syntax is used to localize string literals in HTL-

${'Assets' @ i18n} <!--/* Translates the string to the resource language */-->

${'Assets' @ i18n, locale='en-US', hint='Translation Hint'} <!--/* Complete syntax with locale and hint options */-->

The i18n option can be combined with the format option, which replaces the placeholders after the string has been run through the dictionary:

${'Assets {0} - {1} of {2}' @ i18n, format=[properties.first, properties.last, properties.total]}

13. Array Join: Implode function

The join option allows to control the output of an array object by specifying the separator string.

${['one', 'two'] @ join='; '} <!--/* outputs: one; two */-->

14. URI Manipulation

Following options are available-
  • scheme (To prepend with http/ https)
    ${'http://example.com/path/page.html' @ scheme='https'} <!-- outputs: https://example.com/path/page.html -->
  • domain
    ${'///path/page.html' @ domain='example.org'} <!-- outputs: //example.org/path/page.html -->
  • path
    ${'http://example.com/this/one.selector.html/suffix?key=value#fragment' @ path=''} <!-- outputs: http://example.com/this/one.selector.html/suffix?key=value#fragment -->
  • prependPath
  • appendPath
    ${'path/page.selector.html/suffix?key=value#fragment' @ appendPath='appended'} <!-- outputs: path/page/appended.selector.html/suffix?key=value#fragment -->
  • selectors
  • addSelectors
  • removeSelectors
  • extension
    ${'path/page.json#fragment' @ extension='html'} <!-- outputs: path/page.html#fragment -->
  • suffix
    ${'path/page.html?key=value' @ suffix='my/suffix'} <!-- outputs: path/page.html/my/suffix?key=value -->
  • prependSuffix
  • appendSuffix
  • query
    ${'http://www.example.org/search?s=1&q=htl' @ query} <!-- outputs: http://www.example.org/search -->
  • addQuery
  • removeQuery
  • fragment
    ${'path/page#one' @ fragment='two'} <!-- outputs: path/page#two -->


References:

Monday, August 8, 2016

HTL (Sightly) Chit Notes Part-2

15. Java Use API

Format to call in html file-

<sly  data-sly-use.javaUseClassName="apps.mycomponent.MyComponent @title='Test Title'">${javaUseClassName.someProperty} </sly> 

Here class name is used without extension.  You cannot pass argument to a method. But it is possible to pass argument at the activation of the Java/Javascript class.

16. JavaScript Use API

<sly  data-sly-use.jsUseClassName="${'mycomponent.js' @ fieldValue =resource.valueMap}">${jsUseClassName.jsonVal}</sly>

Sample js file content -

"use strict";

use(function () {

var nodeJson = JSON.parse(this.fieldValue);
var title = currentPage.getTitle();

var description = properties.get("jcr:description", "default desc");

return {
   jsonVal: nodeJson,
   title: title,
   description: description
}
});

17. Template & Call

Template blocks can be used like function calls: in their declaration they can get parameters, which can then be passed when calling them. They also allow recursion. This consist of following steps:

A. Define A Template: data-sly-template

Template can be defined in a static or dynamic way-

<template data-sly-template.templateOne>blah</template> <!--/* Static Template */-->

<template data-sly-template.templateTwo="${ @ title, resource='The resource of parent node'}"><h1>${title}</h1>
<p>Parent: ${resource.name}</p></template> <!--/* Dynamic Template, with parameter- title and resource */-->

Note that the host element and its content are not output by HTL.

B. Call The Template: data-sly-call

Calling a static template defined above-

<div data-sly-call="${templateOne}"></div>

Calling the dynamic template with parameters-

<div data-sly-call="${templateTwo @ title=properties.jcr:title, resource=resource.parent}"></div>

C. Externalizing The Template (Optional Step): data-sly-use

When templates are located in a separate file, they can be loaded with data-sly-use:

<div data-sly-use.lib="templateLib.html" data-sly-call="${lib.templateOne}"></div>
<div data-sly-call="${lib.templateTwo@ title=properties.jcr:title, resource=resource.parent}"></div>

CDN | Clearing Cloudflare cache

In order to clear Cloudflare cache automatically via code, follow below steps: 1. Develop Custom TransportHandler Develop a custom Trans...