import { useEffect, useRef, useState } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; import { __ } from '@wordpress/i18n'; import { Theme } from 'shiki'; import { useTheme } from '../../hooks/useTheme'; import { Lang } from '../../types'; import { fontFamilyLong, maybeClamp } from '../../util/fonts'; type ThemePreviewProps = { id: string; theme: Theme; lang: Lang; code: string; fontSize: string; lineHeight: string; fontFamily: string; clampFonts: boolean; onClick: () => void; }; export const ThemePreview = ({ id, theme, lang, onClick, code, fontSize, lineHeight, fontFamily, clampFonts, }: ThemePreviewProps) => { const [inView, setInView] = useState(false); const { highlighter, error, loading } = useTheme({ theme, // If no code is written yet, show a classic Carmack snippet lang: code ? lang : 'c', ready: inView, }); const [codeRendered, setCode] = useState(''); const [backgroundColor, setBg] = useState('#ffffff'); const observer = useRef( new IntersectionObserver(([entry]) => { if (entry.isIntersecting) { setInView(true); observer.current.disconnect(); } }), ); const codeSnippet = ` float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the frack? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed return y; }`.trim(); useEffect(() => { if (!highlighter) return; if ((lang as string) === 'ansi' && code) { setCode(highlighter.ansiToHtml(code)); setBg(highlighter.getBackgroundColor()); return; } const hl = code ? highlighter.codeToHtml(decodeEntities(code), { lang }) : highlighter.codeToHtml(decodeEntities(codeSnippet), { lang: 'c', }); setCode(hl); setBg(highlighter.getBackgroundColor()); }, [highlighter, lang, code, codeSnippet]); return ( ); };