FormidableLabs / prism-react-renderer

🖌️ Renders highlighted Prism output to React (+ theming & vendored Prism)
MIT License
1.89k stars 152 forks source link

Add support for diff-highlight #90

Open rrousselGit opened 4 years ago

rrousselGit commented 4 years ago

Related to https://github.com/FormidableLabs/prism-react-renderer/issues/2 and https://github.com/facebook/docusaurus/issues/3318

Prism comes with a useful plugin: diff-highlight for combining syntax highlighting and diff highlighting.

Since prism-react-renderer does not support plugins, it would be interesting to reimplement this plugin directly in prism-react-renderer. This can increase quite significantly the readability of diffs.

kud commented 3 years ago

Interested! I'd like to have diff + javascript for instance.

maqi1520 commented 2 years ago

this is my code

const isDiff = language.startsWith('diff-')

  let highlightStyle = []

  let code = children
  if (isDiff) {
    code = []
    language = language.substr(5)
    highlightStyle = children.split('\n').map((line) => {
      if (line.startsWith('+')) {
        code.push(line.substr(1))
        return 'inserted'
      }
      if (line.startsWith('-')) {
        code.push(line.substr(1))
        return 'deleted'
      }
      code.push(line)
    })
    code = code.join('\n')
  }

https://github.com/maqi1520/mdx-editor/blob/main/src/components/MDX/CodeBlock.jsx

image

thefat32 commented 7 months ago

You can check my solution for this docusaurus issue facebook/docusaurus#3318 on a possible apporach to remiplement prism plugins for prism-react-renderer using hooks "before-tokenize" and "after-tokenize"

nabak9 commented 7 months ago

You don't need to rewrite the plugins to make this work. I got my plugins to work with a few lines of code, I hope this will help everyone that has been waiting for so long:

I assign the tokens to a ref and then run the 'complete' hook that calls the plugins registered to prism in useLayoutEffect as I need a reference to my code element.

const codeBlock: string = 'hello world';
const editorLanguage:string = 'my-custom-lang';
const tokensRef = React.useRef<Token[][]>([]);

useLayoutEffect(() => {
        Prism.hooks.run('complete', {
            code: codeBlock,
            grammar: Prism.languages[editorLanguage],
            language: editorLanguage,
            tokens: tokensRef.current,
            element: codeRef.current,
        });
}, [tokensRef.current]);

return  (
<Highlight code={codeBlock} language={editorLanguage} prism={Prism} theme={talkwalkerTheme}>
  {({ className, style, tokens, getLineProps, getTokenProps }) => {
      tokensRef.current = tokens;

      return (
          <pre className="prism-highlighting" aria-hidden="true">
              <code
                  className={`${className} match-braces rainbow-braces no-keep-markup`} // class names used by plugins
                  ref={codeRef}>
                  {tokens.map((line, i) => line.map((token, key) => <span key={key} {...getTokenProps({ token })} />))}
              </code>
          </pre>
      );
  }}
</Highlight>
);