react-syntax-highlighter - 將markdown的代碼區塊變漂亮,並加上複製功能
2024-10-25 03:00
前言
最近上網看文章時發現有些文章的代碼區塊會根據代碼的檔案類型來附加顏色,讓我也想將我的 blog 加上此功能,於是想到就做,此篇文章主要是做一個紀錄和教學。
步驟 1
先下載所需的套件:
console1npm i react-markdown 2npm i remark-gfm 3npm i react-syntax-highlighter
- react-markdown: 解析markdown檔案。
- remark-gfm: 支援url、刪除線、表格等功能。
- react-syntax-highlighter: 本文主角,用來處理代碼區塊。
步驟 2
使用 react-markdown 來解析 markdown,並修改代碼區塊:
tsx1import ReactMarkdown from "react-markdown"; 2import remarkGfm from "remark-gfm"; 3import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; 4import { oneLight } from "react-syntax-highlighter/dist/cjs/styles/prism"; 5 6const PostPage: React.FC = () => { 7 const post = `...你的markdown內容...` 8 9 SyntaxHighlighter.registerLanguage("ts", typescript); 10 SyntaxHighlighter.registerLanguage("typescript", typescript); 11 SyntaxHighlighter.registerLanguage("tsx", tsx); 12 13 return ( 14 <div className="post-page"> 15 <ReactMarkdown 16 remarkPlugins={[remarkGfm]} 17 components={{ 18 code({ inline, className, ...props }: any) { 19 const hasLang = /language-(\w+)/.exec(className || ""); 20 return !inline && hasLang ? ( 21 <SyntaxHighlighter 22 style={oneLight} 23 language={hasLang[1]} 24 PreTag="div" 25 showLineNumbers={true} 26 useInlineStyles={true} 27 > 28 {String(props.children).replace(/\n$/, "")} 29 </SyntaxHighlighter> 30 ) : ( 31 <code className={className} {...props} /> 32 ); 33 }, 34 }} 35 > 36 {post} 37 </ReactMarkdown> 38 </div> 39 ); 40}; 41 42export default PostPage;
- oneLight: 白色模式的style,也有其他style可根據喜好來做使用。
- SyntaxHighlighter.registerLanguage: 將markdown代碼區塊中會使用到的語言給註冊進來,這邊我會將
ts
和typescript
都註冊起來,這樣只要輸入兩者其一都可以套用到style。同理,可以根據所需來引入所需語言,例如:json
、dart
、javascript
等等。 - hasLang: 取出是使用何種語言。
步驟 3 - 代碼複製
將代碼變得漂亮後,怎麼可以沒有複製代碼的功能呢,以下是實作:
tsx1import { useState } from "react"; 2import { FaCheck } from "react-icons/fa"; 3import { FaRegCopy } from "react-icons/fa6"; 4 5const Copy = ({ value }: { value: string }) => { 6 const [isCopy, setIsCopy] = useState<boolean>(false); 7 8 return isCopy ? ( 9 <FaCheck /> 10 ) : ( 11 <FaRegCopy 12 onClick={() => { 13 navigator.clipboard.writeText(value); 14 setIsCopy(true); 15 setTimeout(() => { 16 setIsCopy(false); 17 }, 3000); 18 }} 19 /> 20 ); 21}; 22 23export default Copy;
此功能在點擊之後會複製代碼,並替換icon,3秒後才可以重新複製。
同場加映 - 標題導航
這裡同場加映一下文章標題導航的功能:
下載所需套件
console1npm i rehype-slug 2npm i rehype-autolink-headings
- rehype-slug: 將markdown的標題產生id。
- rehype-autolink-headings: 將已有id的地方產生連結並指向該標題。
導航
當套件幫我們產生連結後,接下來只要透過 <a />
就可以導航到該標題了:
tsx1<a href={`#這裡填入產生的id`}>這裡填入產生的id</a>
最後
由此可見,該功能在知道使用何種套件後並不難實現,至成果展示,就是上面那些代碼區塊了,我們下次見~