DEV Community

gumi TECH for gumi TECH Blog

Posted on

3

React入門 02: ライブラリMarkedでMarkdownの機能を加える

「React入門 01: コンポーネントを組み立てる」(以下「React入門 01」)では、簡単なコンポーネントを組み合わせて、シンプルなSPAのページをつくりました。今回は、Reactで差し込む要素のテキストを、Markdownで書いてみます。MarkdownのテキストをHTMLの記述に変えるために使うのは、JavaScriptライブラリMarkedです。また、Reactで生のHTMLコードを差し込む場合の特別な仕組みについてもご説明します。

Markdown記法とMarkedのインストール

Markdown」は、テキストの書式を定める簡易な記法です。HTMLコードよりも簡単な書き方で、文字や段落の表記が整えられます。JavaScriptライブラリMarkedは、npmでReactアプリケーションのディレクトリにつぎのようにインストールします。



npm install marked --save


Enter fullscreen mode Exit fullscreen mode

marked()関数でMarkdownをHTMLの記述に変える

「React入門 01」で書いたJavaScriptコードに手を加えてゆきましょう。まず、src/components/CommentList.jsのテキストにつぎのようにMarkdown記法を加えます。*(アスタリスク)と_(アンダースコア)は同じ働きです。それを確かめるために、あえて両方用いました。記号ひとつで文字を挟めば強調・斜体(<em>)、ふたつなら強い重要性・太字(<strong>)になります。



const CommentList = () => {
  return (
    <div className="CommentList">
      <Comment author="ヘンリー・キッシンジャー">
      チャンスは__貯金__できない。
      </Comment>
      <Comment author="マーク・トウェイン">
      禁煙なんてたやすい。私は*何千回*もやった。
      </Comment>
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

テキストは子コンポーネント(src/components/Comment.js)が受け取りますので、MarkdownテキストをHTMLの記述に変換するコードは、項目のコンポーネント(Comment)に書き加えます。Markedライブラリからimportするのは関数marked()です。引数に渡したMarkdownのテキストをHTMLの記述にして返します。なお、引数は文字列でなければならないので、childrenで得た子要素はtoString()メソッドで文字列にしておきましょう。

ところが、JavaScriptコードをつぎのように書き替えて、marked()関数の戻り値をそのまま差し込むと、タグがテキストとして示されてしまいます(図001)。



import marked from 'marked';

const Comment = (props) => {
  return (
    <div className="Comment">

      {marked(props.children.toString())}
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

図001■タグがテキストとして表示される

02_003.png

dangerouslySetInnerHTMLによりHTMLのコードを差し込む

生のHTMLコードが差し込めてしまうと、「クロスサイトスクリプティング」(XSS)による攻撃を受けるかもしれません(「クロスサイトスクリプティング対策 ホンキのキホン」参照)。そのため、ReactはHTMLのタグは、そのままでは加えられないようにしたのです。テキストをHTMLとして差し込むためには、dangerouslySetInnerHTMLプロパティを用いなければなりません(「ReactのdangerouslySetInnerHTML使ってみた」参照)。与えるのはオブジェクトで、プロパティ__htmlにHTMLコードを値として定めます。

もっとも、dangerouslySetInnerHTMLプロパティにオブジェクトを直に与えるのは安全といえません。別に定めたメソッド(rawMarkup())を呼び出し、その本体でHTMLコードをつくって返すのがよいでしょう。そこで、コンポーネント(Comment)はさらにつぎのように書き替えます。プロパティに与えるメソッドの呼び出しは、波かっこ{}でくくってください。こうすれば、コンポーネントの要素にはメソッドから返されたコードが、HTMLとして描かれるはずです(図002)。



const Comment = (props) => {
  return (
    <div className="Comment">

      {/* {marked(props.children.toString())} */}
      <span dangerouslySetInnerHTML={rawMarkup(props.children.toString())} />
    </div>
  );
};

const rawMarkup = (markup) => {
  const rawMarkup = marked(markup);
  return { __html: rawMarkup };
};


Enter fullscreen mode Exit fullscreen mode

図002■MarkdownテキストがHTMLとして描かれる

02_004.png

書き改めたふたつのコンポーネントのJavaScriptコードは、それぞれ以下のコード001と002にまとめました。

コード001■src/components/CommentList.js



import React from 'react';
import Comment from './Comment';

const CommentList = () => {
  return (
    <div className="CommentList">
      <Comment author="ヘンリー・キッシンジャー">
      チャンスは__貯金__できない。
      </Comment>
      <Comment author="マーク・トウェイン">
      禁煙なんてたやすい。私は*何千回*もやった。
      </Comment>
    </div>
  );
};

export default CommentList;


Enter fullscreen mode Exit fullscreen mode

コード002■src/components/Comment.js



import React from 'react';
import marked from 'marked';

const Comment = (props) => {
  return (
    <div className="Comment">
      <h2 className="CommentAuthor">
      {props.author}
      </h2>
      <span dangerouslySetInnerHTML={rawMarkup(props.children.toString())} />
    </div>
  );
};

const rawMarkup = (markup) => {
  const rawMarkup = marked(markup);
  return { __html: rawMarkup };
};

export default Comment;


Enter fullscreen mode Exit fullscreen mode

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Cloudinary image

Video API: manage, encode, and optimize for any device, channel or network condition. Deliver branded video experiences in minutes and get deep engagement insights.

Learn more