Markdown is a format that allows you to create pages by adding simple notations to text, but I thought that by combining Markdown with HTMX, which allows you to easily add interactive behavior by simply adding your own attributes to HTML tags, you can further expand the range of applications of Markdown. I thought it would be a good idea to try it out.
Basically, all you need to do is add a script tag that loads the HTMX library to the template applied when converting Markdown to HTML. HTMX is provided by a CDN, so there is no need to download the file locally and specify the path.
<script src="https://unpkg.com/htmx.org@2.0.0" crossorigin="anonymous"></script>
If the HTMX library is loaded, Markdown is a format that allows HTML tags to be written as they are, so simply writing an HTML tag with the HTMX attributes added will work.
For security reasons, an HTTP server is inevitably required, but we created an environment to check the operation in a browser. The environment in which the Live Server extension is installed in VSCode is the easiest to test.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/default.min.css" crossorigin="anonymous">
<script src="https://unpkg.com/htmx.org@2.0.0" crossorigin="anonymous"></script>
<script src="https://uniras.github.io/mdmx/mdmx.js" type="module" crossorigin="anonymous"></script>
<title>Linkage test between markdown and HTMX</title>
</head>
<body>
<div class="markdown" hx-get="file.md" hx-trigger="load"></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
</body>
</html>
Prepare this HTML file and a Markdown file with HTMX added as appropriate, and change the hx-get attribute file.md to the path of the Markdown file you created.
The following is an example of Markdown with embedded HTMX that reads and displays the HTML content of a separate file when a button is pressed.
# Test embedding HTMX in markdonw
This is a test to embed HTMX in markdown.
* list1 * list2 * list3
<button hx-get="test.html" class="btn btn-primary btn-rounded">Press</button>
The https://uniras.github.io/mdmx/mdmx.js in the middle is a home-made JavaScript that waits for HTMX events to convert Markdown to HTML.
It uses Marked and Highlight.js.
This script waits for an afterRequest event (after a request is generated by hx-get, etc.), and if the element on which the event occurs has the markdown class specified, converts the acquired Markdown to HTML and inserts it into the element specified by the hx-target attribute If you want to manage it yourself, please refer to the code below.
If you want to manage it yourself, please refer to the following code.
import { marked } from 'https://cdn.jsdelivr.net/npm/marked@13.0.1/lib/marked.esm.js';
import hljs from 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/es/highlight.min.js';
document.addEventListener('htmx:afterRequest', function(event) {
const targetElement = event.target;
if (targetElement.classList.contains('markdown')) {
const markdownText = event.detail.xhr.responseText;
const htmlContent = marked.parse(markdownText);
let swap = targetElement.getAttribute('hx-swap') || 'innerHTML';
let target = event.detail.target;
htmx.swap(target, htmlContent, { swapStyle: swap });
hljs.highlightAll();
htmx.process(target);
}
});
The result should look something like this
https://uniras.github.io/mdmx/mdmx.html
Personally, I think it is better to use the default tag notation for HTMX, so that you can see at a glance that HTMX is applied and its parts.
Although I have not found any useful use for HTMX yet, it is extremely easy to implement and use, so you may want to keep it in your mind as an option.
Both Markdown and HTMX are solutions that focus on simplicity of use with limited functionality, and I don’t think they are incompatible.