Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
824 changes: 636 additions & 188 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"nock": "^13.5.6",
"node-fetch": "^2.7.0",
"node-html-parser": "^6.1.13",
"nodemon": "^3.1.10",
"prettier": "^3.3.3",
"sinon": "^19.0.2",
"ts-node": "^10.9.2",
Expand All @@ -86,6 +87,8 @@
},
"dependencies": {
"dompurify": "^3.2.7",
"json5": "^2.2.3"
"json5": "^2.2.3",
"vite": "^7.1.9",
"vue": "^3.5.22"
}
}
12,359 changes: 5,493 additions & 6,866 deletions www/app/package-lock.json

Large diffs are not rendered by default.

106 changes: 86 additions & 20 deletions www/app/package.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,91 @@
{
"name": "hmpl-docs",
"description": "hmpl documentation",
"license": "MIT",
"type": "module",
"version": "0.0.1",
"name": "hmpl-js",
"version": "3.0.5",
"description": "🐜 HMPL.js is a lightweight server-oriented template language for JavaScript. Fetch HTML, render it safely, and keep apps dynamic, modern, and small.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
"start": "tsc --watch",
"lint": "npx eslint src/**/* --fix",
"lint:test": "npx eslint test/**/* --fix",
"prebuild": "npm run lint",
"build": "tsc",
"build:prod": "tsup",
"test": "mocha --require ts-node/esm --experimental-specifier-resolution=node",
"test:watch": "mocha --watch --require ts-node/esm --experimental-specifier-resolution=node",
"coverage": "c8 --reporter=lcov npm run test",
"coverage:default": "c8 npm run test"
},
"files": [
"LICENSE",
"README.md",
"dist/",
"src/"
],
"homepage": "https://hmpl-lang.dev",
"license": "MIT",
"keywords": [
"fetch",
"html",
"template-engine",
"rest",
"ajax",
"hateoas",
"hypermedia",
"server",
"templates",
"templating",
"template-language",
"template-engines",
"fetch-api",
"server-side",
"language",
"template",
"hmpl",
"server"
],
"author": "Anton Maklakov",
"repository": {
"type": "git",
"url": "git+https://github.com/hmpl-language/hmpl.git"
},
"bugs": {
"url": "https://github.com/hmpl-language/hmpl/issues"
},
"engines": {
"node": ">=10.12.0"
},
"devDependencies": {
"@babel/cli": "^7.25.9",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/preset-typescript": "^7.26.0",
"@babel/register": "^7.25.9",
"@eslint/plugin-kit": "^0.2.3",
"@types/mocha": "^10.0.9",
"@types/node": "^22.9.0",
"@types/sinon": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^8.14.0",
"@typescript-eslint/parser": "^8.14.0",
"c8": "^10.1.2",
"cross-spawn": "^7.0.6",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"jsdom": "^25.0.1",
"jsdom-global": "^3.0.2",
"mocha": "^10.8.2",
"nock": "^13.5.6",
"node-fetch": "^2.7.0",
"node-html-parser": "^6.1.13",
"prettier": "^3.3.3",
"sinon": "^19.0.2",
"ts-node": "^10.9.2",
"tsup": "^8.3.5",
"typescript": "^5.6.3"
},
"dependencies": {
"@astrojs/sitemap": "^3.5.1",
"@astrojs/starlight": "^0.34.5",
"@astrojs/vue": "^5.1.0",
"astro": "^5.6.1",
"axios": "^1.10.0",
"sharp": "^0.34.2",
"starlight-theme-nova": "^0.9.0",
"toastr": "^2.1.4",
"vue": "^3.5.17"
"dompurify": "^3.2.7",
"json5": "^2.2.3"
}
}
}
Binary file added www/app/public/assets/ant-and-apples.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 12 additions & 4 deletions www/app/src/components/HomePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2332,22 +2332,30 @@ footer {

.contributors-grid {
display: grid;
grid-template-columns: repeat(8, 1fr);
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
justify-content: center;
align-items: center;
gap: 30px;
margin-bottom: 40px;
max-width: 80%;
max-width: 100%;
margin-left: auto;
margin-right: auto;
text-align: center;
}

@media (max-width: 600px) {
@media (max-width: 900px) {
.contributors-grid {
max-width: unset;
gap: 20px;
}
}

@media (max-width: 600px) {
.contributors-grid {
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 15px;
}
}

.contributor {
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ A landing page where the components are completely located on the server, so the

![Photo 4](https://github.com/user-attachments/assets/9c9edeb5-4a23-4a56-9100-2803151e9a3f)
![Photo 5](https://github.com/user-attachments/assets/63c89eeb-5b07-4b3d-979b-77cff7b271d0)

## Ant and Apples
A simple interactive game built with HMPL demonstrating dynamic content loading and state management. [View on GitHub](https://github.com/aanthonymax/ant-and-apples)

<img src="/assets/ant-and-apples.png" alt="Ant and Apples Game" width="730" height="300">
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
layout: post
title: "Write Reactive HTML Without JavaScript"
date: 2025-10-11 20:00 PM
categories: blog
tags: [webdev, javaScript, opensource, programming]
---


Hello! This is not clickbait. I thought for a long time about what to call this article, but it is hard to convey in words what is felt. Therefore, I wrote simply as I felt.

For a long year we have been supplementing the template language, but the range of applied use was quite limited. We developed within the framework of the template paradigm, but, in essence, it was correct, but in an applied [project](https://github.com/hmpl-language/hmpl-dom) it is still quite difficult to implement this without something serious.

By serious I mean a framework, or something like that, that supported the syntax by default, but, in fact, if jsx has react, then it is quite difficult to build a structure on it, since it itself is structural.

Therefore, we took a different path, which I will try to describe in this article.

## Structural Modules and the Real DOM

Whatever anyone says, the time of template languages ​​is a bit different. Today, many people look at artificial intelligence as something breakthrough. And it is, but the fact is that it is not everything in our world. About 10 years ago, there was active development of various template languages, but now you are more likely to find 1000 new AI projects than one with templates.

And this is not surprising, because with the advent of jsx, ejs and handlebars, we can consider that this topic has exhausted itself and humanity can no longer come up with anything better. Maybe it is so, but only in some aspects. We interact with the server in the same way, and php to js, ​​no matter how much you want, you can’t normally attach it.

So, as an experiment, we created this project to move this topic forward.

```html
<div class="container">
{{#request src="/api/my-component.html"}}
{{#indicator trigger="pending"}}
<p>Loading...</p>
{{/indicator}}
{{/request}}
</div>
```
HTMX, no matter what SEO techniques they use and how caricatured they are in some sense, have nevertheless proven over 10-12 years of work on the topic that this topic is truly relevant in development. Together with Alpine.js, we see that not all people want to work on frameworks. This is correct, but it is also difficult and cumbersome on the other hand.

**This topic**, for some reason, was actively developed in attributes 3-4 years ago, but **for some reason no one looks at template languages**. It's as if the hype on them passed 10 years ago and everyone thinks that they are relics of the past, but this is not so.

We believe that this topic is not forgotten, but we cannot deny the fact that today most of such projects are based on working with the real DOM. There is simply no escape from this.

## Hype on Attributes

Anyone who thinks that in the world of development **hype can be out of nowhere is wrong**. Today, there are facts that in the state of the market today, people are not ready to switch to something more monumental, since it is easier to sit down at the framework. Therefore, working with the real DOM, when we connect only a couple of files - this is important. If you remember the same Docsify, to create documentation you do not need to install a bunch of packages that are not related to JS at all, as is done with Jekyll, this is the whole point.

Therefore, no matter how much we develop the theme of the template language, in a vacuum it is quite difficult to use, therefore, in fact, an obvious decision was made to supplement the functionality with a new module, which is called **hmpl-dom**.

```html
<!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 class="indicator">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-dom.min.js"></script>
</body>
</html>
```

Thanks to him, we combined the approach of a template language with working with a real DOM. I am convinced that attributes by definition, no matter how extensible they seem (like in Alpine.js, when you write expressions with functions there), they cannot be a full-fledged replacement.

Yes, they have their advantages, but it's not about them, it's about working with the real DOM without js.

## What if I need to pass `RequestInit`?

No one will move away from js, even in such an implementation. Its meaning is in the choice of using js or not, as well as in the simplicity that is currently on the market.

**index.html**

```
<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.js**

```
import { init } from "hmpl-dom";

init([
{
id: "clicker-config",
value: {
compile: { memo: true },
templateFunction: ({ request: { event } }) => ({
body: JSON.stringify({
action: event.target.getAttribute("data-action")
})
})
}
}
]);
```
We can still pass everything that was done before. It's just another level of nesting, when we had it before only within one compile function, now in a whole connected chain of templates, where a separate templateFunction is created for each (yes, we wouldn't take outerHTML from the entire page, because that would be just stupid.

## Links
More about this project you can find here:

- [Repo](https://github.com/hmpl-language/hmpl-dom)
- [Documentation Page](https://hmpl-lang.dev/dom.html)

Also, if you want to support us, you can put a star on our main project. Thanks!

*This article is based on the original tutorial by Anthony Max, available on [Dev.to](https://dev.to/hmpljs/hmpl-dom-v001-release-the-most-important-module-4783).*
61 changes: 61 additions & 0 deletions www/blog/_posts/2025-10-14-how-the-iframe-tag-changed-the-world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
layout: post
title: "How The iframe Tag Changed The World"
date: 2025-10-14 20:00 PM
categories: blog
tags: [webdev, html]
---

Many things we are accustomed to in programming today were once unimaginable.

In this article, we'll talk about one such thing: the `iframe`. Many people know what it is, of course, and some may have forgotten, but at one time, it was a true miracle.

Let's dive a little into the history of the web and see what was there 🔎

---

## 🕸️ Web 1.0

With the advent of the modern internet in 1991 (www), its ubiquity was just beginning. Back then, it was a novelty that computers could communicate with each other. Everything hinged on local area networks (LANs) connecting computers in a single factory, bank, or other location. While it was understandable that two computers connected by wire could transfer files, it was difficult to do so even across the street.

![first website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ih50ojupo1ef1rkswdf.webp)

Back then, computers were incredibly expensive, like houses, but every year their cost became less and less, and ordinary people, not multi-billion dollar companies, could afford simple computers at that time.

Back then, the internet was just gaining momentum, slowly but surely, and people were exchanging simple documents stored on domains. The first browsers were appearing, and people realized this was the future. Many businesses back then, launching their own simple websites, were able to attract as many customers as they could have from newspapers or television, given their budgets.

It is precisely because of people's desire to earn more that the second stage begins, when the first money appears on websites.

## 🌐 The Beginning of the Internet Bubble

With the onset of this period in 1995, everyone began to believe that this was the future. This was true, but economically, there were questions: was it worth spending so much on an online business? But we're only just beginning. Millions were spent sponsoring their websites. Everyone wanted to stand out somehow, to do something new.

Let's get right to the topic of advertising. Back then, it was similar to what you see in old newspapers today. Plain text, maybe an image at most (the `img` tag was introduced in 1993). It worked back then, but, as you can imagine, it wasn't entirely effective, as it was unnoticeable and crude.

![Simple advertising](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grhyhozqsf1zpp4bva4b.png)

People contrived everything they could, creating various images with text, using terrible color combinations, incomprehensible fonts, and so on. But it seemed perfectly natural back then, as there were no other options, and the work of a web designer as such was just beginning. There was no Figma back then, so :)

## 🌌 The appearance of the iframe tag

It would seem that the `img` tag would be sufficient for advertising at the time. No one could have imagined that it would be possible to display an entire website on another website. But in 1997, it became possible.

![YouTube](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4trehzkwmi53ncjq8r05.png)

Imagine, now a client couldn't just click on something, but also interact with it like on any other website! That is, you could now create an ad in the form of a game, say, tic-tac-toe, and instead of tic-tac-toe, you could use vacuum cleaners.

You can also watch videos. This is a later development, but it's still possible today. It became possible not in 1997, but a little later. Back then, people used Flash Player, but this topic is now so extensive that it deserves another article.

## ✅ Conclusion

The influence of `iframe` is truly difficult to exaggerate, as it essentially created a new direction on the internet, one that gave rise to a new wave of advertising as an art, and gaming. Just look at the Flash Player and the majority of games that use it, which many still remember. I hope this article has covered some of this.

---

**Thank you very much everyone for reading the article!**

![thanks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s15nqbzlq7jb3hd16eix.gif)