HTL(Sightly) - All you need to know

Post on 20-Mar-2017

48 views 9 download

transcript

www.tothenew.com

HTML Template Language

www.tothenew.com

Agenda

● What is HTL?● Why HTL?● Global Objects● HTL Block Statements● HTL Use-API● HTL Expression Options● Best Practises

www.tothenew.com

What is HTML Template Language (HTL)?

● Introduced with AEM 6.0● Takes the place of JSP as the preferred server-side template system

for HTML● Enforces separation of concerns between Presentation & Business

logic● A HTL file contains HTML, some basic presentation logic and

variables to be evaluated at runtime● Sightly was renamed to “HTML Template Language” from August

2016

www.tothenew.com

Why HTL?

● Simplified Development: ○ Purposely limited features: Easy to learn and enforces strict

separation of concerns between markup and logic.○ HTL template is itself a valid HTML5 file: Doesn't break the validity of

the markup and keeps it readable○ Allows HTML developers without Java knowledge and with little

product-specific knowledge to be able to edit HTL templates○ Allows Java developers to focus on the back-end code without

worrying about HTML

After Sightly

www.tothenew.com

Why HTL?

● Increased Security:

○ HTL automatically filters and escapes all text being output to the presentation layer to prevent cross-site-scripting(XSS) vulnerabilities.

○ Automatically applies the proper context-aware escaping to all variables being output to the presentation layer

www.tothenew.com

AEM HTL Read–Eval–Print Loop

● To try out basic HTL, a live execution environment called the Read Eval Print Loop can be used.

● Download Link & documentation:https://github.com/Adobe-Marketing-Cloud/aem-htl-repl

● After package installation, go to /content/repl.html

?

www.tothenew.com

HTL Syntax

• Every HTL file is an HTML5 document or fragment, augmented with a specific syntax that adds the dynamic functionality.

There are two different kind of Syntaxes:-

• HTL Block Statements:- To define structural block elements within HTL file, HTL employs HTML5 data attributes. This allows to attach behavior to existing HTML elements. Block statements can't be used inside html comments, style n script elements. A block statement starts with data-sly.

• HTL Expressions:- HTL expressions are delimited by characters ${ and }. At runtime, these expressions are evaluated and their value is injected into the outgoing HTML stream. Expressions can only be used in attribute values, in element content, or in comments.

www.tothenew.com

Example

<h1 data-sly-test="${currentPage.title}">    <a href="${currentPage.path}.html">        ${currentPage.title}    </a></h1>

• Output

<h1>    <a href="/content/my%20page.html">        My page title&#x21;    </a></h1>

www.tothenew.com

Useful Objects Available

• properties• pageProperties• Component• currentDesign• currentPage• log• out• pageManager• request• resource• response• sling• wcmmode

www.tothenew.com

Comments

HTL comments are HTML comments with additional syntax. They are delimited like this:

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

However, the content of standard HTML comments, delimited like this:<!-- An HTML Comment -->

will be passed through the HTL processor and expressions within the comment will be evaluated.

www.tothenew.com

HTL Block Statements

● dat-sly-test

● data-sly-resource

● data-sly-include

● data-sly-attribute

● data-sly-element & data-sly-text

● data-sly-list

● data-sly-template & dat-sly-call

● data-sly-use

● data-sly-unwrap

www.tothenew.com

data-sly-test

• Conditionally removes the host element and it‘s content if an expression evaluates to false.

• Values that can be converted to false are: undefined variables, null values, the number zero, and empty strings.

• data-sly-test also sup ports the naming and reuse of tests.

Example

<div data-sly-test.author="${wcmmode.edit || wcmmode.design}"> Show this to the author

</div> <div data-sly-test="${!author}">

Not in author mode anymore.. </div>

www.tothenew.com

• data-sly-include : Includes the output of a rendering script run with the current context, passing back control to the current Sightly script.

<div data-sly-include="template.html"></div><div data-sly-include="template.jsp"></div>

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

data-sly-include

www.tothenew.com

data-sly-resource

• Includes a rendered resource from the same server, using an absolute or relative path.Examples:<div data-sly-resource="${ @path='par', resourceType='foundation/components/parsys'}"/>With an expression more options can be specified:<section data-sly-resource="${'my/path' @ appendPath='appended/path'}"></section><section data-sly-resource="${'my/path' @ prependPath='prepended/path'}"></section>

Manipulating selectors:<section data-sly-resource="${'my/path' @ selectors='selector1.selector2'}" /><section data-sly-resource="${'my/path' @ addSelectors=['selector1', 'selector2']}" /><section data-sly-resource="${'my/path' @removeSelectors=['selector1','selector2']}" />

By default, the AEM decoration tags are disabled, the decorationTagName option allows to bring them back, and the cssClassName to add classes to that element.

<article data-sly-resource="${'path/to/resource' @ decorationTagName='span',cssClassName='className'}"></article>

www.tothenew.com

data-sly-attribute

• Sets an attribute or a group of attributes on the current element :<tag class="className" data-sly-attribute.class="${myVar}"></tag> This overwrites the content of the class attribute

Assuming that foobar = {'id' : 'foo', 'class' : 'bar'} ,<input data-sly-attribute="${foobar}" type="text"/>outputs : <input id="foo" class="bar" type="text"/>

• Attributes are processed left-to-right :<div class="bar1" data-sly-attribute.class="bar2" data-sly-attribute="${foobar}"></div>outputs: <div id="foo" class="bar"></div>

www.tothenew.com

• Changes the element, mostly useful for setting element tags like h1..h6, th, td, ol, ul :

<div data-sly-element"${'h1'}">Sightly Element Example</div>outputs: <h1>Sightly Element Example</h1>

For security reasons, data-sly-element accepts only the following element names: a abbr address article aside b bdi bdo blockquote br caption cite code col colgroup data dd del dfn div dl dt em figcaption figure footer h1 h2 h3 h4 h5 h6 header i ins kbd li main mark nav ol p pre q rp rt ruby s samp section small span strong sub sup table tbody td tfoot th thead time tr u var wbr

data-sly-text

• Replaces the content of its host element with the specified text.

<p data-sly-text="${properties.jcr:description}">Lorem ipsum</p>

data-sly-element

www.tothenew.com

data-sly-list● Repeats the content of the host element for each property in the provided

object.<ul data-sly-list="${currentPage.listChildren}"> <li> index: ${itemList.index}, value: ${item.title} </li> </ul><ul data-sly-list.child="${myObj}">

<li> key: ${child}, value: ${myObj[child]} </li></ul>

● itemList holds the following properties:index: zero-based counter (0..length-1).count: one-based counter (1..length).first: true if the current item is the first item.middle: true if the current item is neither the first nor the last item.last: true if the current item is the last item.odd: true if index is odd.even: true if index is even.

www.tothenew.com

● Template blocks can be used like function calls:

○ Parameters can be passed when calling templates.

○ They also allow recursion.

● Template Declaration :

<template data-sly-template.example="${@ class, text}">

<span class="${class}">${text}</span>

</template>

● Call Statement :

<div data-sly-call="${example @ class=‘css-class', text='Hi'}"></div>

● Output:

<div><span class="css-class">Hi</span></div>

Template & Call Statements

www.tothenew.com

• Initializes a helper object (defined in JavaScript or Java) and exposes it through a variable:

JS: <div data-sly-use.page="customPage.js">${page.foo}</div>Java: <div data-sly-use.nav="Navigation">${nav.foo}</div>

• Parameters can be passed to the Use-API by using expression options:<div data-sly-use.nav="${'Navigation' @ depth=1,showVisible=!wcmmode.edit}">

${nav.foo}</div>

• Also used to load data-sly-template markup snippets located in a different file :

data-sly-use

<!-- library.html --><template data-sly-template.foo="${@ text}"> <span class="example">${text}</span></template>

<!-- template.html --><div data-sly-use.library="library.html" data-sly-call="${library.foo @ text='Hi'}"> </div>

Output:<div><span class="example">Hi</span></div>

www.tothenew.com

HTL Use-API

Java Use-API JavaScript Use-API

Pros ● faster● can be inspected with a

debugger● easy to unit-test

● can be modified by front-end developers

● is located within the component, keeping the view logic of a component close to its corresponding template

www.tothenew.com

Java Use-API enables a HTL file to access helper methods in a custom Java class.

1. Implementing Use interface:

public class HTLComponent implements Use { @Override public void init(Bindings bindings) { Resource resource = (Resource)bindings.get("resource"); ValueMap properties = (ValueMap)bindings.get("properties");

// Parameters passed to the use-class String param1 = (String) bindings.get("param1");

}

In AEM 6.2, io.sightly.java.api.Use is deprecated, org.apache.sling.scripting.sightly.pojo.Use is used instead.

Java Use-API

www.tothenew.com

Java Use-API

2. Extend WCMUsePojo class:

public class HTLComponent extends WCMUsePojo { private String myTitle; @Override

public void activate() { String text = get("text", String.class);myTitle = "My Project " + text + getCurrentPage().getTitle()

+ “ : ” + getProperties().get("title", ""); }public String getMyTitle() { return myTitle; }

}

In AEM 6.2, WCMUse is deprecated, com.adobe.cq.sightly.WCMUsePojo used instead.

www.tothenew.com

• If the Java source file is in the same folder as the HTL file<div data-sly-use.nav="Navigation">${nav.foo}</div>

Otherwise,<div data-sly-use.nav="com.htl.model.Navigation">${nav.foo}</div>

• HTL Use-API resolutionFind a Java UseClass in the same directory OR with a fully qualified class nameTry to adapt the current Resource/Request to UseClass, if unsuccessful, try to

instantiate UseClass with a zero-argument constructor.Within HTL, bind the newly adapted or created object to the localName.If UseClass implements the Use interface then call the init method, passing the

current execution context (a javax.scripting.Bindings object).UseClass extending WCMUse is a special case of implementing Use providing the

convenience context methods and its activate method is automatically called from Use.init.

If UseClass is a path to a HTL file containing a data-sly-template, prepare the template.

Otherwise, if UseClass is a path to a JavaScript use-class, prepare the use-class.

data-sly-use (cont.)

www.tothenew.com

• Enables a HTL file to access helper code written in JavaScript.• Allows all complex business logic to be encapsulated in the JavaScript code, while the HTL

code deals only with direct markup production.

use(function () { var Constants = { DESCRIPTION_PROP: "jcr:description", DESCRIPTION_LENGTH: 50 }; var title = currentPage.getNavigationTitle() || currentPage.getTitle() || currentPage.getName();var description = properties.get(Constants.DESCRIPTION_PROP, "").substr(0, Constants.DESCRIPTION_LENGTH); return { title: title, description: description };});

data-sly-use JavaScript Use Api

www.tothenew.com

Client libraries helper template library

The client libraries helper template library (/libs/granite/HTL/templates/clientlib.html) can be loaded through data-sly-use and stored in a clientLib block element variable. Loading the library's CSS style sheets and JavaScript is done through data-sly-call. The clientLib template library exposes three templates:

• css - loads only the CSS files of the referenced client libraries• js - loads only the JavaScript files of the referenced client libraries• all - loads all the files of the referenced client libraries

www.tothenew.com

Client libraries helper template library Example

<head data-sly-use.clientLib="${'/libs/granite/HTL/templates/clientlib.html'}">

<css data-sly-call="${clientLib.css @ categories=['category1', 'category2']}" data-sly-unwrap/>

</head><body> <!-- content --> <js data-sly-call="${clientLib.js @ categories=['category1',

'category2']}" data-sly-unwrap/></body>

www.tothenew.com

• The <sly> HTML tag can be used to remove the current element, allowing only its children to be displayed:

<sly data-sly-test="${event.hasDate}" > <span>Hello</span>

</sly>• Its functionality is similar to the data-sly-unwrap block element :

<div data-sly-test="${event.hasDate}" data-sly-unwrap> <span>Hello</span>

</div>

Both Output : <span>Hello</span>

• Although not a valid HTML 5 tag, the <sly> tag can be displayed in the final output using data-sly-unwrap:

<sly data-sly-unwrap="${false}"></sly>outputs: <sly></sly>

<sly> & data-sly-unwrap

www.tothenew.com

Expression Options

www.tothenew.com

Display Context Option

The context option offers control over escaping and XSS protection.

• Allowing some HTML markup (filtering out scripts)<div>${‘<p>Hello</p>’ @ context='html'}</div>

Without context : &lt;p&gt;hello&lt;/p&gt;

• Adding URI validation protection <p data-link="${link @ context='uri'}">text</p>

• Applying CSS string escaping <style> a { font-family: "${myFont @ context='styleString'}"; } </style>

www.tothenew.com

Display Context Option

Context Use• html• text • elementName• uri • scriptString • scriptComment • scriptRegExp • styleString • styleComment • comment • number • unsafe

Outputs HTML - Removes markup that may contain XSS risks For simple HTML content - Encodes all HTML Allows only element names that are white-listed, else outputs 'div'To get valid Href link or pathApplies JavaScript string escaping For JavaScript block commentsTo apply JavaScript regular expression escaping To apply CSS string escaping For CSS commentsTo apply HTML comment escaping Outputs zero if the value is not a number Disables XSS protection completely, use this at your own risk.

www.tothenew.com

String Format Option

Numbered parameters can be used for injecting variables:

${'Assets {0}' @ format=properties.assetName}OR

${'Assets {0}' @ format=[properties.assetName]}

${'Page {0} of {1}' @ format=[current, total]}

Array Join Option

The join option allows to control the output of an ahorray object by specifying the separator string. This can for e.g. be useful for setting class-names

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

<span class="${myListOfClassNames @ join=' '}"></span>

www.tothenew.com

Internationalization (@i18n)

To translate a string to the resource language:

${'Assets' @ i18n}

Two more options can be used with i18n:• locale : Overrides the language from the source. For e.g.: en-US or fr-CH• hint : Allows to provide some information about the context for the translators.

${'Assets' @ i18n, locale='en-US', hint='Translation Hint'}

www.tothenew.com

URI Manipulation

• Scheme - Allows adding or removing the scheme part for a URI : ${'example.com/path/page.html' @ scheme='http'}outputs: http://example.com/path/page.html

${'http://example.com/path/page.html' @ scheme='https'}outputs: https://example.com/path/page.html

• Domain - Allows adding or replacing the host and port (domain) part for a URI : ${'///path/page.html' @ domain='example.org'}outputs: //example.org/path/page.html

${'http://www.example.com/path/page.html' @ domain='www.example.org'}outputs: http://www.example.org/path/page.html

www.tothenew.com

URI Manipulation

Path / prependPath / appendPath – Modify the path that identifies a resource :

${'http://example.com/this/one.selector.html/suffix?key=value’@ path='that/two'}outputs: http://example.com/that/two.selector.html/suffix?key=value#

${'http://example.com/this/one.selector.html/suffix?key=value' @ path=‘’}outputs: http://example.com/this/one.selector.html/suffix?key=value

${'path' @ prependPath='..'}outputs: ../path

${'http://example.com/path/page.html' @ prependPath='foo'}outputs: http://example.com/foo/path/page.html

${'one' @ appendPath='two'}outputs: one/two

www.tothenew.com

URI Manipulation

Selectors / addSelectors / removeSelectors - Modifies or removes the selectors from a URI:

${'path/page.woo.foo.html' @ selectors='foo.bar'}outputs: path/page.foo.bar.html

${'path/page.woo.foo.html' @ selectors=['foo', 'bar']}outputs: path/page.foo.bar.html

${'path/page.woo.foo.html' @ addSelectors='foo.bar'}outputs: path/page.woo.foo.bar.html

${'path/page.woo.foo.html' @ removeSelectors=['foo', 'bar']}outputs: path/page.woo.html

www.tothenew.com

URI Manipulation

query / addQuery / removeQuery- adds, replaces or removes the query segment of a URI, depending on the contents of its map value :

assuming that jsuse.query evaluates to: { "query": { "q" : "sightly", "array" : [1, 2, 3] } }

${'http://www.example.org/search' @ query=jsuse.query}outputs: http://www.example.org/search?q=sightly&amp;array=1&amp;array=2&amp;array=3

${'http://www.example.org/search?s=1' @ addQuery=jsuse.query}outputs: http://www.example.org/search?s=1&amp;q=sightly&amp;array=1&amp;array=2&amp;array=3

${'http://www.example.org/search?s=1&q=sightly' @ removeQuery=['s', 'q']}outputs: http://www.example.org/search

www.tothenew.com

URI Manipulation

• Extension - adds, modifies or removes the extension from a URI: ${'path/page.json?key=value' @ extension='html'}outputs: path/page.html?key=value

${'path/page.json#fragment' @ extension='html'}outputs: path/page.html#fragment

• fragment - adds, modifies or replaces the fragment segment of a URI :${'path/page' @ fragment='fragment'}

outputs: path/page#fragment

${'path/page#one' @ fragment='two'}outputs: path/page#two

${'path/page#one' @ fragment}outputs: path/page

www.tothenew.com

Best practices

● Abuse of sly

● HTL comments instead of Html comments

● Reuse code using templates

● Use api to be used only when the HTL file alone is not enough to

implement logic

● Javascript use is slower than Java use class so use Javascript only for

less intensive logic

● Use local java use class if the class is used only for that component,

otherwise create a bundle use class

● Passing a parameter to a use-class should only be done when the use-

class is used in a data-sly-template file which itself is called from another

HTL file with parameters that need to be passed on.

www.tothenew.com

Moving from JSP to HTL

• Components written in HTL are compatible with components written in JSP or ESP.

A JSP can include a HTL file like this,• <cq:include script="footer.html"/>and a HTL file can include a JSP like this,<div data-sly-include="footer.jsp"></div>

www.tothenew.com

• HTL Specification :https://docs.adobe.com/docs/en/htl/overview.htmlhttps://github.com/Adobe-Marketing-Cloud/sightly-spec/blob/master/SPECIFICATION.md#31-sly

• Gabriel Walt’s Slideshare PPT:http://www.slideshare.net/GabrielWalt/component-development

• http://www.netcentric.biz/blog/2015/08/aem-sightly-style-guide.html

• http://www.citytechinc.com/content/dam/circuit/Component%20Development.pdf

• http://stackoverflow.com/questions/27583326/expression-option-sightly

References

www.tothenew.com