In the first step, we add the prismjs library and types to it in the project.
In the second step, we add a theme. The prismjs library already has several themes and we use one of them. You can
choose which one you like here: node_modules/prismjs/themes. Also, on the library website, you can choose from about a
million more.
In the third step, we create the component itself, this time with comments.
importReact,{useEffect,ReactNode,useState}from"react";importPrism,{Token}from"prismjs";exportinterfaceCodeProps{//Prismjs supports a lot more languages. The entire list can be found on the site,
//this is a list of those languages that will be useful to me.
language:'js'|'css'|'json'|'jsx'|'typescript'|'yml'|'Rust'|'bash',children:string}//We will use the tokenize method (https://prismjs.com/docs/Prism.html#.tokenize).
//Because other API methods directly manipulate DOM, and that’s not what we want.
//tokenToReactNode is our function that converts the result of executing tokenize into react components.
functiontokenToReactNode(token:Token|string,i:number):ReactNode{if(typeoftoken==="string"){return<spankey={i}>{token}</span>}elseif(typeoftoken.content==="string"){return(<spankey={i}className={`token ${token.type}`}>{token.content}</span>)}elseif(Array.isArray(token.content)){return<spankey={i}className={`token ${token.type}`}>{token.content.map(tokenToReactNode)}</span>}else{return(<spankey={i}className={`token ${token.type}`}>{tokenToReactNode(token.content,0)}</span>)}}exportconstCode:React.FC<CodeProps>=({language,children})=>{//In the state, we store the code and tokens for the code.
const[data,replaceToken]=useState<Array<string|Token>>([])useEffect(()=>{//We need to add languages since, by default only markup, CSS, clike, and javascript are available.
//I did not find a better way, like the one below, if you know - please submit an issue.
import(`prismjs/components/prism-${language}`).then(() => {//If language still not available skip tokenize part
consttokens: Array<string | Token> = Prism.languages[ language ]
? Prism.tokenize(children,Prism.languages[ language ])
: [];
//Save the result to the state.
replaceToken( tokens )
}, [children])});//If the array with tokens is empty, print the code from props, otherwise render our beauty.
return(<preclassName={`language-${language}`}>{data.length?data.map(tokenToReactNode):children}</pre>);}