首頁
學習紀錄
遊戲心得影視Life書單案件檔案
Side Projects委託作品與二創互動實驗場
Kurau
百百 BLOG
首頁
學習紀錄
遊戲心得影視Life書單案件檔案
Side Projects委託作品與二創互動實驗場
Kurau

Kurau Blog

「隨心而寫,真真假假,都是我」

一個記錄生活、輸出興趣的個人空間。
遊戲、影視、閱讀、學習……每一段體驗都值得留下文字。

頁面導覽

  • 學習紀錄
  • 遊戲心得
  • 影視Life
  • 書單
  • 委託作品與二創
  • Kurau
  • 合作邀請

找到我

歡迎來 Discord 找我聊天!

“曾經發生的事不可能忘記,只是暫時想不起來而已。”-《神隱少女》

© 2026 Kurau All rights reserved

開發工具

讓你網頁的Code語法 Hightlight起來

By Kurau·2023-02-12·Updated 2026-05-09·4 分鐘閱讀

目錄

TL;DR
Web 端 Syntax Highlighting 三主流:Prism.js(輕量、CSS-based)、Highlight.js(老牌、語言多)、Shiki(2026 推薦)(VS Code 同款、build time 渲染、零 runtime cost)。配 rehype-pretty-code 是 Next.js / MDX 黃金組合。

教學 (一般React環境)

要在 React 中呈現帶有語法高亮的代碼塊,您可以使用第三方庫,例如,Prism.js 或 Highlight.js。這些庫可以自動對代碼進行語法高亮,並呈現具有顏色標記的代碼塊。

以 Prism.js 為例,您需要在 React 項目中安裝 Prism.js 庫:

npm install prismjs
npm i @types/prismjs --save-dev
Plain

然後,您需要匯入 Prism.js 並選擇您想要的語言(例如,JavaScript):

import React from 'react';
import Prism from 'prismjs';
import 'prismjs/components/prism-javascript';

function ExampleCodeBlock() {
  return (
    <pre>
      <code className="language-javascript">
        {`
          // Example code block
          function example() {
            console.log("Hello, World!");
          }
        `}
      </code>
    </pre>
  );
}

export default ExampleCodeBlock;
JavaScript

這段代碼定義了一個名為 **ExampleCodeBlock** 的 React 組件,該組件將返回一個預先格式化的代碼塊,其中包含示例代碼,並將其類名設置為 **language-javascript**。這將告訴 Prism.js 該代碼是 JavaScript 代碼,因此需要進行語法高亮。

您還需要匯入 Prism.js 的 CSS 樣式以使代碼塊顯示有顏色標記的語法高亮:

import 'prismjs/themes/prism.css';
JavaScript

請注意,您需要確保將 CSS 文件路徑正確引入您的 React 項目,並且它必須可以在 Web 浏览器中訪問到,以便使用

useEffect(() => {
        Prism.highlightAll()
}, [])
TypeScript

Common CodeBlock 我寫好的

interface Props1 {
    children: React.ReactNode
}

export const CodeBlockTS: React.FC<Props1> = ({ children }) => (
    <pre>
        <code className="language-typescript" >
            {children}
        </code>
    </pre>
);
TypeScript

Next.js中如何使用

和前面的方法完全不同 (也許這個方法 前面也可以用這樣 但我還沒測試)

npm install prismjs
npm i @types/prismjs --save-dev
npm i react-syntax-highlighter
npm i @types/react-syntax-highlighter
Plain

然後打上這邊,之後就能夠使用了

import { Prism } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';

<Prism language="javascript" style={vscDarkPlus}>
   {`/* Your Code Here */`}
</Prism >
TypeScript

新增複製按鈕功能 (新版做法)

What is the easiest or recommended method to add a copy code button? · mdx-js · Discussion #1948
Hi, I was wondering what is the easiest or recommended method to add a copy code button, like in the mdx docs page or like in the github markdown view. https://github.com/orgs/mdx-js/discussions/1948

先安裝clsx 為了讓css可以用複雜的邏輯

npm install clsx
JavaScript

接著創建一個複製的Commponent如下:記得搭配的是上面的Next.js中如何使用喔 (非Next.js中的第一版那個 最上面的我還沒測試)

import clsx from 'clsx'
import React from 'react'

interface ICopyToClipboard {
    children: React.ReactNode
}

export const CopyToClipboard = ({ children }: ICopyToClipboard) => {
    const textInput = React.useRef<HTMLDivElement>(null)
    const [hovered, setHovered] = React.useState(false)
    const [copied, setCopied] = React.useState(false)

    const onEnter = () => {
        setHovered(true)
    }

    const onExit = () => {
        setHovered(false)
        setCopied(false)
    }

    const onCopy = () => {
        setCopied(true)
        if (textInput.current !== null && textInput.current.textContent !== null)
            navigator.clipboard.writeText(textInput.current.textContent)
        setTimeout(() => {
            setCopied(false)
        }, 2000)
    }

    return (
        <div
            ref={textInput}
            onMouseEnter={onEnter}
            onMouseLeave={onExit}
            className="relative code-block"
        >
            {hovered && (
                <button
                    aria-label="Copy code"
                    type="button"
                    className={clsx(
                        'absolute right-2 top-2 w-8 h-8 p-1 rounded border-2 bg-gray-700 dark:bg-gray-800',
                        {
                            'focus:outline-none focus:border-green-400 border-green-400': copied,
                            'hover:border-gray-300': !copied,
                        }
                    )}
                    onClick={onCopy}
                >
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                        fill="none"
                        className={copied ? 'text-green-400' : 'text-gray-300'}
                    >
                        {copied ? (
                            <>
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
                                />
                            </>
                        ) : (
                            <>
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
                                />
                            </>
                        )}
                    </svg>
                </button>
            )}
            {children}
        </div>
    )
}
JSON

我們只需要將程式碼如下 包起來就殼已了

<CopyToClipboard>
	<Prism language="javascript" style={vscDarkPlus}>
                        {`service firebase.storage {
    match /b/{bucket}/o {
        match /{allPaths=**} {
            // 只允許已經通過身份驗證的用戶進行讀寫
            allow read, write: if request.auth.uid != null;
        }
    }
}`}
	</Prism>
</CopyToClipboard>
JavaScript

最後我們優化一下

我們直接把Prism元件放到CopyToCLipboard去,這樣使用就更方便。

import clsx from 'clsx'
import React from 'react'
import { Prism } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';

interface ICopyToClipboard {
    children: string
}

export const CopyToClipboard = ({ children }: ICopyToClipboard) => {
    const textInput = React.useRef<HTMLDivElement>(null)
    const [hovered, setHovered] = React.useState(false)
    const [copied, setCopied] = React.useState(false)

    const onEnter = () => {
        setHovered(true)
    }

    const onExit = () => {
        setHovered(false)
        setCopied(false)
    }

    const onCopy = () => {
        setCopied(true)
        if (textInput.current !== null && textInput.current.textContent !== null)
            navigator.clipboard.writeText(textInput.current.textContent)
        setTimeout(() => {
            setCopied(false)
        }, 2000)
    }

    return (
        <div
            ref={textInput}
            onMouseEnter={onEnter}
            onMouseLeave={onExit}
            className="relative code-block"
        >
            {hovered && (
                <button
                    aria-label="Copy code"
                    type="button"
                    className={clsx(
                        'absolute right-2 top-2 w-8 h-8 p-1 rounded border-2 bg-gray-700 dark:bg-gray-800',
                        {
                            'focus:outline-none focus:border-green-400 border-green-400': copied,
                            'hover:border-gray-300': !copied,
                        }
                    )}
                    onClick={onCopy}
                >
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                        fill="none"
                        className={copied ? 'text-green-400' : 'text-gray-300'}
                    >
                        {copied ? (
                            <>
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
                                />
                            </>
                        ) : (
                            <>
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
                                />
                            </>
                        )}
                    </svg>
                </button>
            )}
            <Prism language="jsx" style={vscDarkPlus}>
                {children}
            </Prism>
        </div>
    )
}
JavaScript

就只需要使用CopyToClipboard然後寫上code就完成了

<CopyToClipboard>
                    {`service firebase.storage {
    match /b/{bucket}/o {
        match /{allPaths=**} {
            // 只允許已經通過身份驗證的用戶進行讀寫
            allow read, write: if request.auth.uid != null;
        }
    }
}`}
</CopyToClipboard>
JavaScript

新增複製按鈕功能 (舊版作法)

npm i react-copy-to-clipboard
npm i @types/react-copy-to-clipboard
Plain

之後就可以使用啦

import React from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { CopyToClipboard } from 'react-copy-to-clipboard';

<CopyToClipboard text={`your code`}>
          <button>Copy</button>
</CopyToClipboard>
TypeScript

目錄

  • Next.js中如何使用
  • 新增複製按鈕功能 (新版做法)
  • 新增複製按鈕功能 (舊版作法)

◆ 相關文章

  • 複製你的hightlight 程式碼

    2026-05-09
  • 網頁上實現markdown編輯

    2026-05-09
  • github 多個帳戶 SSH登入

    2026-05-09
  • lodash

    2026-05-09
← 上一篇免費伺服器 介紹下一篇 →載入圖片的方法 base64 跟 require載入圖片 哪一個比較快

◆ 關於作者

Kurau

個人寫作 / 創作的 SoT,記錄遊戲、影視、學習與生活。

更多 Kurau 的文章