0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

keitamaxAdvent Calendar 2024

Day 19

マークダウンで書いたコードをみやすくする

Last updated at Posted at 2024-12-18

はじめに

こんにちは、エンジニアのkeitaMaxです。

マークダウンで書いたコードをみやすくしようと思います。

やりたいこと

スクリーンショット 2024-12-18 19.37.22.png

現状上記のようにコードを書くとかなりみづらい状態になってしまっています。

これをVSCodeのように見やすいものを作成しようと思います。

インストール

react-syntax-highlighterをインストールします。

npm i react-syntax-highlighter

また、React Syntax Highlighterも以下コマンドでインストールします。

npm install react-syntax-highlighter --save

実装

最初にどのように実装したのかコードを記載します。

index.tsx
import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';

export const AddArticle = React.memo(function AddArticle() {
    const [markdown, setMarkdown] = useState<string>('');

    // コードブロックのカスタムレンダラー
    const components = {
        code({ node, inline, className, children, ...props }: any) {
            const match = /language-(\w+)(:(.+))?/.exec(className || '');
            const language = match ? match[1] : null;
            const fileName = match && match[3] ? match[3] : null; // `:`の右側をファイル名として取得

            return !inline && language ? (
                <div>
                    {/* ファイル名がある場合は、角丸と灰色の背景を適用 */}
                    {fileName && (
                        <div className="bg-gray-500 text-white px-2 py-1 text-sm rounded-md w-fit mb-2 -mt-3 -ms-5">
                            {fileName}
                        </div>
                    )}

                    <SyntaxHighlighter
                        style={atomDark} // 好みのテーマに変更可能
                        language={match?.[1]}
                        PreTag="div"
                        {...props}
                    >
                        {children && String(children)?.replace(/\n$/, '')}
                    </SyntaxHighlighter>
                </div>
            ) : (
                <code className={className} {...props}>
                    {children}
                </code>
            );
        },
    };

    return (
        <div className="flex h-screen">
            {/* 左側のエディタ */}
            <div className="w-1/2 p-4">
                <h2 className="text-xl font-bold mb-4">Markdownエディタ</h2>
                <textarea
                    className="w-full h-full p-2 border rounded-md"
                    placeholder="ここにマークダウンを入力してください..."
                    value={markdown}
                    onChange={(e) => setMarkdown(e.target.value)}
                />
            </div>

            {/* 右側のプレビュー */}
            <div className="w-1/2 p-4 border-l overflow-y-auto">
                <h2 className="text-xl font-bold mb-4">プレビュー</h2>
                <div className="prose prose-lg max-w-none">
                    <ReactMarkdown
                        remarkPlugins={[remarkGfm]}
                        components={components} // カスタムレンダラーを指定
                    >
                        {markdown}
                    </ReactMarkdown>
                </div>
            </div>
        </div>
    );
});

export default AddArticle;

前回からcomponentsというものを追加し、

<ReactMarkdown
    remarkPlugins={[remarkGfm]}
    components={components} // カスタムレンダラーを指定
>
    {markdown}
</ReactMarkdown>

ReactMarkdownに読み込ませています。

解説?

const match = /language-(\w+)(:(.+))?/.exec(className || '');
const language = match ? match[1] : null;
const fileName = match && match[3] ? match[3] : null; 

これで:の右側をファイル名として、左側をファイルの型として認識させています。

return !inline && language ? (
    <div>
        {/* ファイル名がある場合は、角丸と灰色の背景を適用 */}
        {fileName && (
            <div className="bg-gray-500 text-white px-2 py-1 text-sm rounded-md w-fit mb-2 -mt-3 -ms-5">
                {fileName}
            </div>
        )}

        <SyntaxHighlighter
            style={atomDark} // 好みのテーマに変更可能
            language={match?.[1]}
            PreTag="div"
            {...props}
        >
            {children && String(children)?.replace(/\n$/, '')}
        </SyntaxHighlighter>
    </div>
) : (
    <code className={className} {...props}>
        {children}
    </code>
);

ここで実際にコードに色をつけてみやすくしています。

どんな感じの見た目か

スクリーンショット 2024-12-18 19.47.55.png

こんな感じになっています!

おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました!

参考

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?