Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A style guide for the HTML Template Language (HTL), the templating language use by the Adobe Experience Manager (AEM).

License

NotificationsYou must be signed in to change notification settings

Netcentric/aem-htl-style-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 

Repository files navigation

A style guide for theHTML Template Language (HTL), formerly known as Sightly, the HTML templating system from Adobe Experience Manager (AEM).

Table of Contents

  1. HTML
  2. Comments
  3. Expression language
  4. Block statements

1. HTML

  • 1.1Avoid inline JavaScript or CSS.

    In order to encourage keeping a clean separation of concerns, HTL has by design some limitations for inline JavaScript or CSS. First, because HTL doesn't parse JavaScript or CSS, and therefore cannot automatically define the corresponding escaping, all expressions written there must provide an explicitcontext option. Then, because the HTML grammar ignores elements located inside a<script> or<style> elements, no block statement can be used within them.

    Therefore JavaScript and CSS code should instead be placed into corresponding.js and.css files. Data attributes are the easiest way to communicate values to JavaScript, and class names are the best way to trigger specific styles.

    <!--/* Bad */--><sectiondata-sly-use.teaser="com.example.TeaserComponent"class="teaser"><h2class="teaser__title">${teaser.title}</h2><script>varteaserConfig={skin:"${teaser.skin @ context='scriptString'}",animationSpeed:${teaser.animationSpeed @context='number'}};</script><style>        .teaser__title {font-size: ${teaser.titleFontSize @ context='styleToken'}        }</style></section><!--/* Good */--><sectiondata-sly-use.teaser="com.example.TeaserComponent"data-teaser-config="${teaser.jsonConfig}"class="teaser"><h2class="teaser__title teaser__title--font-${teaser.titleFontClass}">${teaser.title}</h2></section>

⬆ back to top

2. Comments

  • 2.1Use HTL comments.

    Normal HTML comments get rendered to the final markup. To keep the DOM clean, always use HTL comments over normal HTML comments.

    <!-- Never use HTML comments --><!--/* Always use HTL comments */-->

⬆ back to top

3. Expression language

  • 3.1Set a display context only if necessary

    In most cases you can leave out the display context, because it is determined automatically.

    <!--/* Bad */--><ahref="${teaser.link @ context = 'uri'}"></a><!--/* Good */--><ahref="${teaser.link}"></a>
  • 3.2Use the safest possible display context.

    From the following list of contexts, always choose the one closest to the top that fits your needs:
    number: For whole numbers (in HTML, JS or CSS)
    uri: For links and paths (in HTML, JS or CSS, applied by default forsrc andhref attributes)
    elementName: For HTML element names (applied by default bydata-sly-element)
    attributeName: For HTML attribute names (applied by default bydata-sly-attribute for attribute names)
    scriptToken: For JavaScript identifiers and keywords
    styleToken: For CSS identifiers and keywords
    scriptString: For text within JavaScript strings
    styleString: For text within CSS strings
    attribute: For HTML attribute values (applied by default for attribute values)
    text: For HTML text content (applied by default for any content)
    html: For HTML markup (it filters out all elements and attributes that could be dangerous)
    unsafe: Unescaped and unfiltered direct output

    <!--/* Bad */--><sectiondata-sly-use.teaser="com.example.TeaserComponent"class="teaser"><h4onclick="${teaser.clickHandler @ context='unsafe'}">${teaser.title}</h4><divstyle="color: ${teaser.color @ context='unsafe'};">        ${teaser.htmlContent @ context='unsafe'}</div></section><!--/* Good */--><sectiondata-sly-use.teaser="com.example.TeaserComponent"class="teaser"><h4onclick="${teaser.clickHandler @ context='scriptToken'}">${teaser.title}</h4><divstyle="color: ${teaser.color @ context='styleToken'};">        ${teaser.htmlContent @ context='html'}</div></section>
  • 3.3Avoid writing unnecessary expressions for literals.

    It might sound obvious, but an expression with just a string literal inside equals just that string literal.

    <!--/* Bad */--><slydata-sly-use.clientlib="${'/libs/granite/sightly/templates/clientlib.html'}">    ...</sly><!--/* Good */--><slydata-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">    ...</sly>
  • 3.4Avoid using the ternary operator unnecessarily.

    Take advantage of the logical|| operator to simplify your code.

    <!--/* Bad */--><divclass="${cssClass ? cssClass : 'my-class'}"></div><!--/* Good */--><divclass="${cssClass || 'my-class'}"></div>
  • 3.5Use the native URI manipulation capabilities of HTL.

    Rolling out a custom URI builder is error prone and hardcoding URL's is even worse. UseHTL URI Manipulation instead, in particular, theextension option.

    <!--/* Bad */--><ahref="${component.link}.html"></a><!--/* Good */--><ahref="${component.link @ extension = 'html'}"></a>
  • 3.6Drop Method Prefixes When Accessing Properties from Java Getter Functions.

    When following theJavaBeans naming conventions (as you should) to name your getter methods, you can access the properties with their property name directly. You should access properties this way for consistency and readability.

    <!--/* Bad */--><p>${component.getTitle}</p><ahref="${item.link}"data-sly-unwrap="${item.isActive}">...</a><!--/* Good */--><p>${component.title}</p><ahref="${item.link}"data-sly-unwrap="${item.active}">...</a>

⬆ back to top

4. Block statements

  • 4.1Use thesly tag name for all elements that are not part of the markup.

    HTML elements with the tag namesly are automatically getting unwrapped and will not be part of the final markup.

    <!--/* Bad */--><divdata-sly-include="content.html"data-sly-unwrap></div><!--/* Good */--><slydata-sly-include="content.html"></sly>
    <!--/* Bad */--><divdata-sly-resource="${item @ selectors='event'}"data-sly-unwrap></div><!--/* Good */--><slydata-sly-resource="${item @ selectors = 'event'}"></sly>
    <!--/* Bad */--><divdata-sly-test="${event.hasDate}"data-sly-unwrap>    ...</div><!--/* Good */--><slydata-sly-test="${event.hasDate}">    ...</sly>

    IMPORTANT - Thesly element will not automatically unwrap itself if you use HTL 1.0 (AEM 6.0). In that case, you still have to add thedata-sly-unwrap attribute.

    <!--/* Bad - HTL 1.0 */--><slydata-sly-include="content.html"></sly><!--/* Good - HTL 1.0 */--><slydata-sly-include="content.html"data-sly-unwrap></sly>
  • 4.2Try to placedata-sly-use statements only on top-level elements.

    Sincedata-sly-use identifiers are always global (https://docs.adobe.com/docs/en/htl/docs/use-api/java.html#Local%20identifier), these attributes should only be placed in the top-level element. That way one can easily see name clashes and also it prevents initializing the same object twice.

    <!--/* Bad */--><sectionclass="teaser"><h3data-sly-use.teaser="com.example.TeaserComponent">${teaser.title}</h3></section><!--/* Good */--><sectiondata-sly-use.teaser="com.example.TeaserComponent"class="teaser"><h3>${teaser.title}</h3></section>
  • 4.3Use meaningful identifier names.

    This will enhance the readability of your HTL scripts and and makes it easier for others to understand.

    <!--/* Bad */--><slydata-sly-use.comp="com.example.TeaserComponent">    ...</sly><!--/* Good */--><slydata-sly-use.teaser="com.example.TeaserComponent">    ...</sly>
  • 4.4Use lowerCamelCase for identifier names.

    Using lowerCamelCase (You start by making the first word lowercase. Then, you capitalize the first letter of each word that follows i.e.: "sampleIdentifierName") will help to increase the readability of your identifiers. Notice though thatHTL will internally only use (and log) full lowercase identifiers. Also dashes are not allowed for identifiers.

    <!--/* Bad */--><slydata-sly-use.mediagallery="com.example.MediaGallery">    ...</sly><!--/* Good */--><slydata-sly-use.mediaGallery="com.example.MediaGallery">    ...</sly>
  • 4.5Re-use expressions with identifiers

    If a test block statement is used multiple times, define an identifer and re-use it this way instead. This will allow the htl compiler to cache the expression result and will also make your code easier to read and understand.

    <!--/* Bad */--><sectiondata-sly-test="${!teaser.empty}"class="teaser">    ...</section><divdata-sly-test="${teaser.empty}"class="cq-placeholder"></div><!--/* Good */--><sectiondata-sly-test.hasContent="${!teaser.empty}"class="teaser">    ...</section><divdata-sly-test="${!hasContent}"class="cq-placeholder"></div>

    Similarly, if a generic expression is used multiple times, define an identifer withdata-sly-set and re-use it, for the same reasons stated above.

    <!--/* Bad */--><divdata-sly-unwrap="${!(wcmmode.edit || wcmmode.preview) || resource.hasChildren}"><slydata-sly-test="${resource.hasChildren}"...></sly><slydata-sly-test="${(wcmmode.edit || wcmmode.preview) && !resource.hasChildren}"....></sly></div><!--/* Good */--><divdata-sly-set.editMode="${(wcmmode.edit || wcmmode.preview)}"data-sly-set.hasChildren="${resource.hasChildren}"data-sly-unwrap="${!editMode || hasChildren}"><slydata-sly-test="${hasChildren}"...></sly><slydata-sly-test="${editMode && !hasChildren}"...></sly></div>
  • 4.6Use identifiers instead of the default “item” variable for list block statements.

    <!--/* Bad */--><uldata-sly-list="${tagList.tags}"class="tagList"><liclass="tagList__tag"><aclass="tagList__button"href="${item.url}">${item.title}</a></li></ul><!--/* Good */--><uldata-sly-list.tag="${tagList.tags}"class="tagList"><liclass="tagList__tag"><aclass="tagList__button"href="${tag.url}">${tag.title}</a></li></ul>
  • 4.7Place block statements before the regular HTML attributes.

    The reason for that is that regular HTML attributes might use HTL variables which have been declared in the same element viadata-sly-use. One should always declare things before using them. Also HTL block elements might influence if the element appears at all (viadata-sly-test) or multiple times (viadata-sly-repeat) and therefore are just too important to put them at the end of the attribute list. Further details inissue 25.

    <!--/* Bad */--><pclass="teaser__text"data-sly-test="${teaser.text}"></p><!--/* Good */--><pdata-sly-test="${teaser.text}"class="teaser__text"></p>
  • 4.8Use existing HTML elements for your block statements if possible.

    <!--/* Bad */--><slydata-sly-test="${!teaser.active}"><sectionclass="teaser"></section></sly><!--/* Good */--><sectiondata-sly-test="${!teaser.active}"class="teaser"></section>
  • 4.9Avoid theelement,attribute andtext block statements.

    It's a lot cleaner and explicit to write your HTL scripts without these block statements.

    <!--/* Bad */--><divdata-sly-element="${headlineElement}">${event.year}</div><adata-sly-attribute.href="${event.link}"href="#"></a><pdata-sly-text="${event.year}"class="event__year"></p><!--/* Good */--><h2>${event.year}</h2><ahref="${event.link}"></a><pclass="event__year">${event.year}</p>
  • 4.10Define your templates in a separate file.

    It's cleaner to create separate files for your template markup, so your HTL scripts will not get cluttered.

    <!--/* Bad */--><slydata-sly-use.teaser="com.example.TeaserComponent"><slydata-sly-template.teaserSmall="${@ title, text}"><h2>${title}</h2><p>${text}</p></sly><slydata-sly-call="${teaserSmall @ title=teaser.title, text=teaser.text}"></sly></sly><!--/* Good - Separate template file: "teaser-templates.html" */--><slydata-sly-template.teaserSmall="${@ teaserModel}"><h2>${teaserModel.title}</h2><p>${teaserModel.text}</p></sly><!--/* Good - HTL script */--><slydata-sly-use.teaser="com.example.TeaserComponent"data-sly-use.teaserTemplates="teaser-templates.html"><slydata-sly-call="${teaserTemplates.teaserSmall @ teaserModel=teaser}"></sly></sly>
  • 4.11Avoid using data-sly-test to set arbitrary variable bindings

    Instead of binding a variable withdata-sly-test, use the purposefully defineddata-sly-set. This avoids unintentionally hiding elements if the result of the expression evaluates to false (seeHTL expressions evaluating to false ) and/or stopping the evaluation of further block statements; This is specially difficult to debug when variousdata-sly-test statements affect the same element.

    <!--/* Instead of */--><slydata-sly-test="${person.firstName && person.lastName && person.image}"data-sly-test.fullName="${person.firstName} ${person.lastName}"><h1>${fullName}</h1><imgsrc=${person.image}" alt="${fullName}"/><!--/* Use */--><slydata-sly-test="${person.firstName && person.lastName && person.image}"data-sly-set.fullName="${person.firstName} ${person.lastName}"><h1>${fullName}</h1><imgsrc=${person.image}" alt="${fullName}"/>
  • 4.12Avoid unnecessary<sly> tags.

    It's cleaner and easier to understand your intentions if you add your block statements in the relevant elements directly instead of wrapping them with ansly tag.

    <!--/* Bad */--><slydata-sly-test.title="${component.title}"><h1>${title}</h1></sly><!--/* Good */--><h1data-sly-test.title="${component.title}">${title}</h1>
  • 4.13Use an explicit</sly> end tag to close<sly> tags.

    Becausesly is neither a void nor a foreign element (Seehtml5 start tags), it must be explicitly closed with an end tag</sly>. Using a self-closing tag isnot allowed.

    <!--/* Bad */--><slydata-sly-include="content.html"/><!--/* Good */--><slydata-sly-include="content.html"></sly>

⬆ back to top

License

The MIT License (MIT)

Copyright (c) 2015 Netcentric

Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE.

⬆ back to top

About

A style guide for the HTML Template Language (HTL), the templating language use by the Adobe Experience Manager (AEM).

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors7


[8]ページ先頭

©2009-2025 Movatter.jp