Gasin
Gasin

Reputation: 51

How to load custom prismjs syntax file in react?

Question Desp: How could I highlight a custom syntax with prismjs in a react project?

I've created an extending syntax file (let's call it newlang) by following the guide.

And I know in prismjs there are three ways to highlight code:

First, I tried to require my custom syntax file in my app.

import 'utils/highlight/prism-newlang';

Then, in my highlighting component,

import Prism from 'prismjs';

function CodeHighlight({ value, language }) {
  const codeEle = useRef(null);

  useEffect(() => {
    Prism.highlightElement(codeEle.current, false);
  }, []);

  return (
    <pre className={`language-${language}`}>
      <code ref={codeEle} className={`language-${language}`}>
        {value}
      </code>
    </pre>
  );
}
import { highlight, languages } from 'prismjs/components/prism-core';

function CodeHighlight({ value, language }) {
  const codeNode = useRef(null);

  useEffect(() => {
    const code = codeNode.current.textContent;
    const highlightHTML = highlightCode(code, language);
    codeNode.current.innerHTML = highlightHTML;
  });

  return (
    <pre className={`language-${language}`}>
      <code ref={codeNode} className={`language-${language}`}>
        {value}
      </code>
    </pre>
  );
}

I wonder what's the problem of Method 1 & 2. (Will be the matter of the loading order of custom syntax file?)

Upvotes: 3

Views: 3160

Answers (1)

kirkbyo
kirkbyo

Reputation: 61

For those who run into this issue in the future, I was able to get the first method working. In my case, I was calling Prism.highlight in the handleChange which was calling the function before the DOM was even updated with the internalText. I now use the useEffect hook which is invoked after the DOM is rendered, the trick is you need to declare the internalText as a subscribed parameter.

I have attached my Typescript component.

Hope this helps.

import React, { useState, ChangeEvent, useRef, useEffect } from 'react'
import './prism.css'
import Prism from "prismjs";

export function CodeBlockTile() {
  const language = "javascript"

  const codeElement = useRef<HTMLElement | null>(null);
  const [internalText, setInternalText] = useState<string>("")

  const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
    setInternalText(event.target.value);
  };

  useEffect(() => {
    if (codeElement.current) {
      Prism.highlightElement(codeElement.current)
    }
  }, [internalText])


  return (
    <div>
      <textarea onChange={handleChange} value={internalText}>

      </textarea>
      <pre>
        <code ref={codeElement} className={`language-${language}`}>
          {internalText}
        </code>
      </pre>
    </div>
  )
}

Upvotes: 3

Related Questions