/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2022 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import ErrorBoundary from "@components/ErrorBoundary"; import { useAwaiter } from "@utils/misc"; import { useIntersection } from "@utils/react"; import { hljs, React } from "@webpack/common"; import { resolveLang } from "../api/languages"; import { shiki } from "../api/shiki"; import { useShikiSettings } from "../hooks/useShikiSettings"; import { useTheme } from "../hooks/useTheme"; import { hex2Rgb } from "../utils/color"; import { cl, shouldUseHljs } from "../utils/misc"; import { ButtonRow } from "./ButtonRow"; import { Code } from "./Code"; import { Header } from "./Header"; export interface ThemeBase { plainColor: string; accentBgColor: string; accentFgColor: string; backgroundColor: string; } export interface HighlighterProps { lang?: string; content: string; isPreview: boolean; } export const createHighlighter = (props: HighlighterProps) => ( ); export const Highlighter = ({ lang, content, isPreview, }: HighlighterProps) => { const { tryHljs, useDevIcon, bgOpacity } = useShikiSettings(["tryHljs", "useDevIcon", "bgOpacity"]); const { id: currentThemeId, theme: currentTheme } = useTheme(); const shikiLang = lang ? resolveLang(lang) : null; const useHljs = shouldUseHljs({ lang, tryHljs }); const [preRef, isIntersecting] = useIntersection(true); const [tokens] = useAwaiter(async () => { if (!shikiLang || useHljs || !isIntersecting) return null; return await shiki.tokenizeCode(content, lang!); }, { fallbackValue: null, deps: [lang, content, currentThemeId, isIntersecting], }); const themeBase: ThemeBase = { plainColor: currentTheme?.fg || "var(--text-normal)", accentBgColor: currentTheme?.colors?.["statusBar.background"] || (useHljs ? "#7289da" : "#007BC8"), accentFgColor: currentTheme?.colors?.["statusBar.foreground"] || "#FFF", backgroundColor: currentTheme?.colors?.["editor.background"] || "var(--background-secondary)", }; let langName; if (lang) langName = useHljs ? hljs?.getLanguage?.(lang)?.name : shikiLang?.name; const preClasses = [cl("root")]; if (!langName) preClasses.push(cl("plain")); if (isPreview) preClasses.push(cl("preview")); return (
            
                
{!isPreview && }
); };