Skip to content

Extensions to Adobe Sightly / HTL to work with Composum Pages

License

Notifications You must be signed in to change notification settings

ist-dresden/cpm-platform-htl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTL integration with Composum Pages

Scope

This is an initial approach to integrate the Adobe HTL Expression Language (formerly called Sightly) with the Composum Pages framework.

Unfortunately HTL is quite limited in it's expressiveness, and does not (yet?) support an equivalent of JSP tag libraries. Since the Composum Tag libraries are an important part of the Pages framework, this is a bit limited, and thus not recommended for production usage. There is a somewhat limited adapter that allows using the Composum tags within HTL, which uses one HTL template for the tag start and one for the tag end. Obviously this cannot hide or change the content of the tag, as it is possible in JSP, and it is more verbose.

This project provides the UseProviders that enable the creation of Composum models within HTL, and the discussed Tag adapter. As an example, the test artefact defines a search component completely with HTL.

More details please find here.

What is HTL?

The HTML Template Language HTL (formerly called Sightly) is a modern replacement for JSP that provides the dynamic behaviour by using HTML5 like data attributes and using HTML elements as block statements, and provides enhanced security against XSS by tightly integrating with HTML syntax and automatically escaping data properly.

Integration with Composum models

The ComposumModelUseProvider extends the HTL Java Use-Api such that an object is also created if it can be created with BeanContext.adaptTo, which supports the creation of both SlingBeans and Pages Models with or without Sling-Models. Thus, to create a model is as easy as e.g.

// no parameters
<sly data-sly-use.someobject="foo.bar.SomeClass">
// with parameters
<sly data-sly-use.someobject="${'foo.bar.SomeClass' @ parameter=resource}">

Replacement for Composum Tag libraries

Since HTL there is no direct counterpart for JSP tag libraries, there is a partial emulation of the composum tag libraries as HTL templates. Unfortunately the data-sly-call to a template cannot access the elements content where the call is placed at. Thus, the usual JSP mechanisms for wrapping some content into a custom tag that modifies it and possibly adds variables valid in that context cannot be easily be carried over.

As a workaround the tags that expect content have to be split into templates, one for the start and one for the end of the tag. For instance the cpp:element Tag can be used as follows: 

<sly data-sly-call="${cpp.startElement @ var='field', type='com.composum.pages.components.model.search.SearchField'}"/>
... content that would be within a cpp:element tag in JSP ...
<sly data-sly-call="${cpp.endElement}"/>

If needed, the defined variable field (which is set in an emulated page context, to be comparable to the JSP mechanisms) from the HTL, it can be read as follows (see 'Further extensions' below):

<sly data-sly-use.field="${'com.composum.pages.components.model.search.SearchField' @ fromScope='page', key='field'}"/>

Further extensions

The emulated page context

To enable communication between templates we implements a kind of pagecontext for HTL by putting a map into a request attribute. There are separate maps for each script name - that is, the resource of the script. The emulated page context can be accessed from the Composum tags, or via the AttributesUseProvider (see below).

Access request / session / page context attributes

The AttributesUseProvider allows reading request- or session-attributes or the EmulatedPageContext with a data-sly-use statement such that the IDE knows the specific class and can provide code-completion etc. This use provider is activated whenever the "fromScope" parameter is present. Usage example (reads the search result from a request attribute searchresult):

<sly data-sly-use.searchresult="${'com.composum.pages.commons.service.search.SearchService.Result' @ fromScope='request', key='searchresult'}"/>: 

Possible scopes (case insensitive) are bindings for the script bindings, page for the emilated page context, and request and session.

It is also possible to explicitly pass a value with parameter value to effect a IDE-visible typecast. (The given value is not changed).

Setting request / session / page context attributes

The AttributeHelper allows setting and reading request-/session-attributes, request parameters, script bindings or a simulated pageContext (EmulatedPageContext) since there is no standard HTL way to read, much less set, those. If there should be something written, the parameter scope should be one of bindings, page, request, session (page being the emulated page context), and there can be a key and value parameter to set one value, or an arbitrary number key1, key2, key3 ... and corresponding value1, value2, value3, ... parameters to set the values in that scope. Example:

<sly data-sly-use.attrs="${'com.composum.platform.htl.AttributeHelper' @ scope='page', key='themodel', value=model}"></sly>
<sly data-sly-use.attrs="${'com.composum.platform.htl.AttributeHelper @ scope='page', key1='something', value1=foo", key2='else', value2=bar}"></sly>

It also allows reading request and session attributes and the emulated page context by providing maps requestAttributes and sessionAttributes and pageContext:

<sly data-sly-use.attrs="com.composum.platform.htl.AttributeHelper">${attrs.requestAttributes['sling.core.current.servletName']}</sly>

The UseWithRenderContext interface

To be able to access the org.apache.sling.scripting.sightly.render.RenderContext from models, these can extend the UseWithRenderContext interface.

Usage-Patterns

Tips

Some of the less obvious things:

If you use of the injector-specific annotations, adding @Inject is unneccesary. These annotations can be recognized by carrying the @InjectAnnotation annotation.

Links

Limitations

  • The JSP Expression language cannot be used in the Composum Tags when these are used in HTL.

Implementation concerns

Extension points of HTL: 

  • org.apache.sling.scripting.sightly.use.UseProvider provides ways to instantiate the objects for data-sly-use blocks; the ComposumModelUseProvider is a UseProvider that instantiates Sling-Models also from a BeanContext.
  • org.apache.sling.scripting.sightly.extension.RuntimeExtension : handler for various built in functions, see RuntimeFunction. Could e.g. be used to extend i18n to the Composum Pages way, or extend uriManipulation or includeResource with additional arguments or functionality.

Misc. findings

Defining a global with use within a template doesn't work - that's only local to the template. Thus, a template cannot declare global variables. (Idea: special composum variables as one model composum).
Statements in a template library are not executed when loading - HTL just takes the templates out of there.
Unknown variables are taken from the bindings, but are initialized before everything else, so we can't define additional globals.
The bindings passed on by the Java Use-Api are freshly generated - if it's neccesary to keep something permanently, one needs to put it into the request attributes.

Limitations of HTL

When trying to carry over the concept of tag libraries to HTL, there are the following limitations that hurt the possibilities:

  • data-sly-call on an element throws away the content of the element. Thus, it is not possible to modify, conditionally throw away, or repeat the content of the element, or easily surround some content with a computed number of elements.
    • Partial solution: split up the tags with content into a start and an end template. Problem: functionality that concerns the content of a tag cannot be implemented, and no variables for the content of the tag can be set. (Possible extension of HTL: the content of the data-sly-call element could be delivered to the template e.g. as a RenderUnit as a binding variable, which could be rendered once or several times via a new mechanism.)
  • There seems no way to define something like functions as in a tag library. (Idea: Use-Provider that calls a static function and delivers the result? (→ no IDE support.) Special class for each taglib function with constructor parameters corresponding to the arguments of the taglib function?)
  • In a template the parameters cannot be documented. Thus, it is not possible to see documentation within the IDE.
  • It is not possible to modify the global variables from a template. Thus, it its not possible to emulate a tag like cpp:defineObjects that defines several objects at once - the closest you can do is to create a model class that has several attributes with the objects to define. (Mostly OK; perhaps HTL could be extended that a template could also define some models, not only templates.).
  • data-sly-use for template libraries etc. does not use the resource search path (/apps, /libs, ...)
  • To output an attribute of type URI one needs to insert .toString - URI are silently swallowed.

Open points / possible extensions

  • Model that extends ResourceHandle and can provide e.g. inheritedValues (while setting the inheritancetype). Partial solution: <sly data-sly-use.resourceHandle="com.composum.sling.core.ResourceHandle" />
  • EL Function equivalents
  • Model that provides the defineObjects functionality

About

Extensions to Adobe Sightly / HTL to work with Composum Pages

Resources

License

Stars

Watchers

Forks

Packages

No packages published