I've been trying to generate a snippet of code on my website on a rendered text editor using react-syntax-highlighter. I've spent a while using this plugin and love it, however I've e across an issue I can't find an answer to. I want to change some of the colors of the generated code but cannot find any other way to do this other than using their default selection of themes. They allow you to apply styles to the background and the code but not the spans that hold the colors, is there any simple way to create and apply a custom theme, or to simply target the specific classes and change their colors?
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { atomDark } from "react-syntax-highlighter/dist/esm/styles/prism";
const CodeDisplay = ({ active }) => {
const templateString = `
const NewObject = New Shop(
console.log('shop');
)
`
return (
<>
<SyntaxHighlighter
language="jsx"
style={atomDark}
wrapLongLines
customStyle={{
backgroundColor: "transparent",
opacity: "1",
marginTop: "-2rem",
}}
codeTagProps={{
style: {
color: "white",
},
}}>
{templateString}
</SyntaxHighlighter>
</>
);
};
Output Screenshot
I've been trying to generate a snippet of code on my website on a rendered text editor using react-syntax-highlighter. I've spent a while using this plugin and love it, however I've e across an issue I can't find an answer to. I want to change some of the colors of the generated code but cannot find any other way to do this other than using their default selection of themes. They allow you to apply styles to the background and the code but not the spans that hold the colors, is there any simple way to create and apply a custom theme, or to simply target the specific classes and change their colors?
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { atomDark } from "react-syntax-highlighter/dist/esm/styles/prism";
const CodeDisplay = ({ active }) => {
const templateString = `
const NewObject = New Shop(
console.log('shop');
)
`
return (
<>
<SyntaxHighlighter
language="jsx"
style={atomDark}
wrapLongLines
customStyle={{
backgroundColor: "transparent",
opacity: "1",
marginTop: "-2rem",
}}
codeTagProps={{
style: {
color: "white",
},
}}>
{templateString}
</SyntaxHighlighter>
</>
);
};
Output Screenshot
Share Improve this question edited Feb 6, 2021 at 17:37 frost2709 asked Feb 6, 2021 at 17:01 frost2709frost2709 3851 gold badge5 silver badges14 bronze badges 2- Please add an example of the input and the expected output, to highlight what you want to achieve when changing colors. – Paul-Beyond Commented Feb 6, 2021 at 17:15
- 1 thanks @PdC - I've updated the question to show the input and output, the issue I'm facing is the colors in the output are from a default theme whereas I'd prefer to use my own theme colors and cannot figure out how to simply do this. – frost2709 Commented Feb 6, 2021 at 17:38
2 Answers
Reset to default 6I'm thinking that the best way to do this would just be to copy the theme and edit it.
The theme you're importing in your code is available at https://github./react-syntax-highlighter/react-syntax-highlighter/blob/master/src/styles/prism/atom-dark.js
You could download that file, add it to your source control and modify it all you want. Then just import your edited file wherever you use SyntaxHighlighter
.
If you make a lot of changes that you think are really cool, consider making a PR to the library so other people can use it as well!
The way that worked best for me in order to style the code similar to the dark+
theme in Visual Studio Code is to specify useInlineStyles={false}
to prevent react-syntax-highlighter (RSH) to add inline css style information to each span element produced. RSH however will specify a certain class name to that object that furthermore allows you to define your own CSS styles.
My configuration i.e. looks like this:
...
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
import ts from 'react-syntax-highlighter/dist/esm/languages/hljs/typescript';
import './rsh-style.css';
SyntaxHighlighter.registerLanguage('typescript', ts);
const calcMinLineNumberWidth = (code: string): string | null => {
const lines = [...code].reduce((prev, current) => prev + (current === '\n' ? 1 : 0), 1);
if (lines > 99) {
return "50px";
} else if (lines > 9) {
return "40px";
} else {
return null;
}
}
const highlightLine = (lineNumber: number, markLines: number[], color: string = "#FFDB81"):
React.HTMLProps<HTMLElement> => {
// only works when showLineNumbers and wrapLines are both enabled
const style: React.CSSProperties = { display: "block", width: "fit-content" };
if (markLines.includes(lineNumber)) {
style.backgroundColor = color;
}
return { style };
}
const CodeList: FunctionComponent = (props: CodeListProps) => {
const minWidth = calcMinLineNumberWidth(code);
return (
...
<div className="container">
<div className="divider" />
<SyntaxHighlighter language="typescript" style={style}
className={"syntax-highlighter"}
useInlineStyles={false}
showLineNumbers={true}
lineNumberStyle={{minWidth: minWidth}}
wrapLines={true}
lineProps={(line: number) => highlightLine(line, props.highlightLines, props.highlightColor)}
>
{code}
</SyntaxHighlighter>
</div>
...
)
}
this will produce an output like visible in the snippet added at the bottom of this post.
The lexer react-syntax-highlighter
uses has clearly some issues as in case of multi-line ments a new line start indicated by a new line number is annotated here with a class="hljs-ment"
when it clearly shouldn't. Also, there are multiple things that aren't recognized and therefore tagged properly and thus a code highlighting like in your editor of choice might not be doable.
With a CSS file also added as snippet below that basically defines the colors VSCode uses for certain key elements I obtain an output like in the right part of the picture below. For parison purposes I also included the original styling of dark+
style of VSCode for reference purposes. Some changes like the more greish-purple background are on purpose as it fits the theme of the page better.
As further can be seen, the output RSH returns is not quite able to format the code like VSCode does though most of the colors should be similar to the one VSCode uses in that theme, at least a color picker did return these color values.
Line 19-21 in the image to the right showcases the line highlighting via the respective function used in the lineProps
property, just in case if anybody wonders why they have a different color.
.container {
display: inline-block;
position: relative;
left: 0px;
width: 760px;
}
.container > .syntax-highlighter {
width:100%;
height: 100%;
color: #D4D4D4;
/*background-color: #030003;*/
background-color: rgb(40, 44, 52) !important;
font-family: Droid Sans Mono;
letter-spacing: 1.5px;
border-radius: 15px;
padding-top: 10px;
padding-bottom: 10px;
margin-left: -10px;
font-weight: 500;
}
.container > .syntax-highlighter .language-typescript > span:hover {
background-color: rgba(224, 224, 173, 0.2) !important;
}
.container > .syntax-highlighter .language-typescript .linenumber {
color: rgb(126, 120, 135) !important;
margin-left: 15px;
margin-right: 15px;
background-color: transparent;
border-right: 2px solid rgb(126, 120, 135);
}
.container > .syntax-highlighter .language-typescript .linenumber:hover {
color: rgb(213, 214, 133) !important;
margin-left: 15px;
margin-right: 15px;
}
.container > .syntax-highlighter .language-typescript .hljs-ment {
color: #48a454;
font-weight: 450;
}
.container > .syntax-highlighter .language-typescript .hljs-keyword {
color: #d86fc0;
}
.container > .syntax-highlighter .language-typescript .hljs-function {
color: #4098d7;
}
.container > .syntax-highlighter .language-typescript .hljs-title {
color: #d8e2a9;
}
.container >.syntax-highlighter .language-typescript .hljs-tag {
color: #d4d4d4;
}
.container >.syntax-highlighter .language-typescript .hljs-name {
color: #4098d7;
}
.container >.syntax-highlighter .language-typescript .hljs-attr {
color: #86ddff;
}
.container >.syntax-highlighter .language-typescript .hljs-string {
color: #dc8a77;
}
.container >.syntax-highlighter .language-typescript .hljs-built_in {
color: #00d5b0;
}
<div class="container"><pre class="hljs syntax-highlighter"><code class="language-typescript" style="white-space: pre;"><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">1</span><span class="hljs-ment">/**
</span></span><span style="display: block;" class="hljs-ment"><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">2</span> * Some multi-line ment
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">3</span><span class="hljs-ment"> */</span><span class="">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">4</span><span class=""></span><span class="hljs-keyword">import</span><span class=""> React </span><span class="hljs-keyword">from</span><span class=""> </span><span class="hljs-string">'react'</span><span class="">;
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">5</span><span class=""></span><span class="hljs-keyword">import</span><span class=""> logo </span><span class="hljs-keyword">from</span><span class=""> </span><span class="hljs-string">'./logo.svg'</span><span class="">;
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">6</span><span class=""></span><span class="hljs-keyword">import</span><span class=""> </span><span class="hljs-string">'./App.css'</span><span class="">;
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">7</span>
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; padding-right: 1em; text-align: right; user-select: none; min-width: 40px;">8</span><span class=""></span><span class="hljs-keyword">interface</span><span class=""> SomeInterface {
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">9</span><span class=""> </span><span class="hljs-attr">items</span><span class="">: </span><span class="hljs-built_in">string</span><span class="">[];
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">10</span>}
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">11</span>
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">12</span><span class=""></span><span class="hljs-keyword">type</span><span class=""> SomeType = {
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">13</span><span class=""> </span><span class="hljs-attr">items</span><span class="">: </span><span class="hljs-built_in">string</span><span class="">[];
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">14</span>}
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">15</span>
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">16</span><span class=""></span><span class="hljs-ment">// line ment</span><span class="">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">17</span><span class=""></span><span class="hljs-function hljs-keyword">function</span><span class="hljs-function"> </span><span class="hljs-function hljs-title">App</span><span class="hljs-function">(</span><span class="hljs-function">) </span><span class="">{
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">18</span><span class=""> </span><span class="hljs-keyword">return</span><span class=""> (
</span></span><span style="display: block; background-color: rgb(57, 61, 65);" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">19</span><span class=""> </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">div</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">className</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"App"</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block; background-color: rgb(57, 61, 65);" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">20</span><span class="xml"> </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">header</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">className</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"App-header"</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block; background-color: rgb(57, 61, 65);" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">21</span><span class="xml"> </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">img</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">src</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">{logo}</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">className</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"App-logo"</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">alt</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"logo"</span><span class="xml hljs-tag"> /></span><span class="xml">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">22</span><span class="xml"> </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">p</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">23</span><span class="xml"> Edit </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">code</span><span class="xml hljs-tag">></span><span class="xml">src/App.tsx</span><span class="xml hljs-tag"></</span><span class="xml hljs-tag hljs-name">code</span><span class="xml hljs-tag">></span><span class="xml"> and save to reload.
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">24</span><span class="xml"> </span><span class="xml hljs-tag"></</span><span class="xml hljs-tag hljs-name">p</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">25</span><span class="xml"> </span><span class="xml hljs-tag"><</span><span class="xml hljs-tag hljs-name">a</span><span class="xml hljs-tag">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">26</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">className</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"App-link"</span><span class="xml hljs-tag">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">27</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">href</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"https://reactjs"</span><span class="xml hljs-tag">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">28</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">target</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"_blank"</span><span class="xml hljs-tag">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">29</span><span class="xml hljs-tag"> </span><span class="xml hljs-tag hljs-attr">rel</span><span class="xml hljs-tag">=</span><span class="xml hljs-tag hljs-string">"noopener noreferrer"</span><span class="xml hljs-tag">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">30</span><span class="xml hljs-tag"> ></span><span class="xml">
</span></span><span style="display: block;" class="xml"><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">31</span> Learn React
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">32</span><span class="xml"> </span><span class="xml hljs-tag"></</span><span class="xml hljs-tag hljs-name">a</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">33</span><span class="xml"> </span><span class="xml hljs-tag"></</span><span class="xml hljs-tag hljs-name">header</span><span class="xml hljs-tag">></span><span class="xml">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">34</span><span class="xml"> </span><span class="xml hljs-tag"></</span><span class="xml hljs-tag hljs-name">div</span><span class="xml hljs-tag">></span><span class="">
</span></span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">35</span> );
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">36</span>}
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">37</span>
</span><span style="display: block;" class=""><span class="ment linenumber react-syntax-highlighter-line-number" style="display: inline-block; min-width: 40px; padding-right: 1em; text-align: right; user-select: none;">38</span><span class=""></span><span class="hljs-keyword">export</span><span class=""> </span><span class="hljs-keyword">default</span><span class=""> App;</span></span></code></pre></div>