Jika anda membangun website anda menggunakan Strapi atau dari sumber source markdown yang lain maka kalian akan mengetahui bahwa data yang kita ambil dari untuk menampilkan content adalah dalam bentuk rich-text, namun secara default Markdown tidak mendukung untuk syntax hightlighting.
Sehingga jika anda ingin menambahakan sintaks highlighting pada artikel yang anda buat maka anda perlu menambahakan beberapa package tambahan agar tampilan sintaks pada blog anda menjadi lebih menarik.
Apa saja yang dibutuhkan
kita membutuhkan react-markdown
dan react-syntax-hightlighter
. React markdown kita gunakan untuk rendering dari markdown ke HTML dan react syntax highlighter untuk menangani highlighting.
npm install react-markdown react-syntax-hightlighter
atau
yarn add react-markdown react-syntax-hightlighter
Basic React Markdown
Untuk menampilkan sebuah konten dalam bentuk markdown agar dapat tampil, anda dapat mengirim data content anda kedalam ReactMarkdown seperti berikut
const Article = ({ article }) => <ReactMarkdown children={article.content} />;
Menambahkan code
Component
Sekarang anda dapat menambahkan syntaks highlighting dengan menambahkan value pada prop components
seperti berikut.
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";import { materialDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
const Article = ({ article }) => ( <ReactMarkdown children={article.content} components={{ code({ node, inline, className, children, ...props }) { const match = /language-(\w+)/.exec(className || ""); return !inline && match ? ( <SyntaxHighlighter children={String(children).replace(/\n$/, "")} style={materialDark} language={match[1]} PreTag="div" // {...props} /> ) : ( <code className={`bg-zinc-200 dark:bg-zinc-700 p-1 text-black dark:text-white rounded ${className}`} {...props} > {children} </code> ); }, }} />);
Prop components
pada markdown menerima beberapa key
dan value
, salah satu keynya yaitu code
, dan kita bisa beri value berupa CodeBlock
yang telah kita buat.
Disini saya menggunakan tema materialDark
, anda bisa explore Color Scheme sesuai dengan project anda sendiri.
Saya juga menggunakan tailwind.css
untuk styling beberapa elemen seperti pada tag code
. Selain itu saya juga override untuk beberapa style pada tailwind typography. Jika kalian menggunakan metode styling yang lain anda bisa skip kode dibawah.
module.exports = { // ... theme: { extend: { typography: { DEFAULT: { css: { pre: { backgroundColor: "none", padding: "0 !important", marginLeft: "0 !important", marginRight: "0 !important", marginTop: "0 !important", borderRadius: "0.25rem !important", marginBottom: "10px !important", }, "pre div ": { margin: "0px !important", }, code: { color: "var(--primary-text)", backgroundColor: "var(--primary-inline-code)", fontWeight: 400, padding: "2px 5px", }, "code::before": { content: '""', }, "code::after": { content: '""', }, }, }, }, }, }, plugins: [require("@tailwindcss/typography")],};
Pada kode diatas kita hanya mereset beberapa style seperti override style nya agar menghilangkan margin, hapus tanda petik pada blok kode dll.
Tampilkan nama bahasa pemrograman yang digunakan.
Untuk menampilkan nama bahasa pemrograman sesuai dengan blok kode kita kita dapat memodifikasi code
yang telah kita buat. Kita dapat melakukan ini dengan membungkus SyntaxHightlighter dengan sebuah div dan beri posisi relative lalu didalam div tersebut buatlah suatu paragraf dengan posisi absolute. Paragraf inilah yang nantinya akan menampilkan bahasa pemrograman yg kita gunakan.
Disini saya menggunakan component Language
untuk menampilkan nama extension pada syntax highlight kita.
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";import { materialDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
const Article = ({ article }) => ( <ReactMarkdown children={article.content} components={{ code({ node, inline, className, children, ...props }) { const match = className !== undefined ? className.replace("language-", "") : true; return !inline && match ? ( <div className="relative"> {(match !== "shell" || match === null) && ( <Language match={match} /> )} <SyntaxHighlighter children={String(children).replace(/\n$/, "")} style={materialDark} language={match} PreTag="div" {...props} /> </div> ) : ( <code className={`bg-zinc-200 dark:bg-zinc-700 p-1 text-black dark:text-white rounded ${className}`} {...props} > {children} </code> ); }, }} />);
Berikut merupakan component Language.js
import classNames from "classnames";import { languageMap, shortNameMap } from "./constant";
const Language = ({ match }) => { return ( <span className={classNames( languageMap[match], `font-monospace text-sm tracking-wide rounded-b-md absolute right-2 z-40 top-0 px-2 py-1` )} > {shortNameMap(match)} </span> );};
export default Language;
Pada Language.js
kita mengimpor languageMap
dan shortNameMap
. file languageMap
berisi style classname untuk masing-masing bahasa pemrograman, sedangkan shortNameMap
berfungsi untuk mengconvert beberapa bahasa permrograman menjadi nama file extensinya saja.
export const languageMap = { html: "bg-[#E34C26] text-black", css: "bg-[#1572B6] text-white", javascript: "bg-[#F0DB4F] text-black", typescript: "bg-[#007ACC] text-black", // ...other};
export const shortNameMap = (match) => { const listExtensionOfLanguage = { javascript: "js", typescript: "ts", csharp: "cs", python: "py", // ...other }; return listExtensionOfLanguage[match] || match;};
Untuk contoh diatas saya menggunakan tailwindcss untuk melakukan styling. di file inilah kita melakukan customisasi warna text & background
Sekarang blok code
anda akan terlihat lebih menarik dengan syntax hightlighting yang telah kita terapkan.
Terima kasih 🙂