SvelteのMarkdownレンダラを作った

3109 ワード

n 番煎じだけど Svelte の Markdown レンダラを作った話。

モチベーション

Svelte の知名度は 2,3 年前などと比べるとかなり広まったように見えるが、Svelte + Markdown の動きが殆ど感じられない。

個人的には、簡単さ故に Svelte(Kit)をテンプレートエンジンないし SSG フレームワークとして使うのはかなりアリだと思っている(まだ複雑なものは不安が残る)ので Markdown をレンダリングできると幸せなのだが、現状は以下。

  • svelte-markdown
    • v0.2.2
    • markedベースのレンダラ
    • Markdown パースの拡張性が乏しい(数式描画したいとか)
  • MDsveX
    • v0.10.5
    • React でいう MDX(Markdown の中でコンポーネントが使える)のプリプロセッサ
    • コンパイル時に処理されるので Markdown エディタなどのプレビューなど動的に使えない

どちらも、2,3 年前に最初のバージョンがリリースされているものの、最適解とはいえない。
やはり、動的に使えて拡張したい。

こういうとき React はreact-markdownを使っておけばという安心感がある。

つくったもの

作ってから気づいたのは特別独自性があるとかではないということ。

実装

簡略化するつもりだったが、試行錯誤の末ほとんど react-markdown と同じになってしまった。

unifiedというエコシステム上で、

Markdown
-(string)-> remark-parse
-(mdast)-> remarkPlugins
-(mdast)-> remark-rehype
-(hast)-> rehypePlugins
-(hast)-> ast-component-mapping
-> SvelteComponent

という風に変換している。

プラグインシステム

利用者が拡張できるのは、 remarkPluginsrehypePluginsast-component-mapping の 3 箇所。

  • remarkPluginでは、mdast(Markdown の AST 表現)の変換・操作
  • rehypePluginでは、hast(HTML の AST 表現)の変換・操作
  • ast-component-mappingでは、HTML の要素と Svelte コンポーネントの関係付け

と言った具合。

GFM(GitHub Flavored Markdown) Plugin

「みんながよく使うやつ」なので、標準で同梱している(同梱しているだけ、オプトイン方式)。

これはプラグイン的には

  • remarkPlugin - remark-gfm
    • remark 公式の gfm プラグイン
    • Markdown の拡張文法を解釈する
  • ast-component-mapping
    • テーブルコンポーネントや<del />要素
    • 標準の Markdown にはないコンポーネントになるので追加している

この 2 つをセットで 1 つのプラグインという形。

Vitest によるテスト

当初、Jest を使おうと思っていたが「ESM,TS,Svelte 辛い」になってしまったので Vitest を採用した。

SvelteKit をプロジェクト全体で使っているので Vite との相性がいいのはわかっていたが想像以上に DX が良かった。

今後も特別な理由がなければ Jest でなく Vitest で良さそう。

かんそう

ぼくのかんがえたさいきょうのSvelte マークダウンレンダラを作った。

作り始めて 3 日くらいで詰めが甘いので今後も育てるつもり。

issue, discussion, PR お待ちしております 🙇‍♂️