Introduction
🌐 HMPL (/ˈhæmpəl/ portmanteau of the words Cample and HTML) is a small template language for displaying UI from server to client. It is based on customizable requests sent to the server via fetch and processed into ready-made HTML. The language is syntactically object-based and integrated with JSON5 and DOMPurify. Reduce the size of your javascript files and display the same UI as if it was written in a modern framework!
How it works?
Section titled “How it works?”The HTML you use on your site is enhanced by adding special blocks that resemble components in syntax, but are more like “helper blocks” like in Handlebars.
In these blocks you describe the request that will be sent to the server to get the finished components from there. This includes HTTP methods, request frequency and many other things that are used when talking about fetch.
To describe it more briefly, it is something in between HTMX and EJS 👀.
Why HMPL?
Section titled “Why HMPL?”Unlike other similar modules, the template language provides more complete customization due to a well-thought-out balance between HTML and JS. HMPL supports modern EcmaScript standards - thanks to its well-thought-out functionality, you will not depend on versions.
Also, the template language format itself allows you to work with .hmpl
extension files if you use Vite or WebPack.
Most Frequently Asked Questions
Section titled “Most Frequently Asked Questions”You may have questions about the template language, here is a short list of those that were asked throughout the development cycle:
Is it necessary to use JavaScript?
No, you don’t have to use it with the hmpl-dom module, but the template language itself is fully configured for this.
Is it safe?
Yes, the template language is completely safe, as it only accepts text/html
by default. If you are working with an uncontrolled API, the module also provides protection against XSS attacks. More information about security can be found here.
What is the difference between HTMX and Alpine.js?
We have written several articles on this topic, specifically about the differences from HTMX and Alpine.js
Can I use HMPL with modern frameworks?
Yes! HMPL is designed to work alongside modern frameworks. It’s something in between HTMX and EJS, providing a lightweight alternative for server-client communication without the overhead of full framework implementations.
Usage Examples
Section titled “Usage Examples”Example 1
Section titled “Example 1”HTML before
Section titled “HTML before”<template data-hmpl data-config-id="clicker-config"> <div> <button data-action="increment" id="btn">Click!</button> <div> Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}} </div> </div></template><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-dom.min.js"></script>
API route - /api/clicks
Section titled “API route - /api/clicks”<span class="counts"><?php $clicks ?></span>
HTML after
Section titled “HTML after”<div> <button data-action="increment" id="btn">Click!</button> <div>Clicks: <span class="counts">0</span></div></div>
Example 2
Section titled “Example 2”import { compile } from "hmpl-js";
const templateFn = compile( `<div> <form onsubmit="function prevent(e){e.preventDefault();};return prevent(event);" id="form"> <div class="form-example"> <label for="login">Login: </label> <input type="login" name="login" id="login" required /> </div> <div class="form-example"> <input type="submit" value="Register!" /> </div> </form> <p> {{#request src="/api/register" after="submit:#form" repeat=false indicators=[ { trigger: "pending", content: "<p>Loading...</p>" } ] }} {{/request}} </p></div>`);const initFn = (ctx) => { const event = ctx.request.event;
return { body: new FormData(event.target, event.submitter), credentials: "same-origin" };};const obj = templateFn(initFn);const wrapper = document.getElementById("wrapper");wrapper.appendChild(obj.response);