HMPL.js: Server-Oriented, Customizable Templating for JavaScript

JavaScript Libraries

Discover HMPL.js, a lightweight JavaScript library for server-driven, customizable templates. Build dynamic UIs with minimal JS, leveraging Fetch API, JSON5, and DOMPurify for efficient, secure, and flexible web development.

Server-oriented customizable templating for JavaScript

🌐 Website β€’ πŸ“„ Docs β€’ πŸ–₯️ Demo Sandbox β€’ βš™οΈ Examples

Introduction

HMPL.js offers exceptional flexibility for building server-driven templates with minimal JavaScript. Its block-based syntax, customizable fetch requests, and built-in support for forms, events, and time-based syncing enable the delivery of dynamic user interfaces without the overhead of heavy frameworks. HMPL seamlessly integrates with JSON5 for expressive object syntax and DOMPurify for secure HTML rendering, all packaged in just a few kilobytes.

Example

<div>
  {{#request src="/api/my-component.html"}}
    {{#indicator trigger="pending"}}
      <p>Loading...</p>
    {{/indicator}}
  {{/request}}
</div>

Try HMPL online at: hmpl-playground

Basic usage

HMPL.js allows you to create dynamic components that interact directly with your server.

import hmpl from "hmpl-js";

const templateFn = hmpl.compile(`<div>
  <button data-action="increment" id="btn">Click!</button>
  <div>Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}}</div>
</div>`);

const clicker = templateFn(
  ({
    request: {
      event
    }
  }) => ({
    body: JSON.stringify({
      action: event.target.getAttribute("data-action")
    })
  })
).response;

document.querySelector("#app").append(clicker);

Explain this!

Let's break down the basic usage example:

import hmpl from "hmpl-js"; // Import the HMPL library

// Compile an HMPL template with dynamic behavior
const templateFn = hmpl.compile(`<div>
  <button data-action="increment" id="btn">Click!</button>
  <!-- This div will update with the click count from /api/clicks -->
  <div>Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}}</div>
  <!-- Also, you can write in short: {{#r src="..."}}{{/r}} -->
</div>`);

// Generate a response handler for the template
// In the original object, we will have the following: { response: div, status: 200 }
const clicker = templateFn(
  ({
    request: {
      event
    }
  }) => ({
    // Send a JSON payload with the action from the button's data attribute
    body: JSON.stringify({
      action: event.target.getAttribute("data-action")
    })
  })
).response;

// Append the dynamically generated element to the #app container
document.querySelector("#app").append(clicker);

In this example, we create a dynamic clicker component where pressing a button triggers a server request to fetch the current click count. A key advantage of this approach is that HMPL can retrieve not only simple data (like text) but also entire components and even full pages from the server.

Usage with DOM

For scenarios where you prefer not to use JavaScript for dynamic mounting, the hmpl-dom module allows for declarative integration.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Example</title>
  </head>
  <body>
    <main>
      <template hmpl>
        <div>
          {{#request src="/api/my-component.html"}}
            {{#indicator trigger="pending"}}
              <p>Loading...</p>
            {{/indicator}}
          {{/request}}
        </div>
      </template>
    </main>
    <script src="https://unpkg.com/json5/dist/index.min.js"></script>
    <script src="https://unpkg.com/dompurify/dist/purify.min.js"></script>
    <script src="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
    <script src="https://unpkg.com/hmpl-dom/dist/hmpl.min.js"></script>
  </body>
</html>

With hmpl-dom, components fetched from the server are automatically mounted into the DOM, eliminating the need for manual JavaScript manipulation.

Why HMPL?

By leveraging HMPL's templating capabilities, you can significantly reduce your application's bundle size. Its full customization of requests based on the modern fetch standard, coupled with essential features for modern applications (such as request indicators, event-driven sending, automatic body generation for forms, and caching), and a concise object syntax in markup, facilitate highly efficient server-client interaction. Compare app sizes below:

HMPL also serves as an excellent alternative to popular tools like HTMX and Alpine.js.

Features

  • Customizable: Send tailored requests to the server when receiving UI updates.
  • Memory Preserving: Dramatically reduce client-side file sizes.
  • Based on Fetch API: Utilizes a modern standard, moving beyond XMLHTTPRequest.
  • Server-oriented: Interact directly with the server through markup and minimal JavaScript.
  • Generate thousands of DOM nodes from a single template: Efficiently handle large components on both server and client.
  • Simple: Obtain ready-made UI from the server by writing just a few lines of familiar object syntax.
  • Protected from XSS attacks: Safely render incoming server HTML by enabling built-in sanitization with DOMPurify.
  • Flexible: Adaptable to almost any project, supporting both script-based integration and .hmpl files.
  • Integrated with JSON5: Enjoy flexible object syntax, as in vanilla JS, backed by a widely used and reliable parser.
  • Small bundle size: A rich set of functionalities packed into just a couple of kilobytes.

Installation

HMPL can be installed using several methods. As a simple JavaScript file, it can be connected via a standard script tag or through the import construct in environments that support it (e.g., Webpack, Parcel builds).

Note: Starting with version 2.2.0, the JSON5 module is required, and from version 2.2.5, the DOMPurify module is also necessary. The simplest way to include these is via a CDN.

Package Manager

Install HMPL via npm or other package managers:

npm i hmpl-js

Minified and regular JavaScript files can be found in node_modules/hmpl/dist.

CDN

Connect HMPL and its dependencies via a CDN, which provides access to the npm package files through a link:

<script src="https://unpkg.com/json5/dist/index.min.js"></script>
<script src="https://unpkg.com/dompurify/dist/purify.min.js"></script>
<script src="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
<!-- You might also add integrity="..." crossorigin="anonymous" for security -->

Popular CDN providers include unpkg, skypack, and others. unpkg is used in examples due to its popularity and concise URLs.

Through the starter template project

Get started quickly with a Vite starter project:

npx degit hmpl-language/hello-hmpl-starter hello-hmpl

This provides a solid foundation for building web applications.

Official Tools

VS Code Extension Syntax highlighting and development tools for HMPL.

Vite Plugin Seamless .hmpl file integration with Vite.

Webpack Loader Compile .hmpl files directly within Webpack projects.

We encourage and welcome community-developed tools as well!

Community support

The documentation provides comprehensive information on how the HMPL template language functions. For any questions regarding HMPL, you can utilize the following resources:

  • GitHub: Ask questions in the discussion and issues sections.
  • Discord: Join the "support" channel for assistance.
  • 𝕏 (Twitter): Follow for interesting updates and discussions related to the template language and more.

You can also post your questions on Stack Overflow and reference the resources mentioned above.

Contribution

Refer to our Contributing Guide for detailed steps on how to contribute to the project. A heartfelt thank you to all individuals who have already contributed to HMPL or its related projects!

Star History

Roadmap

Explore the project's roadmap to see plans for future development.

License

Released under the MIT License.

πŸ’Ž Star this repo β€’ πŸ’» Try HMPL.js β€’ πŸ’¬ Join Discord

This project thrives on the valuable contributions of many amazing community developers!