question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Syntax highlighting fails in React applications when using the new highlightAll() method

See original GitHub issue

Describe the issue I am trying to use highlightjs on a React project, which uses Next.js (although I don’t think the issue is related). I have added highlight.js using npm (v106.0) and loaded in a style sheet for a theme.

I have a simple function component set up like this:

import hljs from "highlight.js";
function Post(props) {
  useEffect(() => {
    hljs.highlightAll();
  }, []);

  return (
    <>
      <pre>
        <code> /* code blocks that i want to highlight */ </code>        
      </pre>
    </>
  );
}

This is using the new highlightAll() method call, but when the component is loaded the highlighting fails to take effect, and the <pre><code> block is left unstyled.

Expected behavior I would expect the code block to be styled and the language highlighted using highlightjs and the stylesheet I have selected.

Which language seems to have the issue? The error is not language specific, but all code blocks are failing to get instantiated and highlighted, and any styling applied what so ever.

What I think the issue is I think the issue is that the new highlightAll() is not compatible with React and the way that React shadow loads components. Line #772 makes a check if the dom has loaded, else it breaks out:

  function highlightAll() {
    // if we are called too early in the loading process
    if (!domLoaded) { wantsHighlight = true; return; }

    const blocks = document.querySelectorAll('pre code');
    blocks.forEach(highlightElement);
  }

The only place that domLoaded is set to true is in the boot() method:

  function boot() {
    domLoaded = true;
    // if a highlight was requested before DOM was loaded, do now
    if (wantsHighlight) highlightAll();
  }

The problem is that the only place boot() is called from is an event listener:

  if (typeof window !== 'undefined' && window.addEventListener) {
    window.addEventListener('DOMContentLoaded', boot, false);
  }

Since React will not cause the fire of the DomContentLoaded event when a user navigates to a new page, boot() is never called to set this variable to true, and when I am calling highlightAll() from my code it’s is exiting too early. The boot() is also not exposed to be able to call directly from my code.

Workaround For now, the solution is to call hljs.initHighlighting() (Line 747) since that method does not make the domLoaded check.

But, this method is marked as deprecated, so a fix needs to be put in place to allow this highlighter to continue to work with React applications. Perhaps allow a true parameter to be passed to force it to run the syntax highter code.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:32 (19 by maintainers)

github_iconTop GitHub Comments

1reaction
trm217commented, Mar 4, 2021

I don’t think it would. The problem is it’s not guaranteed that the DOMContentLoaded event is fired when HighLight.js is being loaded. So defacto domLoaded would always be false.

Taking the code from #3039, I would further adapt it to this, to make sure it works as expected even if the DOMContentLoaded event has been fired before Highlight.js was loaded.

I would adapt the code to remove the domLoaded variable altogether and only check the document readystate in the highlight all function.

/**
 * auto-highlights all pre>code elements on the page
 */
function highlightAll() {
  // if we are called too early in the loading process
  if (document.readyState === "loading") { wantsHighlight = true; return; }
  const blocks = document.querySelectorAll('pre code');
  blocks.forEach(highlightElement);
}
function boot() {
  // if a highlight was requested before DOM was loaded, do now
  if (wantsHighlight) highlightAll();
}

// make sure we are in the browser environment
if (typeof window !== 'undefined' && window.addEventListener) {
  window.addEventListener('DOMContentLoaded', boot, false);
}

I think this would work as expected and also simplify the changed code from #3039.

Would it be possible for me to propose my changes on the PR?

1reaction
joshgoebelcommented, Mar 3, 2021

Thanks for trying to help! Knowledgeable people on other ecosystems is always good to have.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The guide to syntax highlighting in React - LogRocket Blog
Appropriate syntax highlighting will enhance your code's readability. Syntax-highlighting libraries like Prism can be used with React.
Read more >
next.js - react-syntax-highlighter is not working with TailwindCSS
In my custom code component, I am using Syntax Highlighter to wrap by code content. <SyntaxHighlighter style={theme} language={props.node.
Read more >
CodeMirror (Source) Syntax Highlighting | CKEditor.com
Love this plugin and I use it everywhere... the only complaint I have is that apps that are using requireJS always error out...
Read more >
Syntax highlight with prismjs : r/vuejs - Reddit
Found that I should use Prism.highlightAll() while reading this article: https://derkinzi.de/prismjs-nuxtjs-static-pages/ , but still doesn't ...
Read more >
CodeMirror 5 User Manual
The distribution comes with a number of modes (see the mode/ directory), and it isn't hard to write new ones for other languages....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found