1- import { useState , type ReactNode } from 'react'
2- import invariant from 'tiny-invariant'
3- import type { Language } from 'prism-react-renderer'
4- import { Highlight , Prism } from 'prism-react-renderer'
1+ import * as React from 'react'
52import { FaCopy } from 'react-icons/fa'
6- import { svelteHighlighter } from '~/utils/svelteHighlighter'
7- // Add back additional language support after `prism-react` upgrade
8- ; ( typeof global !== 'undefined' ? global : window ) . Prism = Prism
9- // @ts -expect-error
10- import ( 'prismjs/components/prism-diff' )
11- // @ts -expect-error
12- import ( 'prismjs/components/prism-bash' )
13-
14- // @ts -ignore Alias markup as vue highlight
15- Prism . languages . vue = Prism . languages . markup
16-
17- // Enable svelte syntax highlighter
18- svelteHighlighter ( )
19-
20- function getLanguageFromClassName ( className : string ) {
21- const match = className . match ( / l a n g u a g e - ( \w + ) / )
22- return match ? match [ 1 ] : ''
23- }
3+ import invariant from 'tiny-invariant'
244
25- function isLanguageSupported ( lang : string ) : lang is Language {
26- return lang in Prism . languages
5+ function getLanguageFromChildren ( children : any ) : string | undefined {
6+ const language = children [ 0 ] ?. props ?. children
7+ return language ? language : undefined
278}
289
29- type Props = {
30- children : ReactNode
31- }
10+ export const CodeBlock = ( props : React . HTMLProps < HTMLPreElement > ) => {
11+ invariant ( ! ! props . children , 'children is required' )
12+ const lang = getLanguageFromChildren ( props . children )
13+ const [ copied , setCopied ] = React . useState ( false )
14+ const ref = React . useRef < HTMLPreElement > ( null )
3215
33- export const CodeBlock = ( { children } : Props ) => {
34- invariant ( ! ! children , 'children is required' )
35- const [ copied , setCopied ] = useState ( false )
36- const child = Array . isArray ( children ) ? children [ 0 ] : children
37- const className = child . props . className || ''
38- const userLang = getLanguageFromClassName ( className )
39- const lang = isLanguageSupported ( userLang ) ? userLang : 'bash'
40- const code = Array . isArray ( child . props . children )
41- ? child . props . children [ 0 ]
42- : child . props . children
4316 return (
4417 < div className = "w-full max-w-full relative" >
4518 < button
4619 className = "absolute right-1 top-3 z-10 p-2 group flex items-center"
4720 onClick = { ( ) => {
21+ navigator . clipboard . writeText ( ref . current ?. innerText || '' )
4822 setCopied ( true )
49- navigator . clipboard . writeText ( code . trim ( ) )
5023 setTimeout ( ( ) => setCopied ( false ) , 2000 )
5124 } }
5225 aria-label = "Copy code to clipboard"
@@ -57,34 +30,19 @@ export const CodeBlock = ({ children }: Props) => {
5730 < FaCopy className = "text-gray-500 group-hover:text-gray-100 dark:group-hover:text-gray-200 transition duration-200" />
5831 ) }
5932 </ button >
60- < div className = "relative not-prose" >
61- < div
62- className = "absolute bg-white text-sm z-10 border border-gray-300 px-2 rounded-md -top-3 right-2
63- dark:bg-gray-600 dark:border-0"
33+ < div className = "relative not-prose w-full max-w-full" >
34+ { lang ? (
35+ < div className = "absolute bg-white text-sm z-10 border border-gray-500/20 px-2 rounded-md -top-3 right-2 dark:bg-gray-600" >
36+ { lang }
37+ </ div >
38+ ) : null }
39+ < pre
40+ className = { `${ props . className } m-0 rounded-md w-full border border-gray-500/20 dark:border-gray-500/30` }
41+ style = { props . style }
42+ ref = { ref }
6443 >
65- { lang }
66- </ div >
67- < div className = "rounded-md font-normal w-full border border-gray-200 dark:border-0" >
68- < Highlight code = { code . trim ( ) } language = { lang } >
69- { ( { className, tokens, getLineProps, getTokenProps } ) => (
70- < pre className = { `overflow-scroll ${ className } ` } style = { { } } >
71- < code className = { className } style = { { } } >
72- { tokens . map ( ( line , i ) => (
73- < div key = { i } { ...getLineProps ( { line, key : i } ) } style = { { } } >
74- { line . map ( ( token , key ) => (
75- < span
76- key = { key }
77- { ...getTokenProps ( { token, key } ) }
78- style = { { } }
79- />
80- ) ) }
81- </ div >
82- ) ) }
83- </ code >
84- </ pre >
85- ) }
86- </ Highlight >
87- </ div >
44+ { props . children }
45+ </ pre >
8846 </ div >
8947 </ div >
9048 )
0 commit comments