mirror of
https://github.com/Equicord/Equicord.git
synced 2025-06-25 22:37:02 -04:00
Bundle dependencies with extensions for webstore rule compliance (#1740)
This commit is contained in:
parent
efb88a4df8
commit
41f5d71e38
46 changed files with 1633 additions and 73 deletions
74
src/plugins/shikiCodeblocks.desktop/api/languages.ts
Normal file
74
src/plugins/shikiCodeblocks.desktop/api/languages.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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 { ILanguageRegistration } from "@vap/shiki";
|
||||
|
||||
export const VPC_REPO = "Vap0r1ze/vapcord";
|
||||
export const VPC_REPO_COMMIT = "88a7032a59cca40da170926651b08201ea3b965a";
|
||||
export const vpcRepoAssets = `https://raw.githubusercontent.com/${VPC_REPO}/${VPC_REPO_COMMIT}/assets/shiki-codeblocks`;
|
||||
export const vpcRepoGrammar = (fileName: string) => `${vpcRepoAssets}/${fileName}`;
|
||||
export const vpcRepoLanguages = `${vpcRepoAssets}/languages.json`;
|
||||
|
||||
export interface Language {
|
||||
name: string;
|
||||
id: string;
|
||||
devicon?: string;
|
||||
grammarUrl: string,
|
||||
grammar?: ILanguageRegistration["grammar"];
|
||||
scopeName: string;
|
||||
aliases?: string[];
|
||||
custom?: boolean;
|
||||
}
|
||||
export interface LanguageJson {
|
||||
name: string;
|
||||
id: string;
|
||||
fileName: string;
|
||||
devicon?: string;
|
||||
scopeName: string;
|
||||
aliases?: string[];
|
||||
}
|
||||
|
||||
export const languages: Record<string, Language> = {};
|
||||
|
||||
export const loadLanguages = async () => {
|
||||
const langsJson: LanguageJson[] = await fetch(vpcRepoLanguages).then(res => res.json());
|
||||
const loadedLanguages = Object.fromEntries(
|
||||
langsJson.map(lang => [lang.id, {
|
||||
...lang,
|
||||
grammarUrl: vpcRepoGrammar(lang.fileName),
|
||||
}])
|
||||
);
|
||||
Object.assign(languages, loadedLanguages);
|
||||
};
|
||||
|
||||
export const getGrammar = (lang: Language): Promise<NonNullable<ILanguageRegistration["grammar"]>> => {
|
||||
if (lang.grammar) return Promise.resolve(lang.grammar);
|
||||
return fetch(lang.grammarUrl).then(res => res.json());
|
||||
};
|
||||
|
||||
const aliasCache = new Map<string, Language>();
|
||||
export function resolveLang(idOrAlias: string) {
|
||||
if (Object.prototype.hasOwnProperty.call(languages, idOrAlias)) return languages[idOrAlias];
|
||||
|
||||
const lang = Object.values(languages).find(lang => lang.aliases?.includes(idOrAlias));
|
||||
|
||||
if (!lang) return null;
|
||||
|
||||
aliasCache.set(idOrAlias, lang);
|
||||
return lang;
|
||||
}
|
118
src/plugins/shikiCodeblocks.desktop/api/shiki.ts
Normal file
118
src/plugins/shikiCodeblocks.desktop/api/shiki.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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 { shikiOnigasmSrc, shikiWorkerSrc } from "@utils/dependencies";
|
||||
import { WorkerClient } from "@vap/core/ipc";
|
||||
import type { IShikiTheme, IThemedToken } from "@vap/shiki";
|
||||
|
||||
import { dispatchTheme } from "../hooks/useTheme";
|
||||
import type { ShikiSpec } from "../types";
|
||||
import { getGrammar, languages, loadLanguages, resolveLang } from "./languages";
|
||||
import { themes } from "./themes";
|
||||
|
||||
const themeUrls = Object.values(themes);
|
||||
|
||||
let resolveClient: (client: WorkerClient<ShikiSpec>) => void;
|
||||
|
||||
export const shiki = {
|
||||
client: null as WorkerClient<ShikiSpec> | null,
|
||||
currentTheme: null as IShikiTheme | null,
|
||||
currentThemeUrl: null as string | null,
|
||||
timeoutMs: 10000,
|
||||
languages,
|
||||
themes,
|
||||
loadedThemes: new Set<string>(),
|
||||
loadedLangs: new Set<string>(),
|
||||
clientPromise: new Promise<WorkerClient<ShikiSpec>>(resolve => resolveClient = resolve),
|
||||
|
||||
init: async (initThemeUrl: string | undefined) => {
|
||||
/** https://stackoverflow.com/q/58098143 */
|
||||
const workerBlob = await fetch(shikiWorkerSrc).then(res => res.blob());
|
||||
|
||||
const client = shiki.client = new WorkerClient<ShikiSpec>(
|
||||
"shiki-client",
|
||||
"shiki-host",
|
||||
workerBlob,
|
||||
{ name: "ShikiWorker" },
|
||||
);
|
||||
await client.init();
|
||||
|
||||
const themeUrl = initThemeUrl || themeUrls[0];
|
||||
|
||||
await loadLanguages();
|
||||
await client.run("setOnigasm", { wasm: shikiOnigasmSrc });
|
||||
await client.run("setHighlighter", { theme: themeUrl, langs: [] });
|
||||
shiki.loadedThemes.add(themeUrl);
|
||||
await shiki._setTheme(themeUrl);
|
||||
resolveClient(client);
|
||||
},
|
||||
_setTheme: async (themeUrl: string) => {
|
||||
shiki.currentThemeUrl = themeUrl;
|
||||
const { themeData } = await shiki.client!.run("getTheme", { theme: themeUrl });
|
||||
shiki.currentTheme = JSON.parse(themeData);
|
||||
dispatchTheme({ id: themeUrl, theme: shiki.currentTheme });
|
||||
},
|
||||
loadTheme: async (themeUrl: string) => {
|
||||
const client = await shiki.clientPromise;
|
||||
if (shiki.loadedThemes.has(themeUrl)) return;
|
||||
|
||||
await client.run("loadTheme", { theme: themeUrl });
|
||||
|
||||
shiki.loadedThemes.add(themeUrl);
|
||||
},
|
||||
setTheme: async (themeUrl: string) => {
|
||||
await shiki.clientPromise;
|
||||
themeUrl ||= themeUrls[0];
|
||||
if (!shiki.loadedThemes.has(themeUrl)) await shiki.loadTheme(themeUrl);
|
||||
|
||||
await shiki._setTheme(themeUrl);
|
||||
},
|
||||
loadLang: async (langId: string) => {
|
||||
const client = await shiki.clientPromise;
|
||||
const lang = resolveLang(langId);
|
||||
|
||||
if (!lang || shiki.loadedLangs.has(lang.id)) return;
|
||||
|
||||
await client.run("loadLanguage", {
|
||||
lang: {
|
||||
...lang,
|
||||
grammar: lang.grammar ?? await getGrammar(lang),
|
||||
}
|
||||
});
|
||||
shiki.loadedLangs.add(lang.id);
|
||||
},
|
||||
tokenizeCode: async (code: string, langId: string): Promise<IThemedToken[][]> => {
|
||||
const client = await shiki.clientPromise;
|
||||
const lang = resolveLang(langId);
|
||||
if (!lang) return [];
|
||||
|
||||
if (!shiki.loadedLangs.has(lang.id)) await shiki.loadLang(lang.id);
|
||||
|
||||
return await client.run("codeToThemedTokens", {
|
||||
code,
|
||||
lang: langId,
|
||||
theme: shiki.currentThemeUrl ?? themeUrls[0],
|
||||
});
|
||||
},
|
||||
destroy() {
|
||||
shiki.currentTheme = null;
|
||||
shiki.currentThemeUrl = null;
|
||||
dispatchTheme({ id: null, theme: null });
|
||||
shiki.client?.destroy();
|
||||
}
|
||||
};
|
67
src/plugins/shikiCodeblocks.desktop/api/themes.ts
Normal file
67
src/plugins/shikiCodeblocks.desktop/api/themes.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 { IShikiTheme } from "@vap/shiki";
|
||||
|
||||
export const SHIKI_REPO = "shikijs/shiki";
|
||||
export const SHIKI_REPO_COMMIT = "0b28ad8ccfbf2615f2d9d38ea8255416b8ac3043";
|
||||
export const shikiRepoTheme = (name: string) => `https://raw.githubusercontent.com/${SHIKI_REPO}/${SHIKI_REPO_COMMIT}/packages/shiki/themes/${name}.json`;
|
||||
|
||||
export const themes = {
|
||||
// Default
|
||||
DarkPlus: shikiRepoTheme("dark-plus"),
|
||||
|
||||
// Dev Choices
|
||||
MaterialCandy: "https://raw.githubusercontent.com/millsp/material-candy/master/material-candy.json",
|
||||
|
||||
// More from Shiki repo
|
||||
DraculaSoft: shikiRepoTheme("dracula-soft"),
|
||||
Dracula: shikiRepoTheme("dracula"),
|
||||
GithubDarkDimmed: shikiRepoTheme("github-dark-dimmed"),
|
||||
GithubDark: shikiRepoTheme("github-dark"),
|
||||
GithubLight: shikiRepoTheme("github-light"),
|
||||
LightPlus: shikiRepoTheme("light-plus"),
|
||||
MaterialDarker: shikiRepoTheme("material-darker"),
|
||||
MaterialDefault: shikiRepoTheme("material-default"),
|
||||
MaterialLighter: shikiRepoTheme("material-lighter"),
|
||||
MaterialOcean: shikiRepoTheme("material-ocean"),
|
||||
MaterialPalenight: shikiRepoTheme("material-palenight"),
|
||||
MinDark: shikiRepoTheme("min-dark"),
|
||||
MinLight: shikiRepoTheme("min-light"),
|
||||
Monokai: shikiRepoTheme("monokai"),
|
||||
Nord: shikiRepoTheme("nord"),
|
||||
OneDarkPro: shikiRepoTheme("one-dark-pro"),
|
||||
Poimandres: shikiRepoTheme("poimandres"),
|
||||
RosePineDawn: shikiRepoTheme("rose-pine-dawn"),
|
||||
RosePineMoon: shikiRepoTheme("rose-pine-moon"),
|
||||
RosePine: shikiRepoTheme("rose-pine"),
|
||||
SlackDark: shikiRepoTheme("slack-dark"),
|
||||
SlackOchin: shikiRepoTheme("slack-ochin"),
|
||||
SolarizedDark: shikiRepoTheme("solarized-dark"),
|
||||
SolarizedLight: shikiRepoTheme("solarized-light"),
|
||||
VitesseDark: shikiRepoTheme("vitesse-dark"),
|
||||
VitesseLight: shikiRepoTheme("vitesse-light"),
|
||||
CssVariables: shikiRepoTheme("css-variables"),
|
||||
};
|
||||
|
||||
export const themeCache = new Map<string, IShikiTheme>();
|
||||
|
||||
export const getTheme = (url: string): Promise<IShikiTheme> => {
|
||||
if (themeCache.has(url)) return Promise.resolve(themeCache.get(url)!);
|
||||
return fetch(url).then(res => res.json());
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue