ブログ

日常の忘備録

reactでmarkdownする時はremarkを使うといいよという話01

こんにちは。学校が夏休みに突入し、うかれているtako_programingです。実は最近10hzというマークダウンをチーム内で共有するwebサービスの開発に携わらせてもらってるんですが、その中でmarkdownの処理の所を任されて1から書くとひどいことになる気がしたのでいろんなライブラリを駆使してやることにしました。

導入で詰まったところ

開発の最初の頃はreact-markdownを使ってマークダウンのプレビューをしていたみたいで、これはこれで便利ではあるのですが、このライブラリはcommon markに準拠していて、僕らはGFM(GitHub Flavored Markdown)でプレビューしたかったので、remark-reactに変更しました。このライブラリはcommon markでもプレビューできるしGFMでもプレビューできる優れもので、即採用することに決めました。 採用することを決めたのはいいんですが、remark-parseのリポジトリのREADME通りに書くと、GFMのtaskListが表示されません。

var React = require('react'),
    remark = require('remark'),
    reactRenderer = require('remark-react');

var App = React.createClass({
    getInitialState() {
        return { text: '- [ ] aaa¥n- [ ] bbb¥n- [ ] ccc' };
    },
    onChange(e) {
        this.setState({ text: e.target.value });
    },
    render() {
        return (<div>
            <textarea
                value={this.state.text}
                onChange={this.onChange} />
            <div id='preview'>
                {remark().use(reactRenderer).processSync(this.state.text).contents}
            </div>
        </div>);
    }
});

React.render(<App />, document.getElementById('app'));

こんなふうに書いても実際のプレビュー画面では通常のリストのように表示されます。READMEには「デフォルトでGFMモードです」みたいなことが書いてあったのでおかしいぞ?となって良いことではないのかもしれませんが急いでいて時間もなかったのでリポジトリにIssueで質問した所「optionでsanitizeをfalseにするんだよ!!」と懇切丁寧に教えていただき、

<div id='preview'>
    {remark().use(reactRenderer, { sanitize: false }).processSync(this.state.text).contents}
</div>

のように書き換えることで、Tasklistが表示されるようになりました。ありがたい。 ですが、ほっとしたのもつかの間、次の敵「コードブロックのシンタックスハイライト」が現れました。デフォルトのままではコードブロックにシンタックスハイライトがつかないんですが、放置するわけにもいかないのでシンタックスハイライトに対応させることにしました。 リポジトリのREADMEでシンタックスハイライト用に紹介されているのはremark-react-lowlightですが、こちらの環境が悪いのか挙動がすこぶる不安定で他の方法を探すことにしました。remark-reactでは、

remarkReactComponents: {
  a: MyLink,
  p: MyParagraph
}

のようにして指定したタグを指定したReactComponentで置き換えることができます。なので、codeタグの所をいい感じのシンタックスハイライトがつくコンポーネントで置き換えればいいのではないかと思い試してみました。 最初はmarkdownエディタの方で使っているreact-codemirrorを試しましたが、こちらも(結構前のことなので詳しく覚えてないが)不安定というか描画がなんか明らかにおかしくなってしまい採用を断念しました。いま挙げた2つのライブラリもどうにかすればちゃんと使えるのだとは思いますが、そこに時間をかけたくなかったのでもう少しなにもしなくても使えるライブラリを探すことにしました。で、最終的に今使っているのがreact-hilightです。なので最終的には

{remark().use(reactRenderer, {
     sanitize: false,
     remarkReactComponents: {
         code: react-highlight
    }
 }).processSync(this.state.content.content).contents}

という感じになりました。react-hilightを使う時はhilight.jsをimportするのを忘れないようにしてください。


これでとりあえずはreact-remarkをつかってマークダウンを描画することができるようになりました。ですが、このままだとtaskListにチェックしても参照先のmarkdownのテキストにはチェックが入らないという問題が発生します。これの解決策はまた次の記事で。