71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
/*
|
|
* Vencord, a Discord client mod
|
|
* Copyright (c) 2025 Vendicated and contributors
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
import { Devs } from "@utils/constants";
|
|
import { canonicalizeMatch } from "@utils/patches";
|
|
import definePlugin from "@utils/types";
|
|
import { Menu } from "@webpack/common";
|
|
|
|
// duplicate values have multiple branches with different types. Just include all to be safe
|
|
const nameMap = {
|
|
radio: "MenuRadioItem",
|
|
separator: "MenuSeparator",
|
|
checkbox: "MenuCheckboxItem",
|
|
groupstart: "MenuGroup",
|
|
|
|
control: "MenuControlItem",
|
|
compositecontrol: "MenuControlItem",
|
|
|
|
item: "MenuItem",
|
|
customitem: "MenuItem",
|
|
};
|
|
|
|
export default definePlugin({
|
|
name: "MenuItemDemanglerAPI",
|
|
description: "Demangles Discord's Menu Item module",
|
|
authors: [Devs.Ven],
|
|
required: true,
|
|
patches: [
|
|
{
|
|
find: "Menu API only allows Items",
|
|
replacement: {
|
|
match: /(?<=(\(\i\.type===(\i\.\i)\).{0,50}?navigable:.+Menu API).+?)}$/s,
|
|
replace: (_, m) => {
|
|
const registerCalls = [] as string[];
|
|
|
|
const typeCheckRe = canonicalizeMatch(/\(\i\.type===(\i\.\i)\)/g); // if (t.type === m.MenuItem)
|
|
const pushTypeRe = /type:"(\w+)"/g; // push({type:"item"})
|
|
|
|
let typeMatch: RegExpExecArray | null;
|
|
while ((typeMatch = typeCheckRe.exec(m)) !== null) {
|
|
const component = typeMatch[1];
|
|
// Set the starting index of the second regex to that of the first to start
|
|
// matching from after the if
|
|
pushTypeRe.lastIndex = typeCheckRe.lastIndex;
|
|
|
|
// extract the first type: "..."
|
|
const type = pushTypeRe.exec(m)?.[1];
|
|
if (type && type in nameMap) {
|
|
const name = nameMap[type];
|
|
registerCalls.push(`$self.registerMenuItem("${name}",${component})`);
|
|
}
|
|
}
|
|
|
|
if (registerCalls.length < 6) {
|
|
console.warn("[MenuItemDemanglerAPI] Expected to remap 6 items, only remapped", registerCalls.length);
|
|
}
|
|
|
|
return `${registerCalls.join(";")};}`;
|
|
},
|
|
},
|
|
},
|
|
],
|
|
|
|
registerMenuItem(name: string, component: any) {
|
|
Object.defineProperty(component, "name", { value: name });
|
|
Menu[name] = component;
|
|
}
|
|
});
|