aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx
diff options
context:
space:
mode:
authorV <vendicated@riseup.net>2023-09-19 04:07:24 +0200
committerV <vendicated@riseup.net>2023-09-19 04:11:27 +0200
commit41f5d71e38f785786656e111cf2ea1200e45886d (patch)
tree564a0300485de18a0b8d396118f09c6f756105ed /src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx
parentefb88a4df8037fc1394a9e2053c49e75d340f401 (diff)
downloadVencord-41f5d71e38f785786656e111cf2ea1200e45886d.tar.gz
Vencord-41f5d71e38f785786656e111cf2ea1200e45886d.tar.bz2
Vencord-41f5d71e38f785786656e111cf2ea1200e45886d.zip
Bundle dependencies with extensions for webstore rule compliance (#1740)
Diffstat (limited to 'src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx')
-rw-r--r--src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx b/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx
new file mode 100644
index 0000000..dd14019
--- /dev/null
+++ b/src/plugins/shikiCodeblocks.desktop/components/Highlighter.tsx
@@ -0,0 +1,126 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+*/
+
+import ErrorBoundary from "@components/ErrorBoundary";
+import { useAwaiter, 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;
+ tempSettings?: Record<string, any>;
+}
+
+export const createHighlighter = (props: HighlighterProps) => (
+ <pre className={cl("container")}>
+ <ErrorBoundary>
+ <Highlighter {...props} />
+ </ErrorBoundary>
+ </pre>
+);
+export const Highlighter = ({
+ lang,
+ content,
+ isPreview,
+ tempSettings,
+}: HighlighterProps) => {
+ const {
+ tryHljs,
+ useDevIcon,
+ bgOpacity,
+ } = useShikiSettings(["tryHljs", "useDevIcon", "bgOpacity"], tempSettings);
+ const { id: currentThemeId, theme: currentTheme } = useTheme();
+
+ const shikiLang = lang ? resolveLang(lang) : null;
+ const useHljs = shouldUseHljs({ lang, tryHljs });
+
+ const [rootRef, 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;
+
+ return (
+ <div
+ ref={rootRef}
+ className={cl("root", { plain: !langName, preview: isPreview })}
+ style={{
+ backgroundColor: useHljs
+ ? themeBase.backgroundColor
+ : `rgba(${hex2Rgb(themeBase.backgroundColor)
+ .concat(bgOpacity / 100)
+ .join(", ")})`,
+ color: themeBase.plainColor,
+ }}
+ >
+ <code>
+ <Header
+ langName={langName}
+ useDevIcon={useDevIcon}
+ shikiLang={shikiLang}
+ />
+ <Code
+ theme={themeBase}
+ useHljs={useHljs}
+ lang={lang}
+ content={content}
+ tokens={tokens}
+ />
+ {!isPreview && <ButtonRow
+ content={content}
+ theme={themeBase}
+ />}
+ </code>
+ </div>
+ );
+};
+