diff options
author | Justice Almanzar <superdash993@gmail.com> | 2022-12-19 17:59:54 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-19 22:59:54 +0000 |
commit | 989bd36eeb6dd6c4b391900765847cdcf87484d9 (patch) | |
tree | 86b15ce6804500b56f9f3c6b807d5fbb8aa6dad4 /src | |
parent | 4974c53f9cc3a3adccfa11f4af68ac4f190b0fc8 (diff) | |
download | Vencord-989bd36eeb6dd6c4b391900765847cdcf87484d9.tar.gz Vencord-989bd36eeb6dd6c4b391900765847cdcf87484d9.tar.bz2 Vencord-989bd36eeb6dd6c4b391900765847cdcf87484d9.zip |
refactor: identifier escapes + "self" group (#339)
Co-authored-by: Ven <vendicated@riseup.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/components/PatchHelper.tsx | 23 | ||||
-rw-r--r-- | src/plugins/shikiCodeblocks/index.ts | 6 | ||||
-rw-r--r-- | src/plugins/shikiCodeblocks/shiki.css (renamed from src/plugins/shikiCodeblocks/style.css) | 9 | ||||
-rw-r--r-- | src/utils/patches.ts | 55 | ||||
-rw-r--r-- | src/utils/types.ts | 4 | ||||
-rw-r--r-- | src/webpack/patchWebpack.ts | 12 |
6 files changed, 92 insertions, 17 deletions
diff --git a/src/components/PatchHelper.tsx b/src/components/PatchHelper.tsx index 22c2b4d..cb60980 100644 --- a/src/components/PatchHelper.tsx +++ b/src/components/PatchHelper.tsx @@ -18,6 +18,7 @@ import { debounce } from "@utils/debounce"; import { makeCodeblock } from "@utils/misc"; +import { canonicalizeMatch, canonicalizeReplace, ReplaceFn } from "@utils/patches"; import { search } from "@webpack"; import { Button, Clipboard, Forms, Margins, Parser, React, Switch, Text, TextInput } from "@webpack/common"; @@ -41,20 +42,29 @@ const findCandidates = debounce(function ({ find, setModule, setError }) { setModule([keys[0], candidates[keys[0]]]); }); -function ReplacementComponent({ module, match, replacement, setReplacementError }) { +interface ReplacementComponentProps { + module: [id: number, factory: Function]; + match: string | RegExp; + replacement: string | ReplaceFn; + setReplacementError(error: any): void; +} + +function ReplacementComponent({ module, match, replacement, setReplacementError }: ReplacementComponentProps) { const [id, fact] = module; const [compileResult, setCompileResult] = React.useState<[boolean, string]>(); const [patchedCode, matchResult, diff] = React.useMemo(() => { const src: string = fact.toString().replaceAll("\n", ""); + const canonicalMatch = canonicalizeMatch(match); try { - var patched = src.replace(match, replacement); + const canonicalReplace = canonicalizeReplace(replacement, "YourPlugin"); + var patched = src.replace(canonicalMatch, canonicalReplace as string); setReplacementError(void 0); } catch (e) { setReplacementError((e as Error).message); return ["", [], []]; } - const m = src.match(match); + const m = src.match(canonicalMatch); return [patched, m, makeDiff(src, patched, m)]; }, [id, match, replacement]); @@ -179,9 +189,10 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { {Object.entries({ "$$": "Insert a $", "$&": "Insert the entire match", - "$`": "Insert the substring before the match", + "$`\u200b": "Insert the substring before the match", "$'": "Insert the substring after the match", - "$n": "Insert the nth capturing group ($1, $2...)" + "$n": "Insert the nth capturing group ($1, $2...)", + "$self": "Insert the plugin instance", }).map(([placeholder, desc]) => ( <Forms.FormText key={placeholder}> {Parser.parse("`" + placeholder + "`")}: {desc} @@ -206,7 +217,7 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { function PatchHelper() { const [find, setFind] = React.useState<string>(""); const [match, setMatch] = React.useState<string>(""); - const [replacement, setReplacement] = React.useState<string | Function>(""); + const [replacement, setReplacement] = React.useState<string | ReplaceFn>(""); const [replacementError, setReplacementError] = React.useState<string>(); diff --git a/src/plugins/shikiCodeblocks/index.ts b/src/plugins/shikiCodeblocks/index.ts index fd6b04b..58e0048 100644 --- a/src/plugins/shikiCodeblocks/index.ts +++ b/src/plugins/shikiCodeblocks/index.ts @@ -22,7 +22,7 @@ import { wordsFromPascal, wordsToTitle } from "@utils/text"; import definePlugin, { OptionType } from "@utils/types"; import previewExampleText from "~fileContent/previewExample.tsx"; -import cssText from "~fileContent/style.css"; +import cssText from "~fileContent/shiki.css"; import { Settings } from "../../Vencord"; import { shiki } from "./api/shiki"; @@ -44,8 +44,8 @@ export default definePlugin({ { find: "codeBlock:{react:function", replacement: { - match: /codeBlock:\{react:function\((.),(.),(.)\)\{/, - replace: "$&return Vencord.Plugins.plugins.ShikiCodeblocks.renderHighlighter($1,$2,$3);", + match: /codeBlock:\{react:function\((\i),(\i),(\i)\)\{/, + replace: "$&return $self.renderHighlighter($1,$2,$3);", }, }, ], diff --git a/src/plugins/shikiCodeblocks/style.css b/src/plugins/shikiCodeblocks/shiki.css index b246db4..b871d99 100644 --- a/src/plugins/shikiCodeblocks/style.css +++ b/src/plugins/shikiCodeblocks/shiki.css @@ -1,10 +1,13 @@ -.shiki-root { - border-radius: 4px; - +.shiki-container { + border: 4px; /* fallback background */ background-color: var(--background-secondary); } +.shiki-root { + border-radius: 4px; +} + .shiki-root code { display: block; overflow-x: auto; 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; } diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 8f11b63..7b318b2 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -18,6 +18,8 @@ import { WEBPACK_CHUNK } from "@utils/constants"; import Logger from "@utils/Logger"; +import { canonicalizeReplacement } from "@utils/patches"; +import { PatchReplacement } from "@utils/types"; import { _initWebpack } from "."; @@ -135,15 +137,17 @@ function patchPush() { if (code.includes(patch.find)) { patchedBy.add(patch.plugin); - // @ts-ignore we change all patch.replacement to array in plugins/index - for (const replacement of patch.replacement) { + // we change all patch.replacement to array in plugins/index + for (const replacement of patch.replacement as PatchReplacement[]) { if (replacement.predicate && !replacement.predicate()) continue; const lastMod = mod; const lastCode = code; + canonicalizeReplacement(replacement, patch.plugin); + try { - const newCode = code.replace(replacement.match, replacement.replace); - if (newCode === code && !replacement.noWarn) { + const newCode = code.replace(replacement.match, replacement.replace as string); + if (newCode === code && !patch.noWarn) { logger.warn(`Patch by ${patch.plugin} had no effect (Module id is ${id}): ${replacement.match}`); if (IS_DEV) { logger.debug("Function Source:\n", code); |