From 989bd36eeb6dd6c4b391900765847cdcf87484d9 Mon Sep 17 00:00:00 2001 From: Justice Almanzar Date: Mon, 19 Dec 2022 17:59:54 -0500 Subject: refactor: identifier escapes + "self" group (#339) Co-authored-by: Ven --- src/utils/patches.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils/types.ts | 4 +++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/utils/patches.ts (limited to 'src/utils') 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 . +*/ + +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(descriptor: TypedPropertyDescriptor, 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, 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: P & Record) { return p; @@ -26,7 +28,7 @@ export default function definePlugin

(p: P & Record string); + replace: string | ReplaceFn; predicate?(): boolean; } -- cgit