diff options
author | Justice Almanzar <superdash993@gmail.com> | 2022-12-02 10:43:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-02 16:43:37 +0100 |
commit | 41dddc9eee6f19fb5055545811aff1e282790a9c (patch) | |
tree | bf38148e87242e169adfa39919aa636a9d0551ce /src/plugins/shikiCodeblocks/index.ts | |
parent | 4760af7f0ee275caa1eee440f4945032057d2b56 (diff) | |
download | Vencord-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.ts | 154 |
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, + }); + }, +}); |