I have basic Prism.js functionality working with my Next.js site by doing the following things:
package.json
"dependencies": {
...
"next": "9.5.3",
"react": "16.13.1",
"typescript": "3.9.4",
"prismjs": "1.22.0"
},
"devDependencies": {
...
"@types/prismjs": "1.16.2"
}
pages/_app.tsx
...
import "prismjs/themes/prism-tomorrow.css";
...
pages/blog-article.tsx
...
import Prism from "prismjs";
import "prismjs/components/prism-hcl";
import "prismjs/plugins/line-highlight/prism-line-highlight";
...
export default function BlogArticle(){
useEffect(() => {
if (typeof window !== 'undefined') {
Prism.highlightAll();
}
}, []);
return <div>
<pre className="language-hcl" style={{marginTop: "1em"}}>
<code>{`xxx`}</code>
</pre>
</div>
}
That all works fine and source code is hightlighted properly - the problem comes when I try to use the line-highlight plugin for Prism.
When I add the data-line attribute to the HTML, as following.
pages/blog-article.tsx
...
<pre className="language-hcl" style={{marginTop: "1em"}} data-line={1}>
<code>{`xxx`}</code>
</pre>
...
I get the following error:
Warning: Text content did not match. Server: "xxx
" Client: "xxx"
So, if I'm understanding right: this is an error from Next.js, telling me that my server-rendered and client-rendered content are different?
Looking at the error message, it looks like the plugin is adding a newline at the end of the content, but only during the server-render, not the client-render.
Note that other Prism plugins seem to work; I tried out the line-numbers plugin and it didn't cause this problem.
Is this a bug with Prism.js, the line-highlight plugin or am I doing something wrong?
Is there a workaround I can do to get it going?
Initially mount the <pre> element without the data-line attribute.
In the useEffect, before calling Prism.highlightAll(), imperatively set the data-line attribute:
'use client'
import React, { useEffect, useRef } from 'react'
import Prism from 'prismjs'
import 'prismjs/themes/prism-tomorrow.css'
export default function Code({
code,
language,
lineNumbers,
}: {
code: string
language: string
lineNumbers?: string
}) {
const ref = useRef<HTMLPreElement>(null)
useEffect(() => {
lineNumbers && ref.current?.setAttribute('data-line', `${lineNumbers}`)
Prism.highlightAll()
}, [])
return (
<div className='Code line-numbers'>
<pre ref={ref} id='12345'>
<code className={`language-${language}`}>{code}</code>
</pre>
</div>
)
}
Note: One downside is that the page paints with unstyled code blocks. A potential "flash of unstyled content".
Original answer:
Same. The only workarounds I've found so far are to build a custom line highlighter with CSS, such as:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With