htl-compiler

    1.0.12 • Public • Published

    HTL Compiler

    Compile HTL templates in the browser or in Node. HTL is a HTML templating language originally created by Adobe and is now apart of the Apache Software Foundation.

    Usage

    Installation

    npm install htl-compiler --save

    Node.JS Usage

    const Compiler = require('htl-compiler');
     
    new Compiler(/* ... */).compile();

    ESM Module Usage

    import Compiler from '/node_modules/htl-compiler/dist/compiler-esm.js';
     
    new Compiler(/* ... */).compile();

    UMD Module Usage

    <script src="/node_modules/htl-compiler/dist/compiler-umd.js"></script>
     
    <script type="text/javascript">
      new Compiler(/* ... */).compile();
    </script> 

    The Rundown

    Given an HTL template provided as a string, and data provided as JSON, this compiler will output HTML.

    new Compiler("<div>${message}</div>", { message: "Hello, World!" }).compile();

    This will output what you would expect:

    <div>Hello, World!</div>

    The following features from the HTL Spec are supported:

    1. data-sly-repeat
    2. data-sly-list
    3. data-sly-test
    4. data-sly-resource
    5. data-sly-use
    6. data-sly-template
    7. data-sly-call
    8. data-sly-attribute
    9. <sly>

    In order to support the HTL concepts of use models and resources, you can also pass two additional parameters to the compiler:

    new Compiler(
      "<div>${message}</div>",
      {
        message: "Hello, World!"
        sampleResource: { /* The data that will be available to the sampleResource */ }
      },
      {
        "class.path.of.use.Model": { /* Data you want this use model to provide */ }
      },
      {
        "sampleResource": "<div>The template for the sampleResource. It will only have a subset of the data available to it.</div>"
      }
    ).compile();

    Usage

    Expressions

    Here is a simple hello world example:

    import Compiler from './src/compiler.js';
     
    const exampleHtml = `
      <div>\${myMessage}</div>
    `;
     
    const resourceResolver = {
      myMessage: "Hello, World!"
    }
     
    const compiledHtml = new Compiler(exampleHtml, resourceResolver).compile();
    // This will produce <div>Hello, World!</div>

    Use models

    Here is an example using use models:

    import Compiler from './src/compiler.js';
     
    const exampleHtml = `
      <sly data-sly-use.test="\${my.example.class.path.TestModel}"
      <div>\${test.messageFromTestModel}</div>
    `;
     
    const resourceResolver = {
      myMessage: "Hello, World!"
    }
     
    const useModels = {
      "my.example.class.path.TestModel": {
        title: "Hello from TestModel"
      }
    }
     
    const compiledHtml = new Compiler(exampleHtml, resourceResolver, useModels).compile();
    // This will produce <div>Hello from TestModel</div>
    Class Based Use Models

    You can also provide a class as a use model. It's constructor will receive a resource resolver. The resource resolvers resolve method will give you access to the resource data, however this comes in the form of a promise. For this reason you should resolve all of the data you need, perform your business logic, and then return a promise of the result in the methods that you expost to the template.

    class MyClass {
      constructor(resourceResolver) {
        this.namePromise = Promise.all(
          resourceResolver.resolve('firstName'),
          resourceResolver.resolve('lastName')
        ).then(name => name[0] + ' ' + name[1]);
      }
     
      name() {
        return this.namePromise;
      }
    }
     
    new Compiler(`
      <sly data-sly-use.example="some.example.class.path.MyClass">
      <div>\${example.name}</div>
      `,
      { firstName: 'Joe', lastName: 'Smith' },
      { 'some.example.class.path.MyClass': MyClass }
    ).compile()

    Resources

    Here is an example using resources:

    import Compiler from './src/compiler.js';
     
    const exampleHtml = `
      <div data-sly-resource="simple"></div>
    `;
     
    const resourceResolver = {
      simple: {
        nestedResourceData: "Hello from the simple resource"
      }
    }
     
    const resourceTypes = {
      "simple": "<div>\${nestedResourceData}</div>"
    }
     
    const compiledHtml = new Compiler(exampleHtml, resourceResolver, { }, resourceTypes).compile();
    // This will produce <div><div>Hello from the simple resource</div></div>

    Custom Resource Resolvers

    The second parameter to the compiler is the resource resolver. If you provide a JSON object (with no constructor) a static resource resolver will be used. That means that resource paths will simply resolve to the data at the specified location in the provided json structure. For example if you provide the below json as the second parameter:

    {
      "example": {
        "path": "hello"
      }
    }

    Then the resource at the example.path will evaluate to the string "hello".

    However you can provide your own resource resolver that resolves paths differently. In order to do this you must provide a class as the second parameter to the compiler that implements the following API:

    export default class StaticResourceResolver {
      setResourceData(identifier, jsonData) {
      }
     
      resolve(path) {
      }
    }

    The setResourceData is used at various times during script execution and provides your resource resolver with additional data that it needs to be capable of resolving. If this method is not properly implemented then features such as data-sly-use and data-sly-list will not work because the context data for those features will not be available from your resource resolver. This likely means that you need to set this jsonData to some internal state and check for it's existence in the resolve method before performing custom resource resolution logic.

    The resolve method takes a path variable which can either be a string of the form some.path.separated.by.periods. Your resource resolver should contain some logic for retrieving the value of the indicated resource. This method can either return a promise or the actual value.

    An example use case for this is to provide a resource resolver that resolves resource paths to urls for integration with a custom API.

    To use your resource resolver you will pass it as the second parameter, constructing an instance of your resource resolver.

    const compiledHtml = new Compiler(exampleHtml, new MyCustomResourceResolver()).compile();

    Demos

    Command Line Demo

    To see this in action on the command line you can run the example with:

    npm run example:cli

    Browser Demo

    To see this in action in the browser run the following command and then open up localhost:3000.

    npm run example:browser

    Development

    Build new release

    The following command will build a UMD module at /dist/compiler.js

    npm run build
    

    Testing

    npm test
    

    97% test coverage 30 passing 0 failing

    Keywords

    Install

    npm i htl-compiler

    DownloadsWeekly Downloads

    14

    Version

    1.0.12

    License

    ISC

    Unpacked Size

    500 kB

    Total Files

    234

    Last publish

    Collaborators

    • megazear7