0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React-Markdownをカスタマイズする話

Posted at

reactでのmarkdownを表示するライブラリ react-markdown のカスタマイズ方法をメモしておきます

今回のカスタマイズするポイントは以下です

  • リンクを新規ウィンドウ(タブ)で開く
  • コードブロックのシンタックスハイライト

カスタマイズの書き方

ReactMarkdownにて各要素のタグに関する処理はcomponentsに記載すればOKです

今回はリンク(a)とコードブロック(code)のカスタマイズを行います

<ReactMarkdown
    components={{
        a: AnchorTag,
        code: CodeBlock,
    }}
>

コンポーネントのカスタマイズ

リンクを新規ウィンドウ(タブ)で開く

リンク(a)にカスタム定義 AnchorTagを指定します

a: AnchorTag,

の部分です

const AnchorTag = ({ node, children, ...props }: any) => {
    try {
        new URL(props.href ?? "");
        props.target = "_blank";
        props.rel = "noopener noreferrer";
    } catch (e) { }
    return <a {...props}>{children}</a>;
}

ソースの解説は不要かな。
aのtargetとrelを指定しました

コードブロックのシンタックスハイライト

コードブロック(code)にカスタム定義 CodeBlockを指定します

code: CodeBlock,

CodeBlockでは、言語指定した場合にSyntaxHighlighterを使用します
今回はデザイン atomDarkを使っています

import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 
const CodeBlock = ({ inline, className, children, }: any) => {
    if (inline) {
        return <code className={className}>{children}</code>;
    }
 
    const match = /language-(\w+)/.exec(className || '');
    if (!match) {
        return <code className={className}>{children}</code>;
    }
 
    const lang = match && match[1] ? match[1] : '';
 
    return (
        <SyntaxHighlighter
            style={atomDark}
            language={lang}
        >
            {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
    );
}

終いに

 今回はreact-markdownのカスタマイズに関して書きました
一度定義したら変更することがないので忘れがちなので記事にしました
特にアンカー(a)は基本仕様が_blankだったかなと勘違いしてました

参考:ソース

import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 
type Props = {
    children?: string | null | undefined;
};
 
const CustomReactMarkdown: React.FC<Props> = (props: Props) => {
    return <ReactMarkdown
        components={{
            a: AnchorTag,
            code: CodeBlock,
        }}
    >
        {props.children}
    </ReactMarkdown>
}
 
export default CustomReactMarkdown
 
 
const CodeBlock = ({ inline, className, children, }: any) => {
    if (inline) {
        return <code className={className}>{children}</code>;
    }
 
    const match = /language-(\w+)/.exec(className || '');
    if (!match) {
        return <code className={className}>{children}</code>;
    }
 
    const lang = match && match[1] ? match[1] : '';
 
    return (
        <SyntaxHighlighter
            style={atomDark}
            language={lang}
        >
            {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
    );
}
 
const AnchorTag = ({ node, children, ...props }: any) => {
    try {
        new URL(props.href ?? "");
        props.target = "_blank";
        props.rel = "noopener noreferrer";
    } catch (e) { }
    return <a {...props}>{children}</a>;
}
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?