書きなぐりです... まだ書きかけです... リンクとかぐちゃぐちゃです...
目次
- Markdown パーサ
- Markdown 方言
- サービス, SSG が採用しているパーサ
- ライブラリが採用しているパーサ
- 独自記法を定義することについて
- そのほか
1. Markdown パーサ
パーサ | 方言 | |
---|---|---|
1 | unified | CommonMark のみ(GFM の拡張プラグインがあります) |
2 | marked | CommonMark, GFM の全部を採用 * |
3 | markdown-it | CommonMark, GFM の一部を採用 * |
4 | commonmark | CommonMark のみ * |
5 | remarkable | CommonMark, GFM の一部を採用 * |
6 | showdown | Original のみ*(based on the original works by John Gruber) |
補足: 方言の互換性について
- CommonMark
- unified と commonmark は双方共に CommonMark を「仕様」として採用していますが、双方の「実装」に互換性があるのか、unified と commonmark が実際に全く同じように Markdown -> HTML に変換するのかは調べてはいません。
- GFM
- 「CommonMark の仕様は厳密だけど GFM の仕様は曖昧だよね」という記事を見かけました。GFM の「実装」には互換性がなさそうなことに留意してください。
- GitHub Flavored Markdown は何であって何でないか- Qiita
- リンク
npm trends
補足1: 比較 markdown と markdown-it と unified
- 個人の感想です...
- unified, marked, markdown-it の3つがメジャーかなという感じがします。
- marked
- 速度: 1 小さく変換速度が速い。markdown-it の2倍くらい速い。
- 拡張: 3 反面、拡張性はそこまでで SSG や Qiita, Zenn といった大きなサービスでは採用されていない様子でした。
- markdown-it
- 速度: 2
- 拡張: 2 拡張性がある。
- unified
- 速度: 3
- 拡張: 1 拡張性がある。unified は mdx の仕様を策定しているからか markdown-it に比して React 系のライブラリ, SSG では広く採用されているように見えました。
-
Comparison Javascript Markdown Parsers
- パーサがどう変換するか比較してくれます。
- ページ右上に変換時間も表示されます。marked が一番早そうです。
- unified がないのが残念...
- lang:ja markdown-it marked - X 検索結果
- 以下のポストで remark は unified に読み替えてください。後述します。
とりあえずmarked, markdown-it, remarkの比較はできた
— 数の子 (@k42un0k0) June 25, 2021
markedはシンプル、markdown-itはプラグイン多いけど妙に複雑、remarkはプラグイン多いしやりたいことが簡単ならシンプルに拡張できる
Markdownのちょっとした変換ツールを作りたいのでmarkdownライブラリを検討してる。
— tai2 (@__tai2__) September 10, 2023
* marked 小さくてシンプルで見通しがいい。ただし、API的に親を参照して処理変えるのがきれいにはできない
* markdown-it: なんかドキュメントわかりづらい。親を参照するのはenv使えばできそう
* remark: 抽象化されすぎて、処理複数リポに分割されててなんか見通し悪い。そこまで必要?心理的ハードル高い。visitのインターフェースは親参照できる形になってる。
— tai2 (@__tai2__) September 10, 2023
けっきょく、ASTまでしか利用しない(AST -> HTMLは自前)のであれば、どれ使っても大差ない。
markedのParser.tsをコピペして改造する、が最適解かな。https://t.co/UY1OkwUvCp
— tai2 (@__tai2__) September 10, 2023
- remark
- 上記ポストで言及されている remark は unified のラッパのようなものだと思っています。unified はプラグインを組み合わせて Markdown -> HTML のパーサを組み立てます。remark は unified 本体とそのプラグインを予め組み合わせた便利セットみたいなものだと思っています。
-
This package is a shortcut for unified().use(remarkParse).use(remarkStringify)
https://www.npmjs.com/package/remark#when-should-i-use-this
補足2: commonmark
- このパーサはあまり人気がないですが、メジャーな方言の1つである CommonMark の仕様が保存されているリポジトリにあったので記載しました。
補足3: unified
- グラフについて
- unified の用途は Markdown から HTML に変換するだけではなく、ほかにも用途があるそうです(詳しくはわかっていません)。
- そのため unified ではなく unified のプラグインで検索したほうがより正確な値かもしれません(例えば remark-parse)。
- 本稿ではいろいろややこしいので unified で統一しています。
- unified の資料
- unified のすごくわかりやすい資料です。これがなかったら一生 unified の全体像を把握できませんでした。ありがとうございます。
- 関係は以下を参照、図があります。
- 「unified のエコシステム」の節を参照
- これはあまり読んでいません...
界隈のつよつよの人たちが unified に肯定的なコメントをしている... でも具体的に何を指しているのか、どうしてよいのかわからない...orz
Markdown 方言ガーって言ってる人いたけど、JSならunified/remarkで、ある程度はなんとかなるから、ポータビリティという点では、現状ではやっぱりMarkdownが強いと思うんだよなぁ
— erukiti (@erukiti) November 19, 2019
テキスト処理のASTは結局 unifiedjs/unified として標準化されたなあ。 / “QiitaとMarkdownとコンテンツオーサリング - Qiita” https://t.co/J0PTyqBUPG #markdown
— Aki@めもおきば (@nekoruri) January 23, 2020
GitHub Star History
補足1: unified について
- unified は GitHub Star History で検索すると npm trends に比べて極端に順位が落ちます。
- これは恐らく開発者が unified を直接ダウンロードしているのではなく、ほかのライブラリやフレームワークを経由して unified をダウンロードしているため、直接見ることがないからではないかと思っています。
補足2: 比較方法について
ちょうど Express vs NestJS でどうやって比較するのがいいのか?みたいなのが話題にあがっていました...
GitHub Star を付けるモチベが個々で違いすぎる(期待やブックマークだったり評価だったり)のと、Star 付けてない人の評価の方が実は多いと思ってます。なので実際まだ上回ってはないと思います。
— mattn (@mattn_jp) March 21, 2024
例えば Google 検索結果
「js express」約 441,000,000 件
「js nestjs」約 4,610,000 件 https://t.co/H8eA0irxgK
指標としてはnpm のダウンロード数もありますね。それだとちょうど10倍差。 https://t.co/DEE54tnhsh
— 渋川よしき (@shibu_jp) March 22, 2024
GithubのスターはTwitterのいいねくらいの信頼性だと思ってよさそう
— Cubbit (@cubbit2) March 22, 2024
星が多いなら無名ということはない、では頼れるライブラリかというとそれはまた別、じゃあGoogleトレンドのほうが信頼できるかだとまあGithub星のほうがマシ、でもGithubを見るくらいならNPMのダウンロード数のほうがマシ、みたいな
2. Markdown 方言
# | 方言 | 説明 |
---|---|---|
1 | Original | Perl の実装、仕様。はじめて実装されたもの |
2 | CommonMark | 仕様。方言が乱立したため標準化しようとしたもの |
3 | GFM | 仕様。CommonMark を拡張したもの |
4 | MaltiMarkdown | Perl の実装、仕様 |
5 | PHP Markdown Extra | PHP の実装、仕様 |
6 | Pandoc | Haskell の実装、仕様 |
補足
- 個人の感想です。
- Original, CommonMark, GitHub Flavored Markdown(GFM) の3つがメジャーかなという感じがします。
- Original
- 最初の方言です。その後さまざまな方言が乱立する。
- CommonMark
- という方言で標準化しようとする。
- GitHub Flavored Markdown(GFM)
- GitHub は CommonMark を拡張した GFM を使っている。という流れを抑えておくと良いかなと思いました。
- Original
- Original, CommonMark, GitHub Flavored Markdown(GFM) の3つがメジャーかなという感じがします。
- 方言の一覧はどこから引っ張ってきたの?
- RFC 7764 に記載されていました。
- 文書の性格
- 方言
- Original
Markdown.pl
- RFC 7764 の一覧には Original の記載はありません。
- Original の語の説明は RFC 7763 にあります。
- 上記の表に Original があったほうが Original -> CommonMark -> GFM の流れがわかりやすいかなと思い追記しました。
- Markdown の歴史、誕生 Original -> 乱立 -> 標準化 CommonMark の流れは英語版 Wikipedia に記述があります。
- GFM
- 本稿では GitHub Flavored Markdown を GFM と略すことにします。
- GFM は CommonMark を拡張した仕様です。
- GFM が CommonMark から拡張した部分の仕様は、以下のリンクのうち緑のマーカで引かれた箇所になります。
- Original
- 方言とパーサ(仕様と実装)
- GFM や CommonMark のように純粋に仕様として定義された方言もありますが、それ以外 MaltiMarkdown, PHP Markdown Extra, Pandoc は実装を元にして定義された方言なのかなと思いました。
3. サービス, SSG が採用しているパーサ
サービス | パーサ | 補足 | |
---|---|---|---|
1 | Docsaurus | mdx -> unified | React 製の SSG, 技術ドキュメント向け |
2 | Nextra | unified | Next.js で使うライブラリ |
3 | Gatsby | unified | React 製の SSG |
4 | VitePress | markdown-it | Vue.js 製の SSG, 技術ドキュメント向け |
5 | Nuxt Content | mdc -> unified | Nuxt で使うライブラリ |
6 | Astro | unified | JavaScript 製 SSG |
7 | Sphinx | markdown-it-py | Python 製の SSG, 技術ドキュメント向け |
8 | MkDocs | Markdown | Python 製の SSG, 技術ドキュメント向け |
9 | Zenn | markdown-it | - |
10 | Qiita | Qiita Marker | Ruby 製 |
11 | WordPress | 調べてない | PHP 製, CMS の巨人 |
補足
- 一覧
- SSG
- ここに SSG の一覧があります。GitHub のスター順にならんでいます。
- A List of Static Site Generators for Jamstack Sites
- CMS
- 調べてない...
- SSG
- SSG
- JavaScript
- React
- Nextra
- Docsaurus
- Gatsby
- Vue
- Nuxt Content
- VitePress
- unified に比べると SSG やサービスで採用されていないように見えました。VitePress で採用されていました。VitePress が markdown-it を採用した理由は恐らく速度と拡張性と思われる。実際に速度を測ったわけではないです...
- Astro
- React
- Python
- Sphinx
- 初リリース: 2008/03/21*
- Python の開発ドキュメントを作る際に使用される SSG
- markdown-it-py
- markdown-it の移植版らしいです。
-
This is a Python port of markdown-it, and some of its associated plugins.
https://github.com/executablebooks/markdown-it-py
- MkDocs
- 初リリース: 2014/01/24*
- Python の開発ドキュメントを作る際に使用される SSG
- Markdown
- Original の仕様に則っているそうです。
-
This is a Python implementation of John Gruber's Markdown.
https://github.com/Python-Markdown/markdown - CommonMark が策定されたのは 2014/10/25 です。
- Original に準拠したライブラリがあったのは驚き...
- Sphinx
- サービス
- Qiita と Zenn
- Qiita, Zenn はなぜサーバサイドで markdown -> html の変換を行っているのか?音速で返ってきてびびった...
- Qiita の markdown をそのまま Zenn に貼り付けても全然互換性がない... 結局、移植性みたいなのってあんまり気にしてもしかたないのかな...
- 方言とかいうよりも、ライブラリの選定が重要になってくるのではないのか...
- Qiita Marker
- GMF 方言
- JavaScript
4. ライブラリが採用しているパーサ
- React
- marked-react
- markdown-to-jsx
- react-markdown
- react-remark
- React (Next.js に特化したもの)
- @next/mdx ... local の MDX ファイルが対象です, hot reload が効きます
- @mdx-js/loader ... Webpack を使って bundle しています
- @mdx-js/mdx
- unified
- @mdx-js/mdx
- @mdx-js/loader ... Webpack を使って bundle しています
- next-mdx-remote ... remote のファイルが対象です, hot reload は効きません
-
@mdx-js/mdx
- unified
-
@mdx-js/mdx
- 上記2つのライブラリは Next.js の公式ドキュメントに使用方法の記載があります。
- mdx-bundler
-
@mdx-js/esbuild
-
@mdx-js/mdx
- unified
-
@mdx-js/mdx
-
@mdx-js/esbuild
- @next/mdx ... local の MDX ファイルが対象です, hot reload が効きます
- Vue.js
- そのほか
- Markdoc ... Stripe のドキュメント, 技術ドキュメントガチ勢が作ったライブラリ
補足1: なにを調べたの?
- 上記に前節「3. サービスが採用しているパーサ」で挙げたものより低レイヤのライブラリを列挙しました。SSG やサービスに結びついていないライブラリ。
- 3, 4 をまとめる方法が思いつかなかった。
- 各 JavaScript フレームワークで定義したコンポーネントを組み込める Markdown パーサで分類しました。
- 調べ方は package.json を掘り下げただけでソースコードをちゃんと読んで確認した訳ではありません。
補足2: 感想
- npm trends では unified, remarked, markdown-it が3強のパーサだが、知名度の高いサービスやライブラリは marked を使ってない?
- おそらく marked は小さい実装だから?拡張したりしないなら marked がいいのかな...
- Vue.js の公式ドキュメントの最初の方にあるサンプルコードで marked が使われているのは見たことがある...
補足3:
- next-mdx-remote と mdx-bundler の共通点
- next-mdx-remote と mdx-bundler が存在する理由
-
getStaticProps は JSON に変換可能なやつしか渡せない っぽいのでMDX のコンポーネントをどう渡すか迷ってたんだけど、next-mdx-remote 使うべきかなこれ使わないでできるなら使いたくないんだけど
https://twitter.com/d151005/status/1746103725209591877
-
- package.json に unified があるので、どこかで unified を使っているはず...
- でも
unified().use(rehypeParse)
のようなプラグインを組み合わせているコードが見当たらない - 別のアプローチを取っているように見える...
- next-mdx-remote と mdx-bundler が存在する理由
- next-mdx-remote と mdx-bundler の相違点
- mdx-next-remote は mdx ファイル内で import はできない
- RSC を使えば getStaticProps を介さないから serialize したり code に変換しなくていいんじゃないのか?
- next-mdx-remote には RSC 対応版が存在する... なにをしているんだろう?
- さらに next-mdx-remote のリポジトリでなにかを議論している...
- @mdx-js/mdx だけでもできる様子...(next-mdx-remote, mdx-bundler を使わなくても)
-
This is similar to what people sometimes use mdx-bundler or next-mdx-remote for, but MDX also supports it
https://mdxjs.com/guides/mdx-on-demand/
-
- 比較記事
5. 独自記法による拡張について
Zenn の生みの親である catnose さんは拡張記法を新たに定義することについては否定的なようです。
↓ ガチ勢は Qiita ↔ Zenn の方言のパーサを実装してしまう... でも自分にはこんな能力はない...
↓ ちょっと面倒みたいな意見も見る...
https://x.com/ubugeeei/status/1774069508258562550
https://x.com/ubugeeei/status/1774070092625801280
https://x.com/ubugeeei/status/1774072621547798933
6. そのほか
背景
- どれが一番使われているパーサ、方言なのか知りたかった
- 諸般の事情で SSG としてではなく SSR で mdx-next-remote を使っていて、なんか実装が重く感じた。こんなにコネコネしないといけないのかな?みたいなかんじで。これで良いのか、これが一般的なのか疑問だった。Next.js 使うなら一般的だと思った。でもなんか重い...orz
感想
- 移植性を考えると Vue.js の template, React の JSX を使うよりも markdown の拡張記法を導入したほうがよい?
- 拡張したいなって思って Markdown のパーサを調べたけど、拡張しないほうがよいみたいな気もしてきた...
- 互換性がないから結局最初のライブラリの選定は大事なのかも...
- 変換速度とかどうなんだろう...
- commonmark.js で...
- marked は大御所では採用されていないが変換速度は速い
- 移植性みたいなことを考えると、いっそ独自の拡張記法は導入しない仕様のゆるふわな GFM も禁止して、 CommonMark + HTML タグだけってのもありなのではないのか...
- あるいは WYSIWYG のエディタを提供して HTML で保存するみたいな?でもそうすると WYSIWYG のエディタにロックインされるのかな?