CoolFace
Apppublic

legends810/testingnew

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
CodeBlock.tsx83 linesDownload Raw Back to chat
1import { memo, useEffect, useState } from 'react';2import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki';3import { classNames } from '~/utils/classNames';4import { createScopedLogger } from '~/utils/logger';5 6import styles from './CodeBlock.module.scss';7 8const logger = createScopedLogger('CodeBlock');9 10interface CodeBlockProps {11  className?: string;12  code: string;13  language?: BundledLanguage | SpecialLanguage;14  theme?: 'light-plus' | 'dark-plus';15  disableCopy?: boolean;16}17 18export const CodeBlock = memo(19  ({ className, code, language = 'plaintext', theme = 'dark-plus', disableCopy = false }: CodeBlockProps) => {20    const [html, setHTML] = useState<string | undefined>(undefined);21    const [copied, setCopied] = useState(false);22 23    const copyToClipboard = () => {24      if (copied) {25        return;26      }27 28      navigator.clipboard.writeText(code);29 30      setCopied(true);31 32      setTimeout(() => {33        setCopied(false);34      }, 2000);35    };36 37    useEffect(() => {38      if (language && !isSpecialLang(language) && !(language in bundledLanguages)) {39        logger.warn(`Unsupported language '${language}'`);40      }41 42      logger.trace(`Language = ${language}`);43 44      const processCode = async () => {45        setHTML(await codeToHtml(code, { lang: language, theme }));46      };47 48      processCode();49    }, [code]);50 51    return (52      <div className={classNames('relative group text-left', className)}>53        <div54          className={classNames(55            styles.CopyButtonContainer,56            'bg-transparant absolute top-[10px] right-[10px] rounded-md z-10 text-lg flex items-center justify-center opacity-0 group-hover:opacity-100',57            {58              'rounded-l-0 opacity-100': copied,59            },60          )}61        >62          {!disableCopy && (63            <button64              className={classNames(65                'flex items-center bg-accent-500 p-[6px] justify-center before:bg-white before:rounded-l-md before:text-gray-500 before:border-r before:border-gray-300 rounded-md transition-theme',66                {67                  'before:opacity-0': !copied,68                  'before:opacity-100': copied,69                },70              )}71              title="Copy Code"72              onClick={() => copyToClipboard()}73            >74              <div className="i-ph:clipboard-text-duotone"></div>75            </button>76          )}77        </div>78        <div dangerouslySetInnerHTML={{ __html: html ?? '' }}></div>79      </div>80    );81  },82);83