aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/patches.ts55
-rw-r--r--src/utils/types.ts4
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;
}