diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/patches.ts | 55 | ||||
-rw-r--r-- | src/utils/types.ts | 4 |
2 files changed, 58 insertions, 1 deletions
diff --git a/src/utils/patches.ts b/src/utils/patches.ts new file mode 100644 index 0000000..8ecd68e --- /dev/null +++ b/src/utils/patches.ts @@ -0,0 +1,55 @@ +/* + * 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 { PatchReplacement } from "./types"; + +export type ReplaceFn = (match: string, ...groups: string[]) => string; + +export function canonicalizeMatch(match: RegExp | string) { + if (typeof match === "string") return match; + const canonSource = match.source + .replaceAll("\\i", "[A-Za-z_$][\\w$]*"); + return new RegExp(canonSource, match.flags); +} + +export function canonicalizeReplace(replace: string | ReplaceFn, pluginName: string) { + if (typeof replace === "function") return replace; + return replace.replaceAll("$self", `Vencord.Plugins.plugins.${pluginName}`); +} + +export function canonicalizeDescriptor<T>(descriptor: TypedPropertyDescriptor<T>, canonicalize: (value: T) => T) { + if (descriptor.get) { + const original = descriptor.get; + descriptor.get = function () { + return canonicalize(original.call(this)); + }; + } else if (descriptor.value) { + descriptor.value = canonicalize(descriptor.value); + } + return descriptor; +} + +export function canonicalizeReplacement(replacement: Pick<PatchReplacement, "match" | "replace">, plugin: string) { + const descriptors = Object.getOwnPropertyDescriptors(replacement); + descriptors.match = canonicalizeDescriptor(descriptors.match, canonicalizeMatch); + descriptors.replace = canonicalizeDescriptor( + descriptors.replace, + replace => canonicalizeReplace(replace, plugin), + ); + Object.defineProperties(replacement, descriptors); +} diff --git a/src/utils/types.ts b/src/utils/types.ts index fd8f02b..d3083fc 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -19,6 +19,8 @@ import { Command } from "@api/Commands"; import { Promisable } from "type-fest"; +import type { ReplaceFn } from "./patches"; + // exists to export default definePlugin({...}) export default function definePlugin<P extends PluginDef>(p: P & Record<string, any>) { return p; @@ -26,7 +28,7 @@ export default function definePlugin<P extends PluginDef>(p: P & Record<string, export interface PatchReplacement { match: string | RegExp; - replace: string | ((match: string, ...groups: string[]) => string); + replace: string | ReplaceFn; predicate?(): boolean; } |