🙂

絵文字だけでコーディングしてHTMLにコンパイルするライブラリを作った

2024/12/21に公開

クソアプリアドベントカレンダー2024 21日目の記事です。
まずは今年で10周年とのこと、本当におめでとうございます🎉🎉

10年目にして初参加になります!お手柔らかにお願いします!

概要

絵文字を使ってコーディングを行い、その内容をHTMLとしてコンパイルする「emo-lan」というものをRustで作りました。

ライブラリ自体は以下のRustのパッケージとして公開しています。
https://crates.io/crates/emo-lan

今回このemo-lanの実行環境として、Playgroundも用意しました!
https://emo-lan-playground.vercel.app/

使い方

コードサンプルをコピペして入力エリアに貼り付けましょう。
emo-lanの実行環境のスクリーンショット
今回は自分のXのアイコンと説明文を記述したいので以下のようにコーディングしました。

📄
🔤infixer🔤
🖼️[Xのinfixerのプロフィール画像](https://pbs.twimg.com/profile_images/1322943302497259521/XeRehva-_400x400.jpg)
🔤マークアップおじさん。数学と哲学を学ぶ社会人大学生。🔤

すると以下のようにコンパイル結果にHTMLでマークアップされたものが表示されます!
emo-lanの実行環境のスクリーンショット:出力結果が表示されている
使える絵文字の種類はREADMEにまとめていますが以下になります。

Emoji Description HTML Output
📄 Document start (required) <!DOCTYPE html>
🔤text🔤 Text content <p>text</p>
🖼️(url) Image <img src="url" alt="alt" />

そう!つまり。。DOCTYPE宣言とpタグ、imgタグしか記述できません!!!!!!

技術構成(emo-lan)

emo-lan自体は、Rustで書いています。Rustは今までN回挫折していたのですが、AIの力を借りながら作りました。

構成自体はめっちゃシンプルで字句解析、構文解析、パーサー、コンパイラーの構成になっており、それぞれをクレートに分けて実装しました。

emo-lan/
├── Cargo.toml          # ワークスペース設定とメインの依存関係
├── Cargo.lock          # 依存関係のバージョンロック
├── README.md           # プロジェクトのドキュメント
├── src/                # メインライブラリとWasm関連のコード
│   └── lib.rs         # ライブラリのエントリーポイントとWasm実装
├── lexer/             # 字句解析モジュール
│   ├── Cargo.toml     # lexerの依存関係
│   └── src/
│       └── lib.rs     # 字句解析の実装
├── parser/            # 構文解析モジュール
│   ├── Cargo.toml     # parserの依存関係
│   └── src/
│       └── lib.rs     # 構文解析とHTML生成
├── cli/               # コマンドラインで実行するための機能
│   ├── Cargo.toml     # CLIの依存関係
│   └── src/
│       └── main.rs    # CLIの実装
└── common/            # 共有モジュール
    ├── Cargo.toml     # 共通ライブラリの依存関係
    └── src/
        └── lib.rs     # 共有の型定義とユーティリティ

作ってみてライブラリの性質上文字の解析が多いことから、Rustでの文字列の操作や型について学ぶことができました。

あとは、パターンマッチングが最高すぎて普段JavaScriptやTypeScriptを書く人間からすると羨ましい限りです。。。

例えば以下のようなコードです。
https://github.com/ryokatsuse/emo-lan/blob/2d7836ced5530bd7b29e520b43eafc479c3f239c/src/lib.rs#L87-L108

上記は、実際に引数として渡ってきた抽象構文木(AST)とその中のノードが正しければHTMLタグと出力するし、間違っていればErrに渡してエラーメッセージを返すコードです。網羅性をチェックしつつ条件分岐が見やすくて個人的に好きです。

技術構成(Emo-Lan Playground)

また今回はクソアプリということで目に見えるものを作らないといけないと思い、Webで実行環境を作りました。こちらについては、emo-lanをwasm-packを使ってWebAssemblyにコンパイルしてJavaScriptから呼べるようにしました。

wasm-packを使うといい感じに実行できるファイルにしてくれて、型も生成されるので、あとはそのままNPMパッケージとしてPublishするだけでいけました。

https://www.npmjs.com/package/emo-lan

Playground自体は、自分も普段から使っているNext.jsで作りましたが、UIの実装はほぼv0に任せました。
https://v0.dev/

今回実際コンパイルする処理は以下のようになっています。

https://github.com/ryokatsuse/emo-lan-playground/blob/d889be76d53c82df4f19defe5e50f72587d5a302/src/_components/playground/playground.tsx#L9-L16

handleCompile関数は、コンパイルボタンを押したときのイベントで、ここで予めテキストエリアに入力された値をuseStateで保持しておき、その値を入力値としてcompile_to_html関数に渡しています。この関数こそがemo-lanの中身になります。この関数の出力結果は、正しくパースされればそのままhtmlタグの文字列が返ってきます。

あとはフロントエンドでその文字列をサニタイズしてあげて表示させればOKです。

おわりに

たった3つの絵文字しか解釈できない言語でHTMLへコンパイルするものを作りました。今の時点では何も役に立たないですが、これから絵文字の種類を増やして、様々なHTMLタグに対応させることができればクソテンプレートエンジンが出来上がるのでは?と思ったりしています。

このPlaygroundとemo-lanは暇な時にアップデートしていこうと思うので、もし思い出した時は、サイトに訪れていただけると嬉しいです!

Discussion