aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/shikiCodeblocks/index.ts
diff options
context:
space:
mode:
authorJustice Almanzar <superdash993@gmail.com>2022-12-02 10:43:37 -0500
committerGitHub <noreply@github.com>2022-12-02 16:43:37 +0100
commit41dddc9eee6f19fb5055545811aff1e282790a9c (patch)
treebf38148e87242e169adfa39919aa636a9d0551ce /src/plugins/shikiCodeblocks/index.ts
parent4760af7f0ee275caa1eee440f4945032057d2b56 (diff)
downloadVencord-41dddc9eee6f19fb5055545811aff1e282790a9c.tar.gz
Vencord-41dddc9eee6f19fb5055545811aff1e282790a9c.tar.bz2
Vencord-41dddc9eee6f19fb5055545811aff1e282790a9c.zip
feat(plugin): ShikiCodeblocks (#267)
Co-authored-by: ArjixWasTaken <53124886+ArjixWasTaken@users.noreply.github.com> Co-authored-by: Ven <vendicated@riseup.net>
Diffstat (limited to 'src/plugins/shikiCodeblocks/index.ts')
-rw-r--r--src/plugins/shikiCodeblocks/index.ts154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/plugins/shikiCodeblocks/index.ts b/src/plugins/shikiCodeblocks/index.ts
new file mode 100644
index 0000000..a8be92a
--- /dev/null
+++ b/src/plugins/shikiCodeblocks/index.ts
@@ -0,0 +1,154 @@
+/*
+ * 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 { Devs } from "@utils/constants";
+import { parseUrl } from "@utils/misc";
+import { wordsFromPascal, wordsToTitle } from "@utils/text";
+import definePlugin, { OptionType } from "@utils/types";
+
+import cssText from "~fileContent/style.css";
+
+import { Settings } from "../../Vencord";
+import { shiki } from "./api/shiki";
+import { themes } from "./api/themes";
+import { createHighlighter } from "./components/Highlighter";
+import { DeviconSetting, HljsSetting, ShikiSettings, StyleSheets } from "./types";
+import { clearStyles, removeStyle, setStyle } from "./utils/createStyle";
+
+const themeNames = Object.keys(themes);
+const devIconCss = "@import url('https://cdn.jsdelivr.net/gh/devicons/devicon@v2.10.1/devicon.min.css');";
+
+const getSettings = () => Settings.plugins.ShikiCodeblocks as ShikiSettings;
+
+export default definePlugin({
+ name: "ShikiCodeblocks",
+ description: "Brings vscode-style codeblocks into Discord, powered by Shiki",
+ authors: [Devs.Vap],
+ patches: [
+ {
+ find: "codeBlock:{react:function",
+ replacement: {
+ match: /codeBlock:\{react:function\((.),(.),(.)\)\{/,
+ replace: "$&return Vencord.Plugins.plugins.ShikiCodeblocks.renderHighlighter($1,$2,$3);",
+ },
+ },
+ ],
+ start: async () => {
+ setStyle(cssText, StyleSheets.Main);
+ if (getSettings().useDevIcon !== DeviconSetting.Disabled)
+ setStyle(devIconCss, StyleSheets.DevIcons);
+
+ await shiki.init(getSettings().customTheme || getSettings().theme);
+ },
+ stop: () => {
+ shiki.destroy();
+ clearStyles();
+ },
+ options: {
+ theme: {
+ type: OptionType.SELECT,
+ description: "Default themes",
+ options: themeNames.map(themeName => ({
+ label: wordsToTitle(wordsFromPascal(themeName)),
+ value: themes[themeName],
+ default: themes[themeName] === themes.DarkPlus,
+ })),
+ disabled: () => !!getSettings().customTheme,
+ onChange: shiki.setTheme,
+ },
+ customTheme: {
+ type: OptionType.STRING,
+ description: "A link to a custom vscode theme",
+ placeholder: themes.MaterialCandy,
+ isValid: value => {
+ if (!value) return true;
+ const url = parseUrl(value);
+ if (!url) return "Must be a valid URL";
+
+ if (!url.pathname.endsWith(".json")) return "Must be a json file";
+
+ return true;
+ },
+ onChange: value => shiki.setTheme(value || getSettings().theme),
+ },
+ tryHljs: {
+ type: OptionType.SELECT,
+ description: "Use the more lightweight default Discord highlighter and theme.",
+ options: [
+ {
+ label: "Never",
+ value: HljsSetting.Never,
+ },
+ {
+ label: "Prefer Shiki instead of Highlight.js",
+ value: HljsSetting.Secondary,
+ default: true,
+ },
+ {
+ label: "Prefer Highlight.js instead of Shiki",
+ value: HljsSetting.Primary,
+ },
+ {
+ label: "Always",
+ value: HljsSetting.Always,
+ },
+ ],
+ },
+ useDevIcon: {
+ type: OptionType.SELECT,
+ description: "How to show language icons on codeblocks",
+ options: [
+ {
+ label: "Disabled",
+ value: DeviconSetting.Disabled,
+ },
+ {
+ label: "Colorless",
+ value: DeviconSetting.Greyscale,
+ default: true,
+ },
+ {
+ label: "Colored",
+ value: DeviconSetting.Color,
+ },
+ ],
+ onChange: (newValue: DeviconSetting) => {
+ if (newValue === DeviconSetting.Disabled) removeStyle(StyleSheets.DevIcons);
+ else setStyle(devIconCss, StyleSheets.DevIcons);
+ },
+ },
+ bgOpacity: {
+ type: OptionType.SLIDER,
+ description: "Background opacity",
+ markers: [0, 20, 40, 60, 80, 100],
+ default: 100,
+ stickToMarkers: false,
+ },
+ },
+
+ // exports
+ shiki,
+ createHighlighter,
+ renderHighlighter: ({ lang, content }: { lang: string; content: string; }) => {
+ return createHighlighter({
+ lang,
+ content,
+ isPreview: false,
+ });
+ },
+});