Coding, Insights, and Digital Discoveries 👩🏻💻
From Stay-at-Home Mom to a Developer After 50
The prism-react-renderer library is a React-based syntax highlighter powered by Prism.js, a widely-used library for syntax highlighting. It enables rendering highlighted code snippets in React applications with customizable themes and styles. This makes it ideal for presenting and styling code snippets in React projects, such as this developer-oriented blog.
Customizable Themes: You can choose from ready-made themes or create your own to style the syntax highlighting to fit your needs.
Language Support: Make sure to specify the correct programming language for accurate syntax highlighting.
Token Styling: Different parts of the code (like keywords, functions, and strings) are styled individually for clarity.
Flexible Rendering: The library uses a "render prop" approach, giving you full control over how the highlighted code is displayed in your application.
The Highlight component is a wrapper provided by the prism-react-renderer library. It uses Prism.js under the hood to apply syntax highlighting to code.
Let’s look at an example of using prism-react-renderer through Sonner’s CodeBlock
component implementation:
import Highlight, { defaultProps } from 'prism-react-renderer';
export const CodeBlock = () => {
// some other code here...
return (
....
<Highlight {...defaultProps} theme={theme} code={children} language="jsx">
{({ className, tokens, getLineProps, getTokenProps }) => (
<motion.pre
className={styles.wrapper}
animate={{ height: bounds.height || initialHeight }}
transition={{ type: 'easeOut', duration: 0.2 }}
>
<div className={`${className} ${styles.root}`} ref={setRef}>
<div />
{tokens.map((line, i) => {
const { key: lineKey, ...rest } = getLineProps({ line, key: i });
return (
<div key={lineKey} {...rest}>
{line.map((token, key) => {
const { key: tokenKey, ...rest } = getTokenProps({ token, key });
return <span key={tokenKey} {...rest} />;
})}
</div>
);
})}
</div>
</motion.pre>
)}
</Highlight>
....
)
}
code: The code snippet to be highlighted. In this example, it’s passed as children.
language: The programming language of the code snippet (e.g., jsx, javascript, html, etc.). This ensures correct syntax highlighting.
theme: You can import or define themes for syntax highlighting. Each theme defines styles for specific token types (e.g., strings, keywords) and the overall appearance.
The Highlight
component uses the render function to allow customization of the highlighted code.
className: A CSS class corresponding to the chosen language and theme.
tokens: An array of arrays, where each sub-array represents a line of code, and each item within it represents a token (e.g., a keyword, variable, string, etc.).
getLineProps: A function that generates properties (e.g., keys and styling) for each line of code.
getTokenProps: A function that generates properties for each token within a line of code.
Each line of code is iterated over using tokens.map(...)
.
Each line is rendered as a div, styled with getLineProps
.
Each token within a line is rendered as a span, styled with getTokenProps.
import React from "react";
import Highlight, { Prism } from "prism-react-renderer";
import theme from "prism-react-renderer/themes/nightOwl";
const code = `
function greet(name) {
return 'Hello, ' + name;
}
`;
const CodeBlock = () => (
<Highlight Prism={Prism} theme={theme} language="javascript" code={code}>
{({ tokens, getLineProps, getTokenProps }) => (
<pre style={{ padding: "10px", borderRadius: "5px", fontFamily: "monospace" }}>
{tokens.map((line, i) => (
<div {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
);
export default CodeBlock;
const customTheme = {
plain: {
backgroundColor: "#282C34",
color: "#ffffff",
},
styles: [
{
types: ["keyword"],
style: { color: "rgb(198, 120, 221)" },
},
{
types: ["string"],
style: { color: "rgb(152, 195, 121)" },
},
],
};
import React, { useState } from "react";
import Highlight, { Prism } from "prism-react-renderer";
import theme from "prism-react-renderer/themes/nightOwl";
const CodeRenderer = () => {
const [language, setLanguage] = useState("javascript");
const code = `
function add(a, b) {
return a + b;
}
`;
return (
<div>
<select onChange={(e) => setLanguage(e.target.value)} value={language}>
<option value="javascript">JavaScript</option>
<option value="python">Python</option>
<option value="typescript">TypeScript</option>
</select>
<Highlight Prism={Prism} theme={theme} language={language} code={code}>
{({ tokens, getLineProps, getTokenProps }) => (
<pre style={{ padding: "10px", borderRadius: "5px", fontFamily: "monospace" }}>
{tokens.map((line, i) => (
<div {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</div>
);
};
export default CodeRenderer;
While Prism-react-renderer
is a lightweight and powerful choice for syntax highlighting in React and Next.js applications, several other libraries may better suit specific project requirements.
For example, react-syntax-highlighter
combines the strengths of Prism.js and Highlight.js, offering extensive language support and flexibility. This blog utilizes react-syntax-highlighter
for all code snippet sandboxes.
Another noteworthy option is shiki
, which uses VS Code’s syntax engine to deliver high-quality rendering and seamless integration with Next.js sites. For interactive scenarios where users need to write or edit code, CodeMirror
stands out as a feature-rich editor with built-in syntax highlighting capabilities.
These alternatives each bring their own unique strengths, offering us developers a variety of options to choose from for our syntax highlighting needs.