Metadata
-
Date
-
Last update
-
Tagged
-
Older post
-
Newer post
Syntax highlighting codeblocks with theme-ui
A recent blog post by Prince about how to use syntax highlighting in a site that uses mdx made me want to add syntax highlighting for codeblocks using the same method.
I was using @theme-ui/prism
, which did the same thing, making me postpone implementing it for myself.
His followup post about highlighting lines convinced me. I was going to follow that guide, and combine it with the goodness of @theme-ui/prism
.
I wanted to keep using the awesome presets from @theme-ui/prism
to use colors from popular syntax highlighting themes such as night owl, dracula, night owl light, and many more.
Using the @theme-ui/prism
component
Even though I’m going to remove the @theme-ui/prism
component immediately after this, the official docs for @theme-ui/prism
have an excellent explanation for how to replace the codeblocks (triple backticks) in markdown/mdx with a custom component.
Replacing the component
The Prism
component that those docs told us to use? I replaced it with my own.
I created a component called CodeBlock.js
, and used that instead.
It uses the same internals as @theme-ui/prism
. Only this time, I can tweak them and add cool stuff like line highlighting.
Those internals are powered by a package called prism-react-renderer
.
To start, this file will look almost identical to the Prism
component from @theme-ui/prism
.
Adding line highlighting
The tutorial I mentioned earlier applies a CSS-class to the lines that should be highlighted.
In theme-ui, a variant can be used to style those lines.
Getting relevant data into the component
After the three backtick followed by the language, optional key/value pairs may be passed.
Those keys will be passed into the CodeBlock
component as props.
eg. for ```javascript puppies=cute
The CodeBlock
component will have a prop called puppies
with a value of "cute"
.
I used this to pass a range of line numbers into the component under the hl
prop (short for highlight-lines).
From that point, I followed Prince’s guide again. Inside the component, I created a function that returns a boolean signalling if a line should be highlighted.
The logic to create that function lives outside of the component.
Theme-ui variant
I added some CSS to the theme-ui file to the styles.CodeBlock.highlightLine
variant and applied it to the lines that should be highlighted.
A wrapping element
A small caveat is that the background for highlighted lines doesn’t extend all the way if the user has to (horizontally) scroll the codeblock.
This can be solved by wrapping the entire component in another element, and applying some CSS.
At this point I also moved the nightOwlLight
preset to the styles.CodeBlock
variant inside the theme-ui file.
The corresponding variant in the theme-ui file:
Adding title support
The steps to add a section above the codeblock that can hold a title are very similar to the line highlighting ones.
Getting relevant data into the component
Pass a prop called title
into the CodeBlock
component.
eg. ```javascript title=CodeBlock.js
will make the title
prop have a value of "Codeblock.js"
Own element
Above the existing outer <div>
, create another one and conditionally render the title
.
Theme-ui variant
A theme-ui variant, styles.CodeBlock.title
makes sure the element can be styled via the theme-ui file.