LoginSignup
3
0

More than 1 year has passed since last update.

Markdownを強力に変換するNodeJSライブラリーremarkを使ってみた1

Last updated at Posted at 2022-12-02

これは yuriacats アドベントカレンダー3日目の記事です.


remarkって何?

remarkとは高機能なMarkdownパーサーライブラリー群です。
特徴としてmdastというAST1(抽象構文木)を介していることが挙げられます。ASTを仲介させることでMarkdownとTexを混在させた形態などにも対応できる柔軟さを生み出し、それもあってかGatsbyのスターターの一つである「gatsby-starter-blog」でも採用されています。ESにのみ対応しておりますが、TypeScript対応やDeno対応などモダンな開発にも適応できるサポートがあります。いかにプラグインを活用することでできることを箇条書きにします。

  • Githubの記法のMarkdown対応
  • 目次の作成
  • Markdownの文法チェック
  • Katex(TexのJS移植版)
  • その他のプラグイン

しかしながらかなり、使いこなすのが難しいライブラリーでもあると思います。公式で言っているように単にMarkdownをHTMLに変換する用途であればmicromarkなどの他のライブラリーを積極的に使っても良いかもしれません。

remarkの主要ライブラリー

ざっくりと入力と出力のからプラグインを割り出そうとすると以下のようになるかと思います。

出力\入力 HTML Markdown MDAST
HTML micromark2 rehype-stringify
Markdown micromark2 remarkStringify
MDAST rehype-parse remak-parse
  • HTMLのサポートをするため(rehype系プラグインを使うため)にremark-rehypeがある
  • ASTを扱う基幹ライブラリーとしてunifiedがある。

実装編1

(参考リポジトリー:https://github.com/yuriacats/remark-howto )

  • 目標 :テキストエリアに書かれた文字をそのままHTML要素に変換してHTMLを横に生成する。
yarn install remark unified remark-parse remark-rehype rehype-stringify
  1. Reactのチュートリアル等を参考にしながら、文字をそのまま返すような形にしてみよう。そうすると以下のコードになる。以下のコードをいじって今回はMarkdownをそのまま表示することにする。
import React, { useEffect, useState } from "react";

function App() {
    const [testText, setTestText] = useState("")
    const [resultText, setResultText] = useState("")
    return (
        <div>
            <div className="App">
                <input
                    value={testText}
                    onChange={(event) => setTestText(event.target.)}
                />
                <p>{testText}</p>
            </div>
        </div>
    );
}

export default App;

 
2. 今回は、Markdown→mdast→Stringに変換していきたいと思いますので使用するライブラリーである以下をimportします。大体途中まで書くとVSCodeが補完してくれるので、それでうまく書いていきましょう。

  • unified
  • remark-parse
  • remark-rehype
  • rehype-stringify
import React, { useEffect, useState, Fragment } from "react";
import { unified } from "unified";
import remarkParse from "remark-parse/lib";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify/lib";


function App() {
    const [testText, setTestText] = useState("")
    const [resultText, setResultText] = useState(Fragment)
    return (
        <div>
            <p>HTMLを入力すると下にMarkdown変換したものを表示するよ</p>
            <textarea
                rows={10}
                onChange={(event) => setTestText(event.target.value)}
            />
           <p>{testText}</p>
        </div>
    );
}

export default App;

  1. 今回は書いたものをリアルタイムでHTMLの例として出力したい
  • testTextが変化することをトリガーに関数を走らせましょう。
  • Dom動作を皮切りに変更させる場合useEffect(関数,[監視する変数])を利用すると良い。
  • Markdown → mdast → HTML という順番なので、remark-parse→remark-rehype→rehype-stringifyで変換するとよさそう。
  • 実際にremark-parseのチュートリアルには、remark-parse→remark-rehype→rehype-stringifyでチェーンが作られている。
  • 帰ってくるオブジェクトはPromiseなので.then内で変数を変更させて結果をDomに反映させてみた。

結果的には以下のようになるかと思います。(github)

import React, { useEffect, useState, Fragment } from "react";
import { unified } from "unified";
import remarkParse from "remark-parse/lib";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify/lib";


function App() {
    const [testText, setTestText] = useState("")
    const [resultText, setResultText] = useState(Fragment)
    useEffect(() => {
        const result = unified()
            .use(remarkParse)
            .use(remarkRehype)
            .use(rehypeStringify)
            .process(testText)
            .then((res) => setResultText(res.value))

    }, [testText])
    return (
        <div>
            <p>HTMLを入力すると下にMarkdown変換したものを表示するよ</p>
            <textarea
                rows={10}
                onChange={(event) => setTestText(event.target.value)}
            />
            <p>
                {resultText}
            </p>
        </div>
    );
}

export default App;

  1. AST(抽象構文木)とは文章を解析し、プログラムにとって不要なものを削除した結果として得られる木構造(グラフ構造の一種)の木。

  2. 他にもライブラリーの選択肢はあるかと思います。 2

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0