Skip to content

Instantly share code, notes, and snippets.

@andrelandgraf
Created December 26, 2021 17:35
Show Gist options
  • Select an option

  • Save andrelandgraf/eebe0b710c189fef21dcd25bfe9a8da7 to your computer and use it in GitHub Desktop.

Select an option

Save andrelandgraf/eebe0b710c189fef21dcd25bfe9a8da7 to your computer and use it in GitHub Desktop.
PrismJS custom component
import​ ​type​ ​{​ ​FC,​ ​HTMLAttributes,​ ​ReactElement​ ​}​ ​from​ ​'react';
import​ ​{​ ​Children​ ​}​ ​from​ ​'react';
import​ ​invariant​ ​from​ ​'tiny-invariant';
import​ ​Highlight,​ ​{​ ​Language,​ ​defaultProps​ ​}​ ​from​ ​'prism-react-renderer';
import​ ​CopyClipboardButton​ ​from​ ​'../button/copyClipboardButton';
function​ ​getLanguageFromClassName(className​: ​string)​ ​{
​  ​const​ ​match​ ​=​ ​className.match(/language-(\w+)/);
​  ​return​ ​match​ ? ​match[1]​ : ​'';
}
function​ ​isLanguageSupported(lang​: ​string)​: ​lang​ is ​Language​ ​{
​  ​return​ ​(
​    ​lang​ ​===​ ​'markup'​ ​||
​    ​lang​ ​===​ ​'bash'​ ​||
​    ​lang​ ​===​ ​'clike'​ ​||
​    ​lang​ ​===​ ​'c'​ ​||
​    ​lang​ ​===​ ​'cpp'​ ​||
​    ​lang​ ​===​ ​'css'​ ​||
​    ​lang​ ​===​ ​'javascript'​ ​||
​    ​lang​ ​===​ ​'jsx'​ ​||
​    ​lang​ ​===​ ​'coffeescript'​ ​||
​    ​lang​ ​===​ ​'actionscript'​ ​||
​    ​lang​ ​===​ ​'css-extr'​ ​||
​    ​lang​ ​===​ ​'diff'​ ​||
​    ​lang​ ​===​ ​'git'​ ​||
​    ​lang​ ​===​ ​'go'​ ​||
​    ​lang​ ​===​ ​'graphql'​ ​||
​    ​lang​ ​===​ ​'handlebars'​ ​||
​    ​lang​ ​===​ ​'json'​ ​||
​    ​lang​ ​===​ ​'less'​ ​||
​    ​lang​ ​===​ ​'makefile'​ ​||
​    ​lang​ ​===​ ​'markdown'​ ​||
​    ​lang​ ​===​ ​'objectivec'​ ​||
​    ​lang​ ​===​ ​'ocaml'​ ​||
​    ​lang​ ​===​ ​'python'​ ​||
​    ​lang​ ​===​ ​'reason'​ ​||
​    ​lang​ ​===​ ​'sass'​ ​||
​    ​lang​ ​===​ ​'scss'​ ​||
​    ​lang​ ​===​ ​'sql'​ ​||
​    ​lang​ ​===​ ​'stylus'​ ​||
​    ​lang​ ​===​ ​'tsx'​ ​||
​    ​lang​ ​===​ ​'typescript'​ ​||
​    ​lang​ ​===​ ​'wasm'​ ​||
​    ​lang​ ​===​ ​'yaml'
​  ​);
}
const​ ​CodeBlock​: ​FC<HTMLAttributes<HTMLPreElement>>​ ​=​ ​({​ children ​})​ ​=>​ ​{
​  ​invariant(!!children,​ ​'children is required');
​  ​const​ ​childrenArray​ ​=​ ​Children.toArray(children);
​  ​const​ ​codeElement​ ​=​ ​childrenArray[0]​ ​as​ ​ReactElement;
​  ​const​ ​className​ ​=​ ​codeElement?.props?.className​ ​||​ ​'';
​  ​const​ ​lang​ ​=​ ​getLanguageFromClassName(className);
​  ​invariant(isLanguageSupported(lang),​ ​'lang is required');
​  ​const​ ​code​ ​=​ ​codeElement.props.children[0]​ ​||​ ​'';
​  ​const​ ​identifier​ ​=​ ​code;
​  ​return​ ​(
​    ​<div​ ​className="w-full my-5">
​      ​<Highlight​ ​{​...​defaultProps}​ ​code={code.trim()}​ ​language={lang​ ​||​ ​'bash'}>
​        ​{({​ className​,​ tokens​,​ getLineProps​,​ getTokenProps ​})​ ​=>​ ​(
​          ​<div​ ​className="p-4 rounded-md font-normal text-sm md:text-base bg-docs w-full">
​            ​<div​ ​className="flex justify-end px-4 pb-2 text-particular-dark">
​              ​<span​ ​className="mr-5 text-particular-light">{lang​ ​||​ ​'text'}</span>
​              ​<CopyClipboardButton​ ​title="Copy code"​ ​content={code}​ ​id={identifier}​ ​/>
​            ​</div>
​            ​<pre​ ​className={`pb-2 overflow-scroll ​${className}​`}​ ​style={{}}>
​              ​<code​ ​className={className}​ ​style={{}}>
​                ​{tokens.map((line,​ ​i)​ ​=>​ ​(
​                  ​<div​ ​key={i}​ ​{​...​getLineProps({​ line​,​ ​key​: ​i​ ​})}​ ​style={{}}>
​                    ​{line.map((token,​ ​key)​ ​=>​ ​(
​                      ​<span​ ​key={key}​ ​{​...​getTokenProps({​ token​,​ key ​})}​ ​style={{}}​ ​/>
​                    ​)​)​}
​                  ​</div>
​                ​)​)​}
​              ​</code>
​            ​</pre>
​          ​</div>
​        ​)​}
​      ​</Highlight>
​    ​</div>
​  ​)​;
};
@andrelandgraf
Copy link
Author

Be aware that the example code uses custom tailwind classes. You will need to update the background and text color classes.

@andrelandgraf
Copy link
Author

To style the code, pick a prismJS theme: https://github.com/PrismJS/prism-themes/tree/master/themes

@RafaelDavisH
Copy link

@andrelandgraf, I really appreciate you sharing this. Thank you 👍🏼

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment