MarkdownにHTMXを埋め込んでインタラクティブなWebページを作成する

## 概要

Markdownは、テキストに簡単な記法を追加してページを作成出来るフォーマットですが、  
HTMLタグに独自の属性を追加するだけで簡単にインタラクティブな動作を追加できるHTMXを組み合わせることで、  
Markdownの応用範囲をさらに広げられるんじゃないかと思ったので、試してみました。

## できそうなこと

- 別の場所にあるデータ等を手動でコピペすることなく挿入できる。そのデータが更新されても改めてコピペし直す必要がなくなる。
- Markdownで作成したwebページから、APIをコールしたりその結果を整形して表示できる(HTMXにはHTMLテンプレートを定義してそれを適用する機能がある)
- 別のMarkdownファイルを読み込んで、その内容を表示できる(どこかでMarkdownを変換するロジックが必要)

## 実現方法

基本的に必要な作業はMarkdownをHTMLに変換する際に適用されるテンプレートにHTMXライブラリを読み込ませるscriptタグを追加するだけです。
HTMXはCDNで提供されているので、ローカルにファイルをダウンロードしてパスを指定する必要もありません。

```html
<script src="https://unpkg.com/htmx.org@2.0.0" crossorigin="anonymous"></script>
```

HTMXライブラリがロードされていれば、MarkdownはHTMLタグをそのまま記述できるフォーマットなので、HTMXの属性を追加したHTMLタグを記述するだけで動作します。

## 簡易なテスト環境

セキュリティの関係上、どうしてもHTTPサーバーは必要になりますが、ブラウザで簡単に動作確認できる環境を作りました。
VSCodeにLive Server拡張機能をインストールした環境が最も簡単にテストできると思います。

```html
<!DOCTYPE html>
<html lang="ja">
<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>markdownと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>
```

このHTMLファイルと、適当にHTMXを追加したMarkdownファイルを用意して、`hx-get`属性の`file.md`を作成したMarkdownファイルのパスに変更してください。

以下は、ボタンを押したら別ファイルのHTMLの内容を読み込んで表示するHTMXを組み込んだMarkdownの例です。

```markdown
# markdonwにHTMXを埋め込むテスト

これはmarkdownにHTMXを埋め込んでみるテストです。

* リスト1
* リスト2
* リスト3

<button hx-get="test.html" class="btn btn-primary btn-rounded">押してみて</button>
```

途中の`https://uniras.github.io/mdmx/mdmx.js`は、HTMXのイベントを待機してMarkdownをHTMLに変換する自作のJavaScriptです。  
MarkedとHighlight.jsを使用しています。  
このスクリプトは、afterRequest(hx-get等でリクエストが発生した後)イベントを待機し、  
イベントが発生した要素にmarkdownクラスが指定されていた場合、取得したMarkdownをHTMLに変換してhx-target属性で指定された要素に挿入します。  
自分で管理したい場合は以下のコードを参考にしてください。

```javascript
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);
    }
});
```

結果はこんな感じになるはずです

https://uniras.github.io/mdmx/mdmx.html

## 専用の記法は必要？

個人的にはむしろHTMXはデフォルトのタグ記法のままのほうが、HTMXが適用されてることやその部分がひと目でわかるのでわざわざ専用のMarkdown記法はいらないんじゃないかなと思います。

## おわりに

まだこれと言った有用な使い道がないかもしれませんが、導入も利用も極めて簡単なので、選択肢として頭の片隅に置いておくといいかもしれません。  
MarkdownもHTMXも、どちらも機能を絞ってシンプルに使えることを重視しているソリューションであり、相性は悪くないと思います。