CSS Styles Inliner: Technical documentation - adobe/aem-core-email-components GitHub Wiki

CSS Styles Inliner

Overview

This document is intended to provide information about how CSS styles inliner service work and what its expected behavior is.

Technical details

The entry point is the class StylesInlinerService/Impl. Its core is derived from Eli Lilly project source code.

Execution can be invoked by calling the getHtmlWithInlineStyles() method, which takes the following arguments:

  1. resourceResolver: org.apache.sling.api.resource.ResourceResolver object, used to retrieve external CSS stylesheets;
  2. html: the actual HTML.

There is another entry-point, the getHtmlWithInlineStylesJson() method, which basically invokes the getHtmlWithInlineStyles() method and wraps the result in a JSON object with an "html" attribute. This method takes the following arguments:

  1. resourceResolver: org.apache.sling.api.resource.ResourceResolver object, used to retrieve external CSS stylesheets;
  2. html: the actual HTML;
  3. charset: the charset of the HTTP request.

The main actors involved in execution are:

  1. StyleExtractor: utility that extracts CSS from external links and from internal style tag.
  2. StyleSpecificityFactory: utility that calculates the CSS specificity of each CSS rule.
  3. StyleTokenizer: utility that parses the CSS file, splitting it into a list of StyleToken objects. Every StyleToken contains a single CSS rule, along with its selectors, properties and CSS specificity.
  4. StyleTokenFactory: utility that simplifies StyleTokens handling (creation and update).
  5. StyleMerger: utility that merges CSS style already present in HTML components with that coming from CSS stylesheet.

Execution is automatically triggered by:

  1. StylesInlinerFilter, a filter that is invoked when the email page is called with both the "campaign" and "content" selectors and the "json" extension: this way, the getHtmlWithInlineStylesJson() method is called and the result is the JSON object containing the HTML with inline styles.
  2. StylesInlinerServlet, a servlet that is invoked when the email page is called with the "inline-styles" selector and the "html" extension: this way, the getHtmlWithInlineStyles() method is called and the result is the HTML with inline styles.

Execution steps

  1. The HTML document is parsed using Jsoup (see Jsoup)
  2. The CSS style is retrieved by StyleExtractor
  3. The CSS style is parsed by StyleTokenizer
  4. The HTML page is fully sanitized (see https://github.com/adobe/aem-core-email-components/wiki/HTML-sanitizing:-Technical-documentation)
  5. Style is merged with HTML components by StyleMerger
  6. HTML attributes are created if there are styles matching the HTML inliner configuration (see https://github.com/adobe/aem-core-email-components/wiki/HTML-Inliner:-Technical-documentation)
  7. Wrapper DIVs are removed (see https://github.com/adobe/aem-core-email-components/wiki/Wrapper-DIV-remover:-Technical-documentation)
  8. If there are CSS rules unmatched or non-inlinable, are added to the resulting HTML page in "style" tag
  9. Result is returned
  10. If any error occurs during these steps, a StylesInlinerException is thrown (it will wrap the original exception/error)

Tests and coverage

There are multiple jUnit classes that cover the features requested for the CSS Styles Inliner. The code coverage (retrieved from Intellij Idea Coverage window) is:

  1. Class: 100%
  2. Method: 93%
  3. Lines: 87%