From 5aa19bbf49839c31f4a15fa96994c3fb2ce22e31 Mon Sep 17 00:00:00 2001 From: Elvyra <88881326+EdVraz@users.noreply.github.com> Date: Sat, 20 Apr 2024 11:18:03 +0200 Subject: [PATCH 001/134] fix ValidUser (#2369) --- src/plugins/validUser/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index b0c77cb46..dafa7bc98 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -111,7 +111,7 @@ function MentionWrapper({ data, UserMention, RoleMention, parse, props }: Mentio export default definePlugin({ name: "ValidUser", - description: "Fix mentions for unknown users showing up as '<@343383572805058560>' (hover over a mention to fix it)", + description: "Fix mentions for unknown users showing up as '@unknown-user' (hover over a mention to fix it)", authors: [Devs.Ven], tags: ["MentionCacheFix"], @@ -119,7 +119,7 @@ export default definePlugin({ find: 'className:"mention"', replacement: { // mention = { react: function (data, parse, props) { if (data.userId == null) return RoleMention() else return UserMention() - match: /react(?=\(\i,\i,\i\).{0,50}return null==\i\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, + match: /react(?=\(\i,\i,\i\).{0,50}return null==.{0,70}\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, // react: (...args) => OurWrapper(RoleMention, UserMention, ...args), originalReact: theirFunc replace: "react:(...args)=>$self.renderMention($1,$2,...args),originalReact" } From 87ef214810e561cd37649d3b4eec4dbbbd7e018d Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 20 Apr 2024 11:29:15 +0200 Subject: [PATCH 002/134] RoleColorEverywhere: fix chat mentions --- src/plugins/roleColorEverywhere/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 6d53906f8..71c291fef 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -50,7 +50,7 @@ export default definePlugin({ patches: [ // Chat Mentions { - find: "CLYDE_AI_MENTION_COLOR:null,", + find: 'location:"UserMention', replacement: [ { match: /user:(\i),channel:(\i).{0,400}?"@"\.concat\(.+?\)/, From 74df53e7c8d81abf77ca67ab7432a5a8bfc8e4f6 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 20 Apr 2024 11:37:22 +0200 Subject: [PATCH 003/134] ValidUser: fix not working for @unknown-user mentions --- src/plugins/validUser/index.tsx | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index dafa7bc98..d3decd941 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -115,15 +115,24 @@ export default definePlugin({ authors: [Devs.Ven], tags: ["MentionCacheFix"], - patches: [{ - find: 'className:"mention"', - replacement: { - // mention = { react: function (data, parse, props) { if (data.userId == null) return RoleMention() else return UserMention() - match: /react(?=\(\i,\i,\i\).{0,50}return null==.{0,70}\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, - // react: (...args) => OurWrapper(RoleMention, UserMention, ...args), originalReact: theirFunc - replace: "react:(...args)=>$self.renderMention($1,$2,...args),originalReact" + patches: [ + { + find: 'className:"mention"', + replacement: { + // mention = { react: function (data, parse, props) { if (data.userId == null) return RoleMention() else return UserMention() + match: /react(?=\(\i,\i,\i\).{0,50}return null==.{0,70}\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, + // react: (...args) => OurWrapper(RoleMention, UserMention, ...args), originalReact: theirFunc + replace: "react:(...args)=>$self.renderMention($1,$2,...args),originalReact" + } + }, + { + find: "unknownUserMentionPlaceholder:", + replacement: { + match: /unknownUserMentionPlaceholder:/, + replace: "$&false&&" + } } - }], + ], renderMention(RoleMention, UserMention, data, parse, props) { return ( From 0bebc85b0dc08c9345210499dc9d24dd14c64ac0 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 20 Apr 2024 11:50:28 +0200 Subject: [PATCH 004/134] fix FriendsSince on canary --- src/plugins/friendsSince/index.tsx | 16 +++++++++++++--- src/webpack/webpack.ts | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index dd37137a4..69d8e739d 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -7,12 +7,22 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; +import { makeLazy } from "@utils/lazy"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { filters, find, findByPropsLazy, handleModuleNotFound } from "@webpack"; import { React, RelationshipStore } from "@webpack/common"; const { Heading, Text } = findByPropsLazy("Heading", "Text"); -const container = findByPropsLazy("memberSinceContainer"); +// Workaround for module differing on stable & canary +// FIXME: remove once merged into stable +const getMemberSinceContainer = makeLazy(() => { + for (const name of ["memberSinceWrapper", "memberSinceContainer"]) { + const mod = find(filters.byProps(name), { isIndirect: true }); + if (mod) return mod[name]; + } + handleModuleNotFound("findByProps", "memberSinceWrapper/memberSinceContainer"); + return ""; +}); const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate"); const clydeMoreInfo = findByPropsLazy("clydeMoreInfo"); const locale = findByPropsLazy("getLocale"); @@ -49,7 +59,7 @@ export default definePlugin({ Friends Since -
+
{!!getCurrentChannel()?.guild_id && ( {title} + {(savedSession == null || savedSession.isNew) && ( +
+ NEW +
+ )} + + + ); + }, { noop: true }), + + renderTimestamp: ErrorBoundary.wrap(({ session, timeLabel }: { session: Session, timeLabel: string; }) => { + return ( + + {props => ( + + {timeLabel} + + )} + + ); + }, { noop: true }), + + renderIcon: ErrorBoundary.wrap(({ session, DeviceIcon }: { session: Session, DeviceIcon: React.ComponentType; }) => { + const PlatformIcon = GetPlatformIcon(session.client_info.platform); + + return ( + + +
+ } + lowerBadgeWidth={20} + lowerBadgeHeight={20} + > +
+ +
+ + ); + }, { noop: true }), + + async checkNewSessions() { + const data = await RestAPI.get({ + url: "/auth/sessions" + }); + + for (const session of data.body.user_sessions) { + if (savedSessionsCache.has(session.id_hash)) continue; + + savedSessionsCache.set(session.id_hash, { name: "", isNew: true }); + showNotification({ + title: "BetterSessions", + body: `New session:\n${session.client_info.os} · ${session.client_info.platform} · ${session.client_info.location}`, + permanent: true, + onClick: () => UserSettingsModal.open("Sessions") + }); + } + + saveSessionsToDataStore(); + }, + + flux: { + USER_SETTINGS_ACCOUNT_RESET_AND_CLOSE_FORM() { + const lastFetchedHashes: string[] = AuthSessionsStore.getSessions().map((session: SessionInfo["session"]) => session.id_hash); + + // Add new sessions to cache + lastFetchedHashes.forEach(idHash => { + if (!savedSessionsCache.has(idHash)) savedSessionsCache.set(idHash, { name: "", isNew: false }); + }); + + // Delete removed sessions from cache + if (lastFetchedHashes.length > 0) { + savedSessionsCache.forEach((_, idHash) => { + if (!lastFetchedHashes.includes(idHash)) savedSessionsCache.delete(idHash); + }); + } + + // Dismiss the "NEW" badge of all sessions. + // Since the only way for a session to be marked as "NEW" is going to the Devices tab, + // closing the settings means they've been viewed and are no longer considered new. + savedSessionsCache.forEach(data => { + data.isNew = false; + }); + saveSessionsToDataStore(); + } + }, + + async start() { + await fetchNamesFromDataStore(); + + this.checkNewSessions(); + if (settings.store.backgroundCheck) { + this.checkInterval = setInterval(this.checkNewSessions, settings.store.checkInterval * 60 * 1000); + } + }, + + stop() { + clearInterval(this.checkInterval); + } +}); diff --git a/src/plugins/betterSessions/types.ts b/src/plugins/betterSessions/types.ts new file mode 100644 index 000000000..9026d5313 --- /dev/null +++ b/src/plugins/betterSessions/types.ts @@ -0,0 +1,32 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 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 . +*/ + +export interface SessionInfo { + session: { + id_hash: string; + approx_last_used_time: Date; + client_info: { + os: string; + platform: string; + location: string; + }; + }, + current?: boolean; +} + +export type Session = SessionInfo["session"]; diff --git a/src/plugins/betterSessions/utils.ts b/src/plugins/betterSessions/utils.ts new file mode 100644 index 000000000..3015dc47c --- /dev/null +++ b/src/plugins/betterSessions/utils.ts @@ -0,0 +1,90 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 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 { DataStore } from "@api/index"; +import { UserStore } from "@webpack/common"; + +import { ChromeIcon, DiscordIcon, EdgeIcon, FirefoxIcon, IEIcon, MobileIcon, OperaIcon, SafariIcon, UnknownIcon } from "./components/icons"; +import { SessionInfo } from "./types"; + +const getDataKey = () => `BetterSessions_savedSessions_${UserStore.getCurrentUser().id}`; + +export const savedSessionsCache: Map = new Map(); + +export function getDefaultName(clientInfo: SessionInfo["session"]["client_info"]) { + return `${clientInfo.os} · ${clientInfo.platform}`; +} + +export function saveSessionsToDataStore() { + return DataStore.set(getDataKey(), savedSessionsCache); +} + +export async function fetchNamesFromDataStore() { + const savedSessions = await DataStore.get>(getDataKey()) || new Map(); + savedSessions.forEach((data, idHash) => { + savedSessionsCache.set(idHash, data); + }); +} + +export function GetOsColor(os: string) { + switch (os) { + case "Windows Mobile": + case "Windows": + return "#55a6ef"; // Light blue + case "Linux": + return "#cdcd31"; // Yellow + case "Android": + return "#7bc958"; // Green + case "Mac OS X": + case "iOS": + return ""; // Default to white/black (theme-dependent) + default: + return "#f3799a"; // Pink + } +} + +export function GetPlatformIcon(platform: string) { + switch (platform) { + case "Discord Android": + case "Discord iOS": + case "Discord Client": + return DiscordIcon; + case "Android Chrome": + case "Chrome iOS": + case "Chrome": + return ChromeIcon; + case "Edge": + return EdgeIcon; + case "Firefox": + return FirefoxIcon; + case "Internet Explorer": + return IEIcon; + case "Opera Mini": + case "Opera": + return OperaIcon; + case "Mobile Safari": + case "Safari": + return SafariIcon; + case "BlackBerry": + case "Facebook Mobile": + case "Android Mobile": + return MobileIcon; + default: + return UnknownIcon; + } +} From 7f0e7dd02bd241f9999da77642189868164b6e54 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 24 Apr 2024 05:23:50 +0200 Subject: [PATCH 008/134] fix FakeProfileThemes --- src/plugins/fakeProfileThemes/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index c61437269..a1b629d10 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -92,8 +92,9 @@ export default definePlugin({ match: /(?<=getUserProfile\(\i\){return )(\i\[\i\])/, replace: "$self.colorDecodeHook($1)" } - }, { - find: ".USER_SETTINGS_PROFILE_THEME_ACCENT", + }, + { + find: ".USER_SETTINGS_RESET_PROFILE_THEME", replacement: { match: /RESET_PROFILE_THEME}\)(?<=color:(\i),.{0,500}?color:(\i),.{0,500}?)/, replace: "$&,$self.addCopy3y3Button({primary:$1,accent:$2})" From d5f70070efed3a6c2f481ffe4abce3c5ad45e57b Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 24 Apr 2024 05:27:14 +0200 Subject: [PATCH 009/134] fix badges --- src/plugins/_api/badges.tsx | 2 +- src/plugins/betterSessions/index.tsx | 4 ++-- src/utils/constants.ts | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/plugins/_api/badges.tsx b/src/plugins/_api/badges.tsx index 16b244a19..6b1a79cd5 100644 --- a/src/plugins/_api/badges.tsx +++ b/src/plugins/_api/badges.tsx @@ -65,7 +65,7 @@ export default definePlugin({ patches: [ /* Patch the badge list component on user profiles */ { - find: "Messages.PROFILE_USER_BADGES,role:", + find: 'id:"premium",', replacement: [ { match: /&&(\i)\.push\(\{id:"premium".+?\}\);/, diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index bb79870d2..539508f80 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -21,14 +21,14 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findExportedComponentLazy } from "@webpack"; +import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; import { React, RestAPI, Tooltip } from "@webpack/common"; import { RenameButton } from "./components/RenameButton"; import { Session, SessionInfo } from "./types"; import { fetchNamesFromDataStore, getDefaultName, GetOsColor, GetPlatformIcon, savedSessionsCache, saveSessionsToDataStore } from "./utils"; -const AuthSessionsStore = findByPropsLazy("getSessions"); +const AuthSessionsStore = findStoreLazy("AuthSessionsStore"); const UserSettingsModal = findByPropsLazy("saveAccountChanges", "open"); const TimestampClasses = findByPropsLazy("timestampTooltip", "blockquoteContainer"); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 3098e29d0..917fabf43 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -437,6 +437,14 @@ export const Devs = /* #__PURE__*/ Object.freeze({ Byron: { name: "byeoon", id: 1167275288036655133n + }, + Kaitlyn: { + name: "kaitlyn", + id: 306158896630988801n + }, + PolisanTheEasyNick: { + name: "Oleh Polisan", + id: 242305263313485825n } } satisfies Record); From 6a69701b54107cbb696615949ba0594a097bf010 Mon Sep 17 00:00:00 2001 From: My-Name-Is-Jeff <37018278+My-Name-Is-Jeff@users.noreply.github.com> Date: Tue, 23 Apr 2024 23:30:23 -0400 Subject: [PATCH 010/134] fix ValidUser (#2381) --- src/plugins/validUser/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index d3decd941..2fce693e8 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -120,7 +120,7 @@ export default definePlugin({ find: 'className:"mention"', replacement: { // mention = { react: function (data, parse, props) { if (data.userId == null) return RoleMention() else return UserMention() - match: /react(?=\(\i,\i,\i\).{0,50}return null==.{0,70}\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, + match: /react(?=\(\i,\i,\i\).{0,100}return null==.{0,70}\?\(0,\i\.jsx\)\((\i\.\i),.+?jsx\)\((\i\.\i),\{className:"mention")/, // react: (...args) => OurWrapper(RoleMention, UserMention, ...args), originalReact: theirFunc replace: "react:(...args)=>$self.renderMention($1,$2,...args),originalReact" } From d55205c55ad9ffa82fa03837ebb4eae623d28705 Mon Sep 17 00:00:00 2001 From: dolfies Date: Tue, 23 Apr 2024 23:41:53 -0400 Subject: [PATCH 011/134] feat(plugin): ImplicitRelationships (#947) Co-authored-by: Angelos Bouklis <53124886+ArjixWasTaken@users.noreply.github.com> Co-authored-by: V --- src/plugins/implicitRelationships/README.md | 7 + src/plugins/implicitRelationships/index.ts | 182 ++++++++++++++++++++ src/plugins/sortFriendRequests/index.tsx | 2 +- 3 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/plugins/implicitRelationships/README.md create mode 100644 src/plugins/implicitRelationships/index.ts diff --git a/src/plugins/implicitRelationships/README.md b/src/plugins/implicitRelationships/README.md new file mode 100644 index 000000000..a76e298f7 --- /dev/null +++ b/src/plugins/implicitRelationships/README.md @@ -0,0 +1,7 @@ +# ImplicitRelationships + +Shows your implicit relationships in the Friends tab. + +Implicit relationships on Discord are people with whom you've frecently interacted and share a mutual server; even though Discord thinks you should be friends with them, you haven't added them as friends. + +![](https://camo.githubusercontent.com/6927161ee0c933f7ef6d61f243cca3e6ea4c8db9d1becd8cbf73c45e1bd0d127/68747470733a2f2f692e646f6c66692e65732f7055447859464662674d2e706e673f6b65793d736e3950343936416c32444c7072) diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts new file mode 100644 index 000000000..9ae9fb512 --- /dev/null +++ b/src/plugins/implicitRelationships/index.ts @@ -0,0 +1,182 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 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 { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; +import { findByProps, findStoreLazy } from "@webpack"; +import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common"; +import { Settings } from "Vencord"; + +const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore"); + +interface UserAffinity { + user_id: string; + affinity: number; +} + +export default definePlugin({ + name: "ImplicitRelationships", + description: "Shows your implicit relationships in the Friends tab.", + authors: [Devs.Dolfies], + patches: [ + // Counts header + { + find: ".FRIENDS_ALL_HEADER", + replacement: { + match: /toString\(\)\}\);case (\i\.\i)\.BLOCKED/, + replace: 'toString()});case $1.IMPLICIT:return "Implicit — "+arguments[1];case $1.BLOCKED' + }, + }, + // No friends page + { + find: "FriendsEmptyState: Invalid empty state", + replacement: { + match: /case (\i\.\i)\.ONLINE:(?=return (\i)\.SECTION_ONLINE)/, + replace: "case $1.ONLINE:case $1.IMPLICIT:" + }, + }, + // Sections header + { + find: ".FRIENDS_SECTION_ONLINE", + replacement: { + match: /(\(0,\i\.jsx\)\(\i\.TabBar\.Item,\{id:\i\.\i)\.BLOCKED,className:([^\s]+?)\.item,children:\i\.\i\.Messages\.BLOCKED\}\)/, + replace: "$1.IMPLICIT,className:$2.item,children:\"Implicit\"}),$&" + }, + }, + // Sections content + { + find: '"FriendsStore"', + replacement: { + match: /(?<=case (\i\.\i)\.BLOCKED:return (\i)\.type===\i\.\i\.BLOCKED)/, + replace: ";case $1.IMPLICIT:return $2.type===5" + }, + }, + // Piggyback relationship fetch + { + find: ".fetchRelationships()", + replacement: { + match: /(\i\.\i)\.fetchRelationships\(\)/, + // This relationship fetch is actually completely useless, but whatevs + replace: "$1.fetchRelationships(),$self.fetchImplicitRelationships()" + }, + }, + // Modify sort -- thanks megu for the patch (from sortFriendRequests) + { + find: "getRelationshipCounts(){", + replacement: { + predicate: () => Settings.plugins.ImplicitRelationships.sortByAffinity, + match: /\.sortBy\(\i=>\i\.comparator\)/, + replace: "$&.sortBy((row) => $self.sortList(row))" + } + }, + + // Add support for the nonce parameter to Discord's shitcode + { + find: ".REQUEST_GUILD_MEMBERS", + replacement: { + match: /\.send\(8,{/, + replace: "$&nonce:arguments[1].nonce," + } + }, + { + find: "GUILD_MEMBERS_REQUEST:", + replacement: { + match: /presences:!!(\i)\.presences/, + replace: "$&,nonce:$1.nonce" + }, + }, + { + find: ".not_found", + replacement: { + match: /notFound:(\i)\.not_found/, + replace: "$&,nonce:$1.nonce" + }, + } + ], + settings: definePluginSettings( + { + sortByAffinity: { + type: OptionType.BOOLEAN, + default: true, + description: "Whether to sort implicit relationships by their affinity to you.", + restartNeeded: true + }, + } + ), + + sortList(row: any) { + return row.type === 5 + ? -UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0 + : row.comparator; + }, + + async fetchImplicitRelationships() { + // Implicit relationships are defined as users that you: + // 1. Have an affinity for + // 2. Do not have a relationship with // TODO: Check how this works with pending/blocked relationships + // 3. Have a mutual guild with + const userAffinities: Set = UserAffinitiesStore.getUserAffinitiesUserIds(); + const nonFriendAffinities = Array.from(userAffinities).filter( + id => !RelationshipStore.getRelationshipType(id) + ); + + // I would love to just check user cache here (falling back to the gateway of course) + // However, users in user cache may just be there because they share a DM or group DM with you + // So there's no guarantee that a user being in user cache means they have a mutual with you + // To get around this, we request users we have DMs with, and ignore them below if we don't get them back + const dmUserIds = new Set( + Object.values(ChannelStore.getSortedPrivateChannels()).flatMap(c => c.recipients) + ); + const toRequest = nonFriendAffinities.filter(id => !UserStore.getUser(id) || dmUserIds.has(id)); + const allGuildIds = Object.keys(GuildStore.getGuilds()); + const sentNonce = SnowflakeUtils.fromTimestamp(Date.now()); + let count = allGuildIds.length * Math.ceil(toRequest.length / 100); + + // OP 8 Request Guild Members allows 100 user IDs at a time + const ignore = new Set(toRequest); + const relationships = RelationshipStore.getRelationships(); + const callback = ({ nonce, members }) => { + if (nonce !== sentNonce) return; + members.forEach(member => { + ignore.delete(member.user.id); + }); + + nonFriendAffinities.map(id => UserStore.getUser(id)).filter(user => user && !ignore.has(user.id)).forEach(user => relationships[user.id] = 5); + RelationshipStore.emitChange(); + if (--count === 0) { + FluxDispatcher.unsubscribe("GUILD_MEMBERS_CHUNK", callback); + } + }; + + FluxDispatcher.subscribe("GUILD_MEMBERS_CHUNK", callback); + for (let i = 0; i < toRequest.length; i += 100) { + FluxDispatcher.dispatch({ + type: "GUILD_MEMBERS_REQUEST", + guildIds: allGuildIds, + userIds: toRequest.slice(i, i + 100), + nonce: sentNonce, + }); + } + }, + + start() { + const { FriendsSections } = findByProps("FriendsSections"); + FriendsSections.IMPLICIT = "IMPLICIT"; + } +}); diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index c40a18140..32579a803 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -42,7 +42,7 @@ export default definePlugin({ find: "getRelationshipCounts(){", replacement: { match: /\.sortBy\(\i=>\i\.comparator\)/, - replace: ".sortBy((row) => $self.sortList(row))" + replace: "$&.sortBy((row) => $self.sortList(row))" } }, { find: ".Messages.FRIEND_REQUEST_CANCEL", From 9e0aa4b23ccaef9e030d20d3881135875a3364e2 Mon Sep 17 00:00:00 2001 From: Koda!! <162957404+Kodarru@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:51:49 -0700 Subject: [PATCH 012/134] feat(plugin): StreamerModeOnStream (#2320) Co-authored-by: V --- src/plugins/streamerModeOnStream/index.ts | 45 +++++++++++++++++++++++ src/utils/constants.ts | 4 ++ 2 files changed, 49 insertions(+) create mode 100644 src/plugins/streamerModeOnStream/index.ts diff --git a/src/plugins/streamerModeOnStream/index.ts b/src/plugins/streamerModeOnStream/index.ts new file mode 100644 index 000000000..03b83f577 --- /dev/null +++ b/src/plugins/streamerModeOnStream/index.ts @@ -0,0 +1,45 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2024 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 { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { FluxDispatcher, UserStore } from "@webpack/common"; + +interface StreamEvent { + streamKey: string; +} + +function toggleStreamerMode({ streamKey }: StreamEvent, value: boolean) { + if (!streamKey.endsWith(UserStore.getCurrentUser().id)) return; + + FluxDispatcher.dispatch({ + type: "STREAMER_MODE_UPDATE", + key: "enabled", + value + }); +} + +export default definePlugin({ + name: "StreamerModeOnStream", + description: "Automatically enables streamer mode when you start streaming in Discord", + authors: [Devs.Kodarru], + flux: { + STREAM_CREATE: d => toggleStreamerMode(d, true), + STREAM_DELETE: d => toggleStreamerMode(d, false) + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 917fabf43..8ab0bffb3 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -426,6 +426,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "newwares", id: 421405303951851520n }, + Kodarru: { + name: "Kodarru", + id: 785227396218748949n + }, nakoyasha: { name: "nakoyasha", id: 222069018507345921n From 4fce88fa8f048e648240a42e553c740a2927afda Mon Sep 17 00:00:00 2001 From: Elvyra <88881326+EdVraz@users.noreply.github.com> Date: Wed, 24 Apr 2024 23:05:02 +0200 Subject: [PATCH 013/134] Fix OnePingPerDM and RoleColorEverywhere patches (#2387) --- src/plugins/onePingPerDM/index.ts | 2 +- src/plugins/roleColorEverywhere/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/onePingPerDM/index.ts b/src/plugins/onePingPerDM/index.ts index ae38343db..e9cde6523 100644 --- a/src/plugins/onePingPerDM/index.ts +++ b/src/plugins/onePingPerDM/index.ts @@ -49,7 +49,7 @@ export default definePlugin({ replace: "$&if(!$self.isPrivateChannelRead(arguments[0]?.message))return;else " }, { - match: /sound:(\i\?\i:void 0,volume:\i,onClick)/, + match: /sound:(\i\?\i:void 0,soundpack:\i,volume:\i,onClick)/, replace: "sound:!$self.isPrivateChannelRead(arguments[0]?.message)?undefined:$1" }] }], diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 71c291fef..942697801 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -94,7 +94,7 @@ export default definePlugin({ find: "renderPrioritySpeaker", replacement: [ { - match: /renderName\(\).{0,100}speaking:.{50,150}"div",{/, + match: /renderName\(\).{0,100}speaking:.{50,200}"div",{/, replace: "$&...$self.getVoiceProps(this.props)," } ], From 36327ebd70eadddda03be9b7b36b182e79ae7dde Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:55:28 -0300 Subject: [PATCH 014/134] PronounDB: Fix patch --- src/plugins/pronoundb/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index 61edd191e..b14b26572 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -56,7 +56,7 @@ export default definePlugin({ find: ".pronouns,children", replacement: [ { - match: /{user:(\i),[^}]*,pronouns:(\i),[^}]*}=\i;/, + match: /{user:(\i),[^}]*,pronouns:(\i),[^}]*}=\i.*?;(?=return)/, replace: "$&let vcPronounSource;[$2,vcPronounSource]=$self.useProfilePronouns($1.id);" }, PRONOUN_TOOLTIP_PATCH From c10466f607d889c06afdee46f7af31b1062e78b5 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:30:52 -0300 Subject: [PATCH 015/134] MoreUserTags: Fix patches --- src/plugins/moreUserTags/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index d1ad941b0..4ac542216 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -198,7 +198,8 @@ export default definePlugin({ replacement: [ // make the tag show the right text { - match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=.{0,40}(\i\.\i\.Messages)\.BOT_TAG_BOT/, + // FIXME: Remove the BOT_TAG_BOT variant when the change arrives in stable + match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=.{0,40}(\i\.\i\.Messages)\.(?:APP_TAG|BOT_TAG_BOT)/, replace: (_, origSwitch, variant, tags, displayedText, strings) => `${origSwitch}default:{${displayedText} = $self.getTagText(${tags}[${variant}], ${strings})}` }, @@ -321,19 +322,20 @@ export default definePlugin({ isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]), + // FIXME: Remove the BOT_TAG_BOT variants from strings when the change arrives in stable getTagText(passedTagName: string, strings: Record) { - if (!passedTagName) return strings.BOT_TAG_BOT; + if (!passedTagName) return strings.APP_TAG ?? strings.BOT_TAG_BOT; const [tagName, variant] = passedTagName.split("-"); const tag = tags.find(({ name }) => tagName === name); - if (!tag) return strings.BOT_TAG_BOT; - if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.BOT_TAG_BOT; + if (!tag) return strings.APP_TAG ?? strings.BOT_TAG_BOT; + if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.APP_TAG ?? strings.BOT_TAG_BOT; const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; switch (variant) { case "OP": return `${strings.BOT_TAG_FORUM_ORIGINAL_POSTER} • ${tagText}`; case "BOT": - return `${strings.BOT_TAG_BOT} • ${tagText}`; + return `${strings.APP_TAG ?? strings.BOT_TAG_BOT} • ${tagText}`; default: return tagText; } From fafd46d2028e702d7341e1eb404c68fede49bdd3 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:31:22 -0300 Subject: [PATCH 016/134] FriendsSince: Remove workaround for stable compatibility --- src/plugins/friendsSince/index.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index 69d8e739d..d6b7d1072 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -7,22 +7,12 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; -import { makeLazy } from "@utils/lazy"; import definePlugin from "@utils/types"; -import { filters, find, findByPropsLazy, handleModuleNotFound } from "@webpack"; +import { findByPropsLazy } from "@webpack"; import { React, RelationshipStore } from "@webpack/common"; const { Heading, Text } = findByPropsLazy("Heading", "Text"); -// Workaround for module differing on stable & canary -// FIXME: remove once merged into stable -const getMemberSinceContainer = makeLazy(() => { - for (const name of ["memberSinceWrapper", "memberSinceContainer"]) { - const mod = find(filters.byProps(name), { isIndirect: true }); - if (mod) return mod[name]; - } - handleModuleNotFound("findByProps", "memberSinceWrapper/memberSinceContainer"); - return ""; -}); +const container = findByPropsLazy("memberSinceWrapper"); const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate"); const clydeMoreInfo = findByPropsLazy("clydeMoreInfo"); const locale = findByPropsLazy("getLocale"); @@ -59,7 +49,7 @@ export default definePlugin({ Friends Since -
+
{!!getCurrentChannel()?.guild_id && (
@@ -84,30 +88,48 @@ function ContributorModal({ user }: { user: User; }) {
{website && ( - - - + + {props => ( + + + + )} + )} {githubName && ( - - - + + {props => ( + + + + )} + )}
-
- {plugins.map(p => - showToast("Restart to apply changes!")} - /> - )} -
+ {plugins.length ? ( + + This person has {ContributedHyperLink} to {pluralise(plugins.length, "plugin")}! + + ) : ( + + This person has not made any plugins. They likely {ContributedHyperLink} to Vencord in other ways! + + )} + + {!!plugins.length && ( +
+ {plugins.map(p => + showToast("Restart to apply changes!")} + /> + )} +
+ )} ); } diff --git a/src/components/PluginSettings/contributorModal.css b/src/components/PluginSettings/contributorModal.css index 09f0103fd..ad2f1330c 100644 --- a/src/components/PluginSettings/contributorModal.css +++ b/src/components/PluginSettings/contributorModal.css @@ -25,11 +25,13 @@ display: block; position: absolute; height: 100%; - width: 16px; + width: 32px; background: var(--background-tertiary); z-index: -1; - left: -16px; + left: -32px; top: 0; + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; } .vc-author-modal-avatar { @@ -55,4 +57,5 @@ .vc-author-modal-plugins { display: grid; gap: 0.5em; + margin-top: 0.75em; } diff --git a/src/plugins/_api/badges.tsx b/src/plugins/_api/badges.tsx index 6b1a79cd5..6cbe1feb0 100644 --- a/src/plugins/_api/badges.tsx +++ b/src/plugins/_api/badges.tsx @@ -34,14 +34,13 @@ const ContributorBadge: ProfileBadge = { description: "Vencord Contributor", image: CONTRIBUTOR_BADGE, position: BadgePosition.START, - props: { - style: { - borderRadius: "50%", - transform: "scale(0.9)" // The image is a bit too big compared to default badges - } - }, shouldShow: ({ user }) => isPluginDev(user.id), - link: "https://github.com/Vendicated/Vencord" + onClick(_, { user }) { + // circular import shenanigans + const { openContributorModal } = require("@components/PluginSettings/ContributorModal") as typeof import("@components/PluginSettings/ContributorModal"); + // setImmediate is needed to run on later tick to workaround limitation in proxyLazy + setImmediate(() => openContributorModal(user)); + } }; let DonorBadges = {} as Record>>; @@ -85,7 +84,7 @@ export default definePlugin({ // conditionally override their onClick with badge.onClick if it exists { match: /href:(\i)\.link/, - replace: "...($1.onClick && { onClick: $1.onClick }),$&" + replace: "...($1.onClick && { onClick: vcE => $1.onClick(vcE, arguments[0]) }),$&" } ] } diff --git a/src/utils/misc.tsx b/src/utils/misc.tsx index 2b8ccf8a7..32010e59b 100644 --- a/src/utils/misc.tsx +++ b/src/utils/misc.tsx @@ -114,3 +114,7 @@ export function identity(value: T): T { export const isMobile = navigator.userAgent.includes("Mobi"); export const isPluginDev = (id: string) => Object.hasOwn(DevsById, id); + +export function pluralise(amount: number, singular: string, plural = singular + "s") { + return amount === 1 ? `${amount} ${singular}` : `${amount} ${plural}`; +} From 0a598ae9668547ac11e5a8dd1aee645b1916da2b Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 2 May 2024 15:38:53 +0200 Subject: [PATCH 028/134] fix FriendsSince --- src/plugins/friendsSince/index.tsx | 3 +-- src/webpack/common/components.ts | 25 +++++++++++++++++++++++- src/webpack/common/types/components.d.ts | 11 ++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index d6b7d1072..fb431b52b 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -9,9 +9,8 @@ import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { React, RelationshipStore } from "@webpack/common"; +import { Heading, React, RelationshipStore, Text } from "@webpack/common"; -const { Heading, Text } = findByPropsLazy("Heading", "Text"); const container = findByPropsLazy("memberSinceWrapper"); const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate"); const clydeMoreInfo = findByPropsLazy("clydeMoreInfo"); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 24477c725..020c8fc7e 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -36,6 +36,7 @@ export let Tooltip: t.Tooltip; export let TextInput: t.TextInput; export let TextArea: t.TextArea; export let Text: t.Text; +export let Heading: t.HeadingTag; export let Select: t.Select; export let SearchableSelect: t.SearchableSelect; export let Slider: t.Slider; @@ -59,6 +60,28 @@ export const Flex = waitForComponent("Flex", ["Justify", "Align", "Wrap" export const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal"); waitFor(["FormItem", "Button"], m => { - ({ useToken, Card, Button, FormSwitch: Switch, Tooltip, TextInput, TextArea, Text, Select, SearchableSelect, Slider, ButtonLooks, TabBar, Popout, Dialog, Paginator, ScrollerThin, Clickable, Avatar, FocusLock } = m); + ({ + useToken, + Card, + Button, + FormSwitch: Switch, + Tooltip, + TextInput, + TextArea, + Text, + Select, + SearchableSelect, + Slider, + ButtonLooks, + TabBar, + Popout, + Dialog, + Paginator, + ScrollerThin, + Clickable, + Avatar, + FocusLock, + Heading + } = m); Forms = m; }); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 3e3ffa4bd..c51264370 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -20,23 +20,24 @@ import type { ComponentType, CSSProperties, FunctionComponent, HtmlHTMLAttribute export type TextVariant = "heading-sm/normal" | "heading-sm/medium" | "heading-sm/semibold" | "heading-sm/bold" | "heading-md/normal" | "heading-md/medium" | "heading-md/semibold" | "heading-md/bold" | "heading-lg/normal" | "heading-lg/medium" | "heading-lg/semibold" | "heading-lg/bold" | "heading-xl/normal" | "heading-xl/medium" | "heading-xl/bold" | "heading-xxl/normal" | "heading-xxl/medium" | "heading-xxl/bold" | "eyebrow" | "heading-deprecated-14/normal" | "heading-deprecated-14/medium" | "heading-deprecated-14/bold" | "text-xxs/normal" | "text-xxs/medium" | "text-xxs/semibold" | "text-xxs/bold" | "text-xs/normal" | "text-xs/medium" | "text-xs/semibold" | "text-xs/bold" | "text-sm/normal" | "text-sm/medium" | "text-sm/semibold" | "text-sm/bold" | "text-md/normal" | "text-md/medium" | "text-md/semibold" | "text-md/bold" | "text-lg/normal" | "text-lg/medium" | "text-lg/semibold" | "text-lg/bold" | "display-sm" | "display-md" | "display-lg" | "code"; export type FormTextTypes = Record<"DEFAULT" | "INPUT_PLACEHOLDER" | "DESCRIPTION" | "LABEL_BOLD" | "LABEL_SELECTED" | "LABEL_DESCRIPTOR" | "ERROR" | "SUCCESS", string>; -export type Heading = `h${1 | 2 | 3 | 4 | 5 | 6}`; +export type HeadingTag = `h${1 | 2 | 3 | 4 | 5 | 6}`; export type Margins = Record<"marginTop16" | "marginTop8" | "marginBottom8" | "marginTop20" | "marginBottom20", string>; export type ButtonLooks = Record<"FILLED" | "INVERTED" | "OUTLINED" | "LINK" | "BLANK", string>; export type TextProps = PropsWithChildren & { variant?: TextVariant; - tag?: "div" | "span" | "p" | "strong" | Heading; + tag?: "div" | "span" | "p" | "strong" | HeadingTag; selectable?: boolean; lineClamp?: number; }>; export type Text = ComponentType; +export type Heading = ComponentType; export type FormTitle = ComponentType & PropsWithChildren<{ /** default is h5 */ - tag?: Heading; + tag?: HeadingTag; faded?: boolean; disabled?: boolean; required?: boolean; @@ -45,7 +46,7 @@ export type FormTitle = ComponentType & PropsWithChi export type FormSection = ComponentType>; type FocusLock = ComponentType + containerRef: RefObject; }>>; From a055b1d47b971e92fc34cd7b13ac0e172cfd19fd Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 2 May 2024 18:52:41 -0300 Subject: [PATCH 029/134] refactor(Webpack): more reliable patching (#2237) --- scripts/generateReport.ts | 284 ++++++++++-------- src/plugins/index.ts | 49 ++- src/plugins/showHiddenChannels/index.tsx | 6 +- src/utils/patches.ts | 10 +- src/webpack/common/components.ts | 2 +- src/webpack/common/utils.ts | 3 + src/webpack/patchWebpack.ts | 363 ++++++++++++++--------- src/webpack/webpack.ts | 28 +- 8 files changed, 443 insertions(+), 302 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 41e384295..912f38eda 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -269,7 +269,7 @@ page.on("pageerror", e => console.error("[Page Error]", e)); await page.setBypassCSP(true); -function runTime(token: string) { +async function runtime(token: string) { console.log("[PUP_DEBUG]", "Starting test..."); try { @@ -282,9 +282,13 @@ function runTime(token: string) { // Monkey patch Logger to not log with custom css // @ts-ignore + const originalLog = Vencord.Util.Logger.prototype._log; + // @ts-ignore Vencord.Util.Logger.prototype._log = function (level, levelColor, args) { if (level === "warn" || level === "error") - console[level]("[Vencord]", this.name + ":", ...args); + return console[level]("[Vencord]", this.name + ":", ...args); + + return originalLog.call(this, level, levelColor, args); }; // Force enable all plugins and patches @@ -310,45 +314,30 @@ function runTime(token: string) { }); }); - Vencord.Webpack.waitFor( - "loginToken", - m => { - console.log("[PUP_DEBUG]", "Logging in with token..."); - m.loginToken(token); - } - ); + let wreq: typeof Vencord.Webpack.wreq; - // Force load all chunks - Vencord.Webpack.onceReady.then(() => setTimeout(async () => { - console.log("[PUP_DEBUG]", "Webpack is ready!"); + const { canonicalizeMatch, Logger } = Vencord.Util; - const { wreq } = Vencord.Webpack; + const validChunks = new Set(); + const invalidChunks = new Set(); - console.log("[PUP_DEBUG]", "Loading all chunks..."); + let chunksSearchingResolve: (value: void | PromiseLike) => void; + const chunksSearchingDone = new Promise(r => chunksSearchingResolve = r); - let chunks = null as Record | null; - const sym = Symbol("Vencord.chunksExtract"); + // True if resolved, false otherwise + const chunksSearchPromises = [] as Array<() => boolean>; + const lazyChunkRegex = canonicalizeMatch(/Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\)/g); + const chunkIdsRegex = canonicalizeMatch(/\("(.+?)"\)/g); - Object.defineProperty(Object.prototype, sym, { - get() { - chunks = this; - }, - set() { }, - configurable: true, - }); + async function searchAndLoadLazyChunks(factoryCode: string) { + const lazyChunks = factoryCode.matchAll(lazyChunkRegex); + const validChunkGroups = new Set<[chunkIds: string[], entryPoint: string]>(); - await (wreq as any).el(sym); - delete Object.prototype[sym]; + await Promise.all(Array.from(lazyChunks).map(async ([, rawChunkIds, entryPoint]) => { + const chunkIds = Array.from(rawChunkIds.matchAll(chunkIdsRegex)).map(m => m[1]); + if (chunkIds.length === 0) return; - const validChunksEntryPoints = new Set(); - const validChunks = new Set(); - const invalidChunks = new Set(); - - if (!chunks) throw new Error("Failed to get chunks"); - - for (const entryPoint in chunks) { - const chunkIds = chunks[entryPoint]; - let invalidEntryPoint = false; + let invalidChunkGroup = false; for (const id of chunkIds) { if (wreq.u(id) == null || wreq.u(id) === "undefined.js") continue; @@ -359,56 +348,28 @@ function runTime(token: string) { if (isWasm) { invalidChunks.add(id); - invalidEntryPoint = true; + invalidChunkGroup = true; continue; } validChunks.add(id); } - if (!invalidEntryPoint) - validChunksEntryPoints.add(entryPoint); - } + if (!invalidChunkGroup) { + validChunkGroups.add([chunkIds, entryPoint]); + } + })); - for (const entryPoint of validChunksEntryPoints) { - try { - // Loads all chunks required for an entry point - await (wreq as any).el(entryPoint); - } catch (err) { } - } + // Loads all found valid chunk groups + await Promise.all( + Array.from(validChunkGroups) + .map(([chunkIds]) => + Promise.all(chunkIds.map(id => wreq.e(id as any).catch(() => { }))) + ) + ); - // Matches "id" or id: - const chunkIdRegex = /(?:"(\d+?)")|(?:(\d+?):)/g; - const wreqU = wreq.u.toString(); - - const allChunks = [] as string[]; - let currentMatch: RegExpExecArray | null; - - while ((currentMatch = chunkIdRegex.exec(wreqU)) != null) { - const id = currentMatch[1] ?? currentMatch[2]; - if (id == null) continue; - - allChunks.push(id); - } - - if (allChunks.length === 0) throw new Error("Failed to get all chunks"); - const chunksLeft = allChunks.filter(id => { - return !(validChunks.has(id) || invalidChunks.has(id)); - }); - - for (const id of chunksLeft) { - const isWasm = await fetch(wreq.p + wreq.u(id)) - .then(r => r.text()) - .then(t => t.includes(".module.wasm") || !t.includes("(this.webpackChunkdiscord_app=this.webpackChunkdiscord_app||[]).push")); - - // Loads a chunk - if (!isWasm) await wreq.e(id as any); - } - - // Make sure every chunk has finished loading - await new Promise(r => setTimeout(r, 1000)); - - for (const entryPoint of validChunksEntryPoints) { + // Requires the entry points for all valid chunk groups + for (const [, entryPoint] of validChunkGroups) { try { if (wreq.m[entryPoint]) wreq(entryPoint as any); } catch (err) { @@ -416,54 +377,139 @@ function runTime(token: string) { } } - console.log("[PUP_DEBUG]", "Finished loading all chunks!"); + // setImmediate to only check if all chunks were loaded after this function resolves + // We check if all chunks were loaded every time a factory is loaded + // If we are still looking for chunks in the other factories, the array will have that factory's chunk search promise not resolved + // But, if all chunk search promises are resolved, this means we found every lazy chunk loaded by Discord code and manually loaded them + setTimeout(() => { + let allResolved = true; - for (const patch of Vencord.Plugins.patches) { - if (!patch.all) { - new Vencord.Util.Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`); - } - } + for (let i = 0; i < chunksSearchPromises.length; i++) { + const isResolved = chunksSearchPromises[i](); - for (const [searchType, args] of Vencord.Webpack.lazyWebpackSearchHistory) { - let method = searchType; - - if (searchType === "findComponent") method = "find"; - if (searchType === "findExportedComponent") method = "findByProps"; - if (searchType === "waitFor" || searchType === "waitForComponent") { - if (typeof args[0] === "string") method = "findByProps"; - else method = "find"; - } - if (searchType === "waitForStore") method = "findStore"; - - try { - let result: any; - - if (method === "proxyLazyWebpack" || method === "LazyComponentWebpack") { - const [factory] = args; - result = factory(); - } else if (method === "extractAndLoadChunks") { - const [code, matcher] = args; - - const module = Vencord.Webpack.findModuleFactory(...code); - if (module) result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); + if (isResolved) { + // Remove finished promises to avoid having to iterate through a huge array everytime + chunksSearchPromises.splice(i--, 1); } else { - // @ts-ignore - result = Vencord.Webpack[method](...args); + allResolved = false; } - - if (result == null || ("$$vencordInternal" in result && result.$$vencordInternal() == null)) throw "a rock at ben shapiro"; - } catch (e) { - let logMessage = searchType; - if (method === "find" || method === "proxyLazyWebpack" || method === "LazyComponentWebpack") logMessage += `(${args[0].toString().slice(0, 147)}...)`; - else if (method === "extractAndLoadChunks") logMessage += `([${args[0].map(arg => `"${arg}"`).join(", ")}], ${args[1].toString()})`; - else logMessage += `(${args.map(arg => `"${arg}"`).join(", ")})`; - - console.log("[PUP_WEBPACK_FIND_FAIL]", logMessage); } - } - setTimeout(() => console.log("[PUPPETEER_TEST_DONE_SIGNAL]"), 1000); - }, 1000)); + if (allResolved) chunksSearchingResolve(); + }, 0); + } + + Vencord.Webpack.waitFor( + "loginToken", + m => { + console.log("[PUP_DEBUG]", "Logging in with token..."); + m.loginToken(token); + } + ); + + Vencord.Webpack.beforeInitListeners.add(async webpackRequire => { + console.log("[PUP_DEBUG]", "Loading all chunks..."); + + wreq = webpackRequire; + + Vencord.Webpack.factoryListeners.add(factory => { + let isResolved = false; + searchAndLoadLazyChunks(factory.toString()).then(() => isResolved = true); + + chunksSearchPromises.push(() => isResolved); + }); + + // setImmediate to only search the initial factories after Discord initialized the app + // our beforeInitListeners are called before Discord initializes the app + setTimeout(() => { + for (const factoryId in wreq.m) { + let isResolved = false; + searchAndLoadLazyChunks(wreq.m[factoryId].toString()).then(() => isResolved = true); + + chunksSearchPromises.push(() => isResolved); + } + }, 0); + }); + + await chunksSearchingDone; + + // All chunks Discord has mapped to asset files, even if they are not used anymore + const allChunks = [] as string[]; + + // Matches "id" or id: + for (const currentMatch of wreq!.u.toString().matchAll(/(?:"(\d+?)")|(?:(\d+?):)/g)) { + const id = currentMatch[1] ?? currentMatch[2]; + if (id == null) continue; + + allChunks.push(id); + } + + if (allChunks.length === 0) throw new Error("Failed to get all chunks"); + + // Chunks that are not loaded (not used) by Discord code anymore + const chunksLeft = allChunks.filter(id => { + return !(validChunks.has(id) || invalidChunks.has(id)); + }); + + await Promise.all(chunksLeft.map(async id => { + const isWasm = await fetch(wreq.p + wreq.u(id)) + .then(r => r.text()) + .then(t => t.includes(".module.wasm") || !t.includes("(this.webpackChunkdiscord_app=this.webpackChunkdiscord_app||[]).push")); + + // Loads and requires a chunk + if (!isWasm) { + await wreq.e(id as any); + if (wreq.m[id]) wreq(id as any); + } + })); + + console.log("[PUP_DEBUG]", "Finished loading all chunks!"); + + for (const patch of Vencord.Plugins.patches) { + if (!patch.all) { + new Logger("WebpackInterceptor").warn(`Patch by ${patch.plugin} found no module (Module id is -): ${patch.find}`); + } + } + + for (const [searchType, args] of Vencord.Webpack.lazyWebpackSearchHistory) { + let method = searchType; + + if (searchType === "findComponent") method = "find"; + if (searchType === "findExportedComponent") method = "findByProps"; + if (searchType === "waitFor" || searchType === "waitForComponent") { + if (typeof args[0] === "string") method = "findByProps"; + else method = "find"; + } + if (searchType === "waitForStore") method = "findStore"; + + try { + let result: any; + + if (method === "proxyLazyWebpack" || method === "LazyComponentWebpack") { + const [factory] = args; + result = factory(); + } else if (method === "extractAndLoadChunks") { + const [code, matcher] = args; + + const module = Vencord.Webpack.findModuleFactory(...code); + if (module) result = module.toString().match(canonicalizeMatch(matcher)); + } else { + // @ts-ignore + result = Vencord.Webpack[method](...args); + } + + if (result == null || ("$$vencordInternal" in result && result.$$vencordInternal() == null)) throw "a rock at ben shapiro"; + } catch (e) { + let logMessage = searchType; + if (method === "find" || method === "proxyLazyWebpack" || method === "LazyComponentWebpack") logMessage += `(${args[0].toString().slice(0, 147)}...)`; + else if (method === "extractAndLoadChunks") logMessage += `([${args[0].map(arg => `"${arg}"`).join(", ")}], ${args[1].toString()})`; + else logMessage += `(${args.map(arg => `"${arg}"`).join(", ")})`; + + console.log("[PUP_WEBPACK_FIND_FAIL]", logMessage); + } + } + + setTimeout(() => console.log("[PUPPETEER_TEST_DONE_SIGNAL]"), 1000); } catch (e) { console.log("[PUP_DEBUG]", "A fatal error occurred:", e); process.exit(1); @@ -473,7 +519,7 @@ function runTime(token: string) { await page.evaluateOnNewDocument(` ${readFileSync("./dist/browser.js", "utf-8")} - ;(${runTime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)}); + ;(${runtime.toString()})(${JSON.stringify(process.env.DISCORD_TOKEN)}); `); await page.goto(CANARY ? "https://canary.discord.com/login" : "https://discord.com/login"); diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 7092001ee..2d5e3e5a4 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -34,6 +34,9 @@ export const PMLogger = logger; export const plugins = Plugins; export const patches = [] as Patch[]; +/** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */ +let enabledPluginsSubscribedFlux = false; + const settings = Settings.plugins; export function isPluginEnabled(p: string) { @@ -119,6 +122,33 @@ export function startDependenciesRecursive(p: Plugin) { return { restartNeeded, failures }; } +export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) { + if (p.flux) { + logger.debug("Subscribing to flux events of plugin", p.name); + for (const [event, handler] of Object.entries(p.flux)) { + fluxDispatcher.subscribe(event as FluxEvents, handler); + } + } +} + +export function unsubscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) { + if (p.flux) { + logger.debug("Unsubscribing from flux events of plugin", p.name); + for (const [event, handler] of Object.entries(p.flux)) { + fluxDispatcher.unsubscribe(event as FluxEvents, handler); + } + } +} + +export function subscribeAllPluginsFluxEvents(fluxDispatcher: typeof FluxDispatcher) { + enabledPluginsSubscribedFlux = true; + + for (const name in Plugins) { + if (!isPluginEnabled(name)) continue; + subscribePluginFluxEvents(Plugins[name], fluxDispatcher); + } +} + export const startPlugin = traceFunction("startPlugin", function startPlugin(p: Plugin) { const { name, commands, flux, contextMenus } = p; @@ -138,7 +168,7 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: } if (commands?.length) { - logger.info("Registering commands of plugin", name); + logger.debug("Registering commands of plugin", name); for (const cmd of commands) { try { registerCommand(cmd, name); @@ -149,13 +179,13 @@ export const startPlugin = traceFunction("startPlugin", function startPlugin(p: } } - if (flux) { - for (const event in flux) { - FluxDispatcher.subscribe(event as FluxEvents, flux[event]); - } + if (enabledPluginsSubscribedFlux) { + subscribePluginFluxEvents(p, FluxDispatcher); } + if (contextMenus) { + logger.debug("Adding context menus patches of plugin", name); for (const navId in contextMenus) { addContextMenuPatch(navId, contextMenus[navId]); } @@ -182,7 +212,7 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu } if (commands?.length) { - logger.info("Unregistering commands of plugin", name); + logger.debug("Unregistering commands of plugin", name); for (const cmd of commands) { try { unregisterCommand(cmd.name); @@ -193,13 +223,10 @@ export const stopPlugin = traceFunction("stopPlugin", function stopPlugin(p: Plu } } - if (flux) { - for (const event in flux) { - FluxDispatcher.unsubscribe(event as FluxEvents, flux[event]); - } - } + unsubscribePluginFluxEvents(p, FluxDispatcher); if (contextMenus) { + logger.debug("Removing context menus patches of plugin", name); for (const navId in contextMenus) { removeContextMenuPatch(navId, contextMenus[navId]); } diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index ce4a47ade..09aa2302a 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -36,6 +36,8 @@ const enum ShowMode { HiddenIconWithMutedStyle } +const CONNECT = 1n << 20n; + export const settings = definePluginSettings({ hideUnreads: { description: "Hide Unreads", @@ -273,12 +275,12 @@ export default definePlugin({ { // Change the role permission check to CONNECT if the channel is locked match: /ADMINISTRATOR\)\|\|(?<=context:(\i)}.+?)(?=(.+?)VIEW_CHANNEL)/, - replace: (m, channel, permCheck) => `${m}!Vencord.Webpack.Common.PermissionStore.can(${PermissionsBits.CONNECT}n,${channel})?${permCheck}CONNECT):` + replace: (m, channel, permCheck) => `${m}!Vencord.Webpack.Common.PermissionStore.can(${CONNECT}n,${channel})?${permCheck}CONNECT):` }, { // Change the permissionOverwrite check to CONNECT if the channel is locked match: /permissionOverwrites\[.+?\i=(?<=context:(\i)}.+?)(?=(.+?)VIEW_CHANNEL)/, - replace: (m, channel, permCheck) => `${m}!Vencord.Webpack.Common.PermissionStore.can(${PermissionsBits.CONNECT}n,${channel})?${permCheck}CONNECT):` + replace: (m, channel, permCheck) => `${m}!Vencord.Webpack.Common.PermissionStore.can(${CONNECT}n,${channel})?${permCheck}CONNECT):` }, { // Include the @everyone role in the allowed roles list for Hidden Channels diff --git a/src/utils/patches.ts b/src/utils/patches.ts index c30f7b17c..99f0595d6 100644 --- a/src/utils/patches.ts +++ b/src/utils/patches.ts @@ -18,20 +18,20 @@ import { PatchReplacement, ReplaceFn } from "./types"; -export function canonicalizeMatch(match: RegExp | string) { +export function canonicalizeMatch(match: T): T { if (typeof match === "string") return match; const canonSource = match.source .replaceAll("\\i", "[A-Za-z_$][\\w$]*"); - return new RegExp(canonSource, match.flags); + return new RegExp(canonSource, match.flags) as T; } -export function canonicalizeReplace(replace: string | ReplaceFn, pluginName: string): string | ReplaceFn { +export function canonicalizeReplace(replace: T, pluginName: string): T { const self = `Vencord.Plugins.plugins[${JSON.stringify(pluginName)}]`; if (typeof replace !== "function") - return replace.replaceAll("$self", self); + return replace.replaceAll("$self", self) as T; - return (...args) => replace(...args).replaceAll("$self", self); + return ((...args) => replace(...args).replaceAll("$self", self)) as T; } export function canonicalizeDescriptor(descriptor: TypedPropertyDescriptor, canonicalize: (value: T) => T) { diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 020c8fc7e..46f843ce6 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -36,7 +36,7 @@ export let Tooltip: t.Tooltip; export let TextInput: t.TextInput; export let TextArea: t.TextArea; export let Text: t.Text; -export let Heading: t.HeadingTag; +export let Heading: t.Heading; export let Select: t.Select; export let SearchableSelect: t.SearchableSelect; export let Slider: t.Slider; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index ec6c0e1ed..f5d30cd76 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -26,6 +26,9 @@ export let FluxDispatcher: t.FluxDispatcher; waitFor(["dispatch", "subscribe"], m => { FluxDispatcher = m; + // Non import call to avoid circular dependency + Vencord.Plugins.subscribeAllPluginsFluxEvents(m); + const cb = () => { m.unsubscribe("CONNECTION_OPEN", cb); _resolveReady(); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index db47c875a..d2b569e8d 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -18,66 +18,120 @@ import { WEBPACK_CHUNK } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import { canonicalizeReplacement } from "@utils/patches"; +import { canonicalizeMatch, canonicalizeReplacement } from "@utils/patches"; import { PatchReplacement } from "@utils/types"; +import { WebpackInstance } from "discord-types/other"; import { traceFunction } from "../debug/Tracer"; -import { _initWebpack } from "."; +import { patches } from "../plugins"; +import { _initWebpack, beforeInitListeners, factoryListeners, moduleListeners, subscriptions, wreq } from "."; + +const logger = new Logger("WebpackInterceptor", "#8caaee"); +const initCallbackRegex = canonicalizeMatch(/{return \i\(".+?"\)}/); let webpackChunk: any[]; -const logger = new Logger("WebpackInterceptor", "#8caaee"); +// Patch the window webpack chunk setter to monkey patch the push method before any chunks are pushed +// This way we can patch the factory of everything being pushed to the modules array +Object.defineProperty(window, WEBPACK_CHUNK, { + configurable: true, -if (window[WEBPACK_CHUNK]) { - logger.info(`Patching ${WEBPACK_CHUNK}.push (was already existent, likely from cache!)`); - _initWebpack(window[WEBPACK_CHUNK]); - patchPush(window[WEBPACK_CHUNK]); -} else { - Object.defineProperty(window, WEBPACK_CHUNK, { - get: () => webpackChunk, - set: v => { - if (v?.push) { - if (!v.push.$$vencordOriginal) { - logger.info(`Patching ${WEBPACK_CHUNK}.push`); - patchPush(v); + get: () => webpackChunk, + set: v => { + if (v?.push) { + if (!v.push.$$vencordOriginal) { + logger.info(`Patching ${WEBPACK_CHUNK}.push`); + patchPush(v); + + // @ts-ignore + delete window[WEBPACK_CHUNK]; + window[WEBPACK_CHUNK] = v; + } + } + + webpackChunk = v; + } +}); + +// wreq.O is the webpack onChunksLoaded function +// Discord uses it to await for all the chunks to be loaded before initializing the app +// We monkey patch it to also monkey patch the initialize app callback to get immediate access to the webpack require and run our listeners before doing it +Object.defineProperty(Function.prototype, "O", { + configurable: true, + + set(onChunksLoaded: any) { + // When using react devtools or other extensions, or even when discord loads the sentry, we may also catch their webpack here. + // This ensures we actually got the right one + // this.e (wreq.e) is the method for loading a chunk, and only the main webpack has it + if (new Error().stack?.includes("discord.com") && String(this.e).includes("Promise.all")) { + logger.info("Found main WebpackRequire.onChunksLoaded"); + + delete (Function.prototype as any).O; + + const originalOnChunksLoaded = onChunksLoaded; + onChunksLoaded = function (this: unknown, result: any, chunkIds: string[], callback: () => any, priority: number) { + if (callback != null && initCallbackRegex.test(callback.toString())) { + Object.defineProperty(this, "O", { + value: originalOnChunksLoaded, + configurable: true + }); + + const wreq = this as WebpackInstance; + + const originalCallback = callback; + callback = function (this: unknown) { + logger.info("Patched initialize app callback invoked, initializing our internal references to WebpackRequire and running beforeInitListeners"); + _initWebpack(wreq); + + for (const beforeInitListener of beforeInitListeners) { + beforeInitListener(wreq); + } + + originalCallback.apply(this, arguments as any); + }; + + callback.toString = originalCallback.toString.bind(originalCallback); + arguments[2] = callback; } - if (_initWebpack(v)) { - logger.info("Successfully initialised Vencord webpack"); - // @ts-ignore - delete window[WEBPACK_CHUNK]; - window[WEBPACK_CHUNK] = v; - } - } - webpackChunk = v; - }, - configurable: true - }); + originalOnChunksLoaded.apply(this, arguments as any); + }; - // wreq.m is the webpack module factory. - // normally, this is populated via webpackGlobal.push, which we patch below. - // However, Discord has their .m prepopulated. - // Thus, we use this hack to immediately access their wreq.m and patch all already existing factories - // - // Update: Discord now has TWO webpack instances. Their normal one and sentry - // Sentry does not push chunks to the global at all, so this same patch now also handles their sentry modules - Object.defineProperty(Function.prototype, "m", { - set(v: any) { - // When using react devtools or other extensions, we may also catch their webpack here. - // This ensures we actually got the right one - if (new Error().stack?.includes("discord.com")) { - logger.info("Found webpack module factory"); - patchFactories(v); - } + onChunksLoaded.toString = originalOnChunksLoaded.toString.bind(originalOnChunksLoaded); + } - Object.defineProperty(this, "m", { - value: v, - configurable: true, - }); - }, - configurable: true - }); -} + Object.defineProperty(this, "O", { + value: onChunksLoaded, + configurable: true + }); + } +}); + +// wreq.m is the webpack module factory. +// normally, this is populated via webpackGlobal.push, which we patch below. +// However, Discord has their .m prepopulated. +// Thus, we use this hack to immediately access their wreq.m and patch all already existing factories +// +// Update: Discord now has TWO webpack instances. Their normal one and sentry +// Sentry does not push chunks to the global at all, so this same patch now also handles their sentry modules +Object.defineProperty(Function.prototype, "m", { + configurable: true, + + set(v: any) { + // When using react devtools or other extensions, we may also catch their webpack here. + // This ensures we actually got the right one + const error = new Error(); + if (error.stack?.includes("discord.com")) { + logger.info("Found Webpack module factory", error.stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? ""); + patchFactories(v); + } + + Object.defineProperty(this, "m", { + value: v, + configurable: true + }); + } +}); function patchPush(webpackGlobal: any) { function handlePush(chunk: any) { @@ -91,6 +145,7 @@ function patchPush(webpackGlobal: any) { } handlePush.$$vencordOriginal = webpackGlobal.push; + handlePush.toString = handlePush.$$vencordOriginal.toString.bind(handlePush.$$vencordOriginal); // Webpack overwrites .push with its own push like so: `d.push = n.bind(null, d.push.bind(d));` // it wraps the old push (`d.push.bind(d)`). this old push is in this case our handlePush. // If we then repatched the new push, we would end up with recursive patching, which leads to our patches @@ -99,41 +154,41 @@ function patchPush(webpackGlobal: any) { handlePush.bind = (...args: unknown[]) => handlePush.$$vencordOriginal.bind(...args); Object.defineProperty(webpackGlobal, "push", { + configurable: true, + get: () => handlePush, set(v) { handlePush.$$vencordOriginal = v; - }, - configurable: true + } }); } -function patchFactories(factories: Record void>) { - const { subscriptions, listeners } = Vencord.Webpack; - const { patches } = Vencord.Plugins; +let webpackNotInitializedLogged = false; +function patchFactories(factories: Record void>) { for (const id in factories) { let mod = factories[id]; - // Discords Webpack chunks for some ungodly reason contain random - // newlines. Cyn recommended this workaround and it seems to work fine, - // however this could potentially break code, so if anything goes weird, - // this is probably why. - // Additionally, `[actual newline]` is one less char than "\n", so if Discord - // ever targets newer browsers, the minifier could potentially use this trick and - // cause issues. - // - // 0, prefix is to turn it into an expression: 0,function(){} would be invalid syntax without the 0, - let code: string = "0," + mod.toString().replaceAll("\n", ""); + const originalMod = mod; const patchedBy = new Set(); - const factory = factories[id] = function (module, exports, require) { + const factory = factories[id] = function (module: any, exports: any, require: WebpackInstance) { + if (wreq == null && IS_DEV) { + if (!webpackNotInitializedLogged) { + webpackNotInitializedLogged = true; + logger.error("WebpackRequire was not initialized, running modules without patches instead."); + } + + return void originalMod(module, exports, require); + } + try { mod(module, exports, require); } catch (err) { // Just rethrow discord errors if (mod === originalMod) throw err; - logger.error("Error in patched chunk", err); + logger.error("Error in patched module", err); return void originalMod(module, exports, require); } @@ -153,11 +208,11 @@ function patchFactories(factories: Record string, original: any, (...args: any[]): void; }; - // for some reason throws some error on which calling .toString() leads to infinite recursion - // when you force load all chunks??? - factory.toString = () => mod.toString(); + factory.toString = originalMod.toString.bind(originalMod); factory.original = originalMod; + for (const factoryListener of factoryListeners) { + try { + factoryListener(originalMod); + } catch (err) { + logger.error("Error in Webpack factory listener:\n", err, factoryListener); + } + } + + // Discords Webpack chunks for some ungodly reason contain random + // newlines. Cyn recommended this workaround and it seems to work fine, + // however this could potentially break code, so if anything goes weird, + // this is probably why. + // Additionally, `[actual newline]` is one less char than "\n", so if Discord + // ever targets newer browsers, the minifier could potentially use this trick and + // cause issues. + // + // 0, prefix is to turn it into an expression: 0,function(){} would be invalid syntax without the 0, + let code: string = "0," + mod.toString().replaceAll("\n", ""); + for (let i = 0; i < patches.length; i++) { const patch = patches[i]; - const executePatch = traceFunction(`patch by ${patch.plugin}`, (match: string | RegExp, replace: string) => code.replace(match, replace)); if (patch.predicate && !patch.predicate()) continue; + if (!code.includes(patch.find)) continue; - if (code.includes(patch.find)) { - patchedBy.add(patch.plugin); + patchedBy.add(patch.plugin); - const previousMod = mod; - const previousCode = code; + const executePatch = traceFunction(`patch by ${patch.plugin}`, (match: string | RegExp, replace: string) => code.replace(match, replace)); + const previousMod = mod; + const previousCode = code; - // 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; + // We change all patch.replacement to array in plugins/index + for (const replacement of patch.replacement as PatchReplacement[]) { + if (replacement.predicate && !replacement.predicate()) continue; - canonicalizeReplacement(replacement, patch.plugin); + const lastMod = mod; + const lastCode = code; - try { - const newCode = executePatch(replacement.match, replacement.replace as string); - if (newCode === code) { - if (!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); - } + canonicalizeReplacement(replacement, patch.plugin); + + try { + const newCode = executePatch(replacement.match, replacement.replace as string); + if (newCode === code) { + if (!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); } - - if (patch.group) { - logger.warn(`Undoing patch group ${patch.find} by ${patch.plugin} because replacement ${replacement.match} had no effect`); - code = previousCode; - mod = previousMod; - patchedBy.delete(patch.plugin); - break; - } - } else { - code = newCode; - mod = (0, eval)(`// Webpack Module ${id} - Patched by ${[...patchedBy].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${id}`); - } - } catch (err) { - logger.error(`Patch by ${patch.plugin} errored (Module id is ${id}): ${replacement.match}\n`, err); - - if (IS_DEV) { - const changeSize = code.length - lastCode.length; - const match = lastCode.match(replacement.match)!; - - // Use 200 surrounding characters of context - const start = Math.max(0, match.index! - 200); - const end = Math.min(lastCode.length, match.index! + match[0].length + 200); - // (changeSize may be negative) - const endPatched = end + changeSize; - - const context = lastCode.slice(start, end); - const patchedContext = code.slice(start, endPatched); - - // inline require to avoid including it in !IS_DEV builds - const diff = (require("diff") as typeof import("diff")).diffWordsWithSpace(context, patchedContext); - let fmt = "%c %s "; - const elements = [] as string[]; - for (const d of diff) { - const color = d.removed - ? "red" - : d.added - ? "lime" - : "grey"; - fmt += "%c%s"; - elements.push("color:" + color, d.value); - } - - logger.errorCustomFmt(...Logger.makeTitle("white", "Before"), context); - logger.errorCustomFmt(...Logger.makeTitle("white", "After"), patchedContext); - const [titleFmt, ...titleElements] = Logger.makeTitle("white", "Diff"); - logger.errorCustomFmt(titleFmt + fmt, ...titleElements, ...elements); } - patchedBy.delete(patch.plugin); if (patch.group) { - logger.warn(`Undoing patch group ${patch.find} by ${patch.plugin} because replacement ${replacement.match} errored`); - code = previousCode; + logger.warn(`Undoing patch group ${patch.find} by ${patch.plugin} because replacement ${replacement.match} had no effect`); mod = previousMod; + code = previousCode; + patchedBy.delete(patch.plugin); break; } - code = lastCode; - mod = lastMod; + continue; } - } - if (!patch.all) patches.splice(i--, 1); + code = newCode; + mod = (0, eval)(`// Webpack Module ${id} - Patched by ${[...patchedBy].join(", ")}\n${newCode}\n//# sourceURL=WebpackModule${id}`); + } catch (err) { + logger.error(`Patch by ${patch.plugin} errored (Module id is ${id}): ${replacement.match}\n`, err); + + if (IS_DEV) { + const changeSize = code.length - lastCode.length; + const match = lastCode.match(replacement.match)!; + + // Use 200 surrounding characters of context + const start = Math.max(0, match.index! - 200); + const end = Math.min(lastCode.length, match.index! + match[0].length + 200); + // (changeSize may be negative) + const endPatched = end + changeSize; + + const context = lastCode.slice(start, end); + const patchedContext = code.slice(start, endPatched); + + // inline require to avoid including it in !IS_DEV builds + const diff = (require("diff") as typeof import("diff")).diffWordsWithSpace(context, patchedContext); + let fmt = "%c %s "; + const elements = [] as string[]; + for (const d of diff) { + const color = d.removed + ? "red" + : d.added + ? "lime" + : "grey"; + fmt += "%c%s"; + elements.push("color:" + color, d.value); + } + + logger.errorCustomFmt(...Logger.makeTitle("white", "Before"), context); + logger.errorCustomFmt(...Logger.makeTitle("white", "After"), patchedContext); + const [titleFmt, ...titleElements] = Logger.makeTitle("white", "Diff"); + logger.errorCustomFmt(titleFmt + fmt, ...titleElements, ...elements); + } + + patchedBy.delete(patch.plugin); + + if (patch.group) { + logger.warn(`Undoing patch group ${patch.find} by ${patch.plugin} because replacement ${replacement.match} errored`); + mod = previousMod; + code = previousCode; + break; + } + + mod = lastMod; + code = lastCode; + } } + + if (!patch.all) patches.splice(i--, 1); } } } diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 564da4813..34a9b69c9 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -68,20 +68,16 @@ export const filters = { } }; -export const subscriptions = new Map(); -export const listeners = new Set(); - export type CallbackFn = (mod: any, id: string) => void; -export function _initWebpack(instance: typeof window.webpackChunkdiscord_app) { - if (cache !== void 0) throw "no."; +export const subscriptions = new Map(); +export const moduleListeners = new Set(); +export const factoryListeners = new Set<(factory: (module: any, exports: any, require: WebpackInstance) => void) => void>(); +export const beforeInitListeners = new Set<(wreq: WebpackInstance) => void>(); - instance.push([[Symbol("Vencord")], {}, r => wreq = r]); - instance.pop(); - if (!wreq) return false; - - cache = wreq.c; - return true; +export function _initWebpack(webpackRequire: WebpackInstance) { + wreq = webpackRequire; + cache = webpackRequire.c; } let devToolsOpen = false; @@ -425,7 +421,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def const match = module.toString().match(canonicalizeMatch(matcher)); if (!match) { - const err = new Error("extractAndLoadChunks: Couldn't find entry point id in module factory code"); + const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code"); logger.warn(err, "Code:", code, "Matcher:", matcher); // Strict behaviour in DevBuilds to fail early and make sure the issue is found @@ -491,14 +487,6 @@ export function waitFor(filter: string | string[] | FilterFn, callback: Callback subscriptions.set(filter, callback); } -export function addListener(callback: CallbackFn) { - listeners.add(callback); -} - -export function removeListener(callback: CallbackFn) { - listeners.delete(callback); -} - /** * Search modules by keyword. This searches the factory methods, * meaning you can search all sorts of things, displayName, methodName, strings somewhere in the code, etc From 85d6d74a3e14ed4a1cc83c8131b83c08cfdce04a Mon Sep 17 00:00:00 2001 From: HAHALOSAH <67280050+HAHALOSAH@users.noreply.github.com> Date: Thu, 2 May 2024 23:00:00 +0000 Subject: [PATCH 030/134] messageLogger: fix niche bug ignoring edits when content is same (#2403) --- src/plugins/messageLogger/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index c3a25e1b6..988cd8e39 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -255,7 +255,7 @@ export default definePlugin({ replace: "$1" + ".update($3,m =>" + " (($2.message.flags & 64) === 64 || $self.shouldIgnore($2.message, true)) ? m :" + - " $2.message.content !== m.editHistory?.[0]?.content && $2.message.content !== m.content ?" + + " $2.message.content !== m.content ?" + " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($2.message, m)]) :" + " m" + ")" + From 86b53b24a66048c5b961f43575611fcdcb83b753 Mon Sep 17 00:00:00 2001 From: dolfies Date: Thu, 2 May 2024 19:09:53 -0400 Subject: [PATCH 031/134] feat(plugin): PauseInvitesForever (#2372) Co-authored-by: V --- src/plugins/pauseInvitesForever/README.md | 5 ++ src/plugins/pauseInvitesForever/index.tsx | 74 +++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 src/plugins/pauseInvitesForever/README.md create mode 100644 src/plugins/pauseInvitesForever/index.tsx diff --git a/src/plugins/pauseInvitesForever/README.md b/src/plugins/pauseInvitesForever/README.md new file mode 100644 index 000000000..7ccf0b72f --- /dev/null +++ b/src/plugins/pauseInvitesForever/README.md @@ -0,0 +1,5 @@ +# PauseInvitesForever + +Adds a button to the Security Actions modal to to pause invites indefinitely. + +![](https://github.com/Vendicated/Vencord/assets/47677887/e5ba40a3-cb08-462a-8615-fb74dd54c790) diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx new file mode 100644 index 000000000..81f18fd6e --- /dev/null +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -0,0 +1,74 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 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 { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { GuildStore, RestAPI } from "@webpack/common"; + +const Messages = findByPropsLazy("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); +const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); + +export default definePlugin({ + name: "PauseInvitesForever", + tags: ["DisableInvitesForever"], + description: "Brings back the option to pause invites indefinitely that stupit Discord removed.", + authors: [Devs.Dolfies, Devs.amia], + + patches: [ + { + find: "Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION", + replacement: [{ + match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/, + replace: "children: $self.renderInvitesLabel(arguments[0].guildId, setChecked)", + }, + { + match: /(\i\.hasDMsDisabled\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/, + replace: "$1,setChecked=$2" + }] + } + ], + + showDisableInvites(guildId: string) { + // Once the experiment is removed, this should keep working + const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true }; + // @ts-ignore + return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED"); + }, + + disableInvites(guildId: string) { + const guild = GuildStore.getGuild(guildId); + const features = [...guild.features, "INVITES_DISABLED"]; + RestAPI.patch({ + url: `/guilds/${guild.id}`, + body: { features }, + }); + }, + + renderInvitesLabel(guildId: string, setChecked: Function) { + return ( +
+ {Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {this.showDisableInvites(guildId) && { + setChecked(true); + this.disableInvites(guildId); + }}> Pause Indefinitely.} +
+ ); + } +}); From 84c53b4a27404059446f3748af32cb4da8d2bac0 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 04:52:07 -0300 Subject: [PATCH 032/134] MoreUserTags: Remove old workaround; MessageClickActions: Move finds outside of start --- src/plugins/messageClickActions/index.ts | 7 +++---- src/plugins/moreUserTags/index.tsx | 12 +++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 052c33f61..3d4bb21bb 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -23,11 +23,13 @@ import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { FluxDispatcher, PermissionsBits, PermissionStore, UserStore } from "@webpack/common"; +const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage"); +const EditStore = findByPropsLazy("isEditing", "isEditingAny"); + let isDeletePressed = false; const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true); const keyup = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = false); - const settings = definePluginSettings({ enableDeleteOnClick: { type: OptionType.BOOLEAN, @@ -60,9 +62,6 @@ export default definePlugin({ settings, start() { - const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage"); - const EditStore = findByPropsLazy("isEditing", "isEditingAny"); - document.addEventListener("keydown", keydown); document.addEventListener("keyup", keyup); diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 4ac542216..df47e5456 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -198,8 +198,7 @@ export default definePlugin({ replacement: [ // make the tag show the right text { - // FIXME: Remove the BOT_TAG_BOT variant when the change arrives in stable - match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=.{0,40}(\i\.\i\.Messages)\.(?:APP_TAG|BOT_TAG_BOT)/, + match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=.{0,40}(\i\.\i\.Messages)\.APP_TAG/, replace: (_, origSwitch, variant, tags, displayedText, strings) => `${origSwitch}default:{${displayedText} = $self.getTagText(${tags}[${variant}], ${strings})}` }, @@ -322,20 +321,19 @@ export default definePlugin({ isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]), - // FIXME: Remove the BOT_TAG_BOT variants from strings when the change arrives in stable getTagText(passedTagName: string, strings: Record) { - if (!passedTagName) return strings.APP_TAG ?? strings.BOT_TAG_BOT; + if (!passedTagName) return strings.APP_TAG; const [tagName, variant] = passedTagName.split("-"); const tag = tags.find(({ name }) => tagName === name); - if (!tag) return strings.APP_TAG ?? strings.BOT_TAG_BOT; - if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.APP_TAG ?? strings.BOT_TAG_BOT; + if (!tag) return strings.APP_TAG; + if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.APP_TAG; const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; switch (variant) { case "OP": return `${strings.BOT_TAG_FORUM_ORIGINAL_POSTER} • ${tagText}`; case "BOT": - return `${strings.APP_TAG ?? strings.BOT_TAG_BOT} • ${tagText}`; + return `${strings.APP_TAG} • ${tagText}`; default: return tagText; } From 03d7e0fb93a32c2ee6984cfdb7e2d5ea3f4de127 Mon Sep 17 00:00:00 2001 From: dolfies Date: Fri, 3 May 2024 09:09:54 -0400 Subject: [PATCH 033/134] fix sort conflict of ImplicitRelationships & SortFriendRequests (#2408) --- src/plugins/implicitRelationships/index.ts | 8 ++++---- src/plugins/sortFriendRequests/index.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index be17e0fe4..15165d64a 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -81,8 +81,8 @@ export default definePlugin({ find: "getRelationshipCounts(){", replacement: { predicate: () => Settings.plugins.ImplicitRelationships.sortByAffinity, - match: /\.sortBy\(\i=>\i\.comparator\)/, - replace: "$&.sortBy((row) => $self.sortList(row))" + match: /\}\)\.sortBy\((.+?)\)\.value\(\)/, + replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()" } }, @@ -120,10 +120,10 @@ export default definePlugin({ } ), - sortList(row: any) { + wrapSort(comparator: Function, row: any) { return row.type === 5 ? -UserAffinitiesStore.getUserAffinity(row.user.id)?.affinity ?? 0 - : row.comparator; + : comparator(row); }, async fetchImplicitRelationships() { diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index 32579a803..7033591bd 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -41,8 +41,8 @@ export default definePlugin({ patches: [{ find: "getRelationshipCounts(){", replacement: { - match: /\.sortBy\(\i=>\i\.comparator\)/, - replace: "$&.sortBy((row) => $self.sortList(row))" + match: /\}\)\.sortBy\((.+?)\)\.value\(\)/, + replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()" } }, { find: ".Messages.FRIEND_REQUEST_CANCEL", @@ -53,10 +53,10 @@ export default definePlugin({ } }], - sortList(row: any) { + wrapSort(comparator: Function, row: any) { return row.type === 3 || row.type === 4 ? -this.getSince(row.user) - : row.comparator; + : comparator(row); }, getSince(user: User) { From 315f4f4e587f1d15f69b94c0d1b89b42f43c5eaf Mon Sep 17 00:00:00 2001 From: Sqaaakoi Date: Sat, 4 May 2024 01:17:12 +1200 Subject: [PATCH 034/134] ReviewDB: add more context menu shortcuts to view reviews (#2382) Co-authored-by: V --- src/plugins/reviewDB/index.tsx | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index 0c3578b07..bcd0f163f 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -35,13 +35,25 @@ import { getCurrentUserInfo, readNotification } from "./reviewDbApi"; import { settings } from "./settings"; import { showToast } from "./utils"; -const guildPopoutPatch: NavContextMenuPatchCallback = (children, props: { guild: Guild, onClose(): void; }) => { +const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => { children.push( openReviewsModal(props.guild.id, props.guild.name)} + action={() => openReviewsModal(guild.id, guild.name)} + /> + ); +}; + +const userContextPatch: NavContextMenuPatchCallback = (children, { user }: { user?: User, onClose(): void; }) => { + if (!user) return; + children.push( + openReviewsModal(user.id, user.username)} /> ); }; @@ -53,7 +65,10 @@ export default definePlugin({ settings, contextMenus: { - "guild-header-popout": guildPopoutPatch + "guild-header-popout": guildPopoutPatch, + "guild-context": guildPopoutPatch, + "user-context": userContextPatch, + "user-profile-actions": userContextPatch }, patches: [ From 1af44b25f3fa3c6be7ddf66eea82c1adbc087a5a Mon Sep 17 00:00:00 2001 From: katlyn <17418611+katlyn@users.noreply.github.com> Date: Fri, 3 May 2024 06:51:53 -0800 Subject: [PATCH 035/134] feat(USRBG): update to new API (#2388) --- src/plugins/usrbg/index.tsx | 41 +++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/plugins/usrbg/index.tsx b/src/plugins/usrbg/index.tsx index ce6bd709b..b92839a9a 100644 --- a/src/plugins/usrbg/index.tsx +++ b/src/plugins/usrbg/index.tsx @@ -24,9 +24,14 @@ import definePlugin, { OptionType } from "@utils/types"; import style from "./index.css?managed"; -const BASE_URL = "https://raw.githubusercontent.com/AutumnVN/usrbg/main/usrbg.json"; +const API_URL = "https://usrbg.is-hardly.online/users"; -let data = {} as Record; +interface UsrbgApiReturn { + endpoint: string + bucket: string + prefix: string + users: Record +} const settings = definePluginSettings({ nitroFirst: { @@ -48,7 +53,7 @@ const settings = definePluginSettings({ export default definePlugin({ name: "USRBG", description: "Displays user banners from USRBG, allowing anyone to get a banner without Nitro", - authors: [Devs.AutumnVN, Devs.pylix, Devs.TheKodeToad], + authors: [Devs.AutumnVN, Devs.katlyn, Devs.pylix, Devs.TheKodeToad], settings, patches: [ { @@ -80,8 +85,7 @@ export default definePlugin({ } ], - - data, + data: null as UsrbgApiReturn | null, settingsAboutComponent: () => { return ( @@ -91,9 +95,9 @@ export default definePlugin({ voiceBackgroundHook({ className, participantUserId }: any) { if (className.includes("tile_")) { - if (data[participantUserId]) { + if (this.userHasBackground(participantUserId)) { return { - backgroundImage: `url(${data[participantUserId]})`, + backgroundImage: `url(${this.getImageUrl(participantUserId)})`, backgroundSize: "cover", backgroundPosition: "center", backgroundRepeat: "no-repeat" @@ -104,24 +108,35 @@ export default definePlugin({ useBannerHook({ displayProfile, user }: any) { if (displayProfile?.banner && settings.store.nitroFirst) return; - if (data[user.id]) return data[user.id]; + if (this.userHasBackground(user.id)) return this.getImageUrl(user.id); }, premiumHook({ userId }: any) { - if (data[userId]) return 2; + if (this.userHasBackground(userId)) return 2; }, shouldShowBadge({ displayProfile, user }: any) { - return displayProfile?.banner && (!data[user.id] || settings.store.nitroFirst); + return displayProfile?.banner && (!this.userHasBackground(user.id) || settings.store.nitroFirst); + }, + + userHasBackground(userId: string) { + return !!this.data?.users[userId]; + }, + + getImageUrl(userId: string): string|null { + if (!this.userHasBackground(userId)) return null; + + // We can assert that data exists because userHasBackground returned true + const { endpoint, bucket, prefix, users: { [userId]: etag } } = this.data!; + return `${endpoint}/${bucket}/${prefix}${userId}?${etag}`; }, async start() { enableStyle(style); - const res = await fetch(BASE_URL); + const res = await fetch(API_URL); if (res.ok) { - data = await res.json(); - this.data = data; + this.data = await res.json(); } } }); From 78183eb226c360dbdd978c32ea08ccc9ac38f475 Mon Sep 17 00:00:00 2001 From: sunnie <78964224+sunnniee@users.noreply.github.com> Date: Fri, 3 May 2024 23:00:42 +0300 Subject: [PATCH 036/134] MsgClickActions: control ping via shift & NoReplyMention plugin (#2390) Co-authored-by: V --- src/plugins/messageClickActions/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 3d4bb21bb..14899c367 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -17,7 +17,7 @@ */ import { addClickListener, removeClickListener } from "@api/MessageEvents"; -import { definePluginSettings, Settings } from "@api/Settings"; +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; @@ -84,11 +84,17 @@ export default definePlugin({ const EPHEMERAL = 64; if (msg.hasFlag(EPHEMERAL)) return; + const isShiftPress = event.shiftKey && !settings.store.requireModifier; + const NoReplyMention = Vencord.Plugins.plugins.NoReplyMention as any as typeof import("../noReplyMention").default; + const shouldMention = Vencord.Plugins.isPluginEnabled("NoReplyMention") + ? NoReplyMention.shouldMention(msg, isShiftPress) + : !isShiftPress; + FluxDispatcher.dispatch({ type: "CREATE_PENDING_REPLY", channel, message: msg, - shouldMention: !Settings.plugins.NoReplyMention.enabled, + shouldMention, showMentionToggle: channel.guild_id !== null }); } From 520e9151681db577007ab8a5b6a1ecb5b9aae7b8 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 3 May 2024 22:18:31 +0200 Subject: [PATCH 037/134] fix badges with custom component --- src/plugins/_api/badges.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/_api/badges.tsx b/src/plugins/_api/badges.tsx index 6cbe1feb0..3cfbb4d99 100644 --- a/src/plugins/_api/badges.tsx +++ b/src/plugins/_api/badges.tsx @@ -78,7 +78,7 @@ export default definePlugin({ }, // replace their component with ours if applicable { - match: /(?<=text:(\i)\.description,spacing:12,)children:/, + match: /(?<=text:(\i)\.description,spacing:12,.{0,50})children:/, replace: "children:$1.component ? () => $self.renderBadgeComponent($1) :" }, // conditionally override their onClick with badge.onClick if it exists From 0350db76908d847d14a863fbd7bdf8f282cf6395 Mon Sep 17 00:00:00 2001 From: Kyuuhachi <1547062+Kyuuhachi@users.noreply.github.com> Date: Fri, 3 May 2024 22:42:14 +0200 Subject: [PATCH 038/134] feat(plugin): ImageLink (#2297) --- src/plugins/imageLink/README.md | 3 +++ src/plugins/imageLink/index.ts | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/plugins/imageLink/README.md create mode 100644 src/plugins/imageLink/index.ts diff --git a/src/plugins/imageLink/README.md b/src/plugins/imageLink/README.md new file mode 100644 index 000000000..add657948 --- /dev/null +++ b/src/plugins/imageLink/README.md @@ -0,0 +1,3 @@ +# ImageLink + +If a message consists of only a link to an image, Discord hides the link and shows only the image embed. This plugin makes the link show regardless. diff --git a/src/plugins/imageLink/index.ts b/src/plugins/imageLink/index.ts new file mode 100644 index 000000000..73a977fa9 --- /dev/null +++ b/src/plugins/imageLink/index.ts @@ -0,0 +1,24 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +export default definePlugin({ + name: "ImageLink", + description: "Never hide image links in messages, even if it's the only content", + authors: [Devs.Kyuuhachi], + + patches: [ + { + find: "isEmbedInline:function()", + replacement: { + match: /(?<=isEmbedInline:function\(\)\{return )\i(?=\})/, + replace: "()=>false", + }, + }, + ], +}); From 1ef87361f2f4c9117c45aab321a8c8c236e4f10d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 18:47:15 -0300 Subject: [PATCH 039/134] Test Patches: Faster chromium setup; Update action versions (#2412) --- .github/workflows/reportBrokenPlugins.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/reportBrokenPlugins.yml b/.github/workflows/reportBrokenPlugins.yml index 4b09463e0..12cbb0770 100644 --- a/.github/workflows/reportBrokenPlugins.yml +++ b/.github/workflows/reportBrokenPlugins.yml @@ -11,20 +11,20 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: ${{ github.event_name == 'schedule' }} with: ref: dev - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: ${{ github.event_name == 'workflow_dispatch' }} - - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json + - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 19 - uses: actions/setup-node@v3 + - name: Use Node.js 18 + uses: actions/setup-node@v4 with: - node-version: 19 + node-version: 18 cache: "pnpm" - name: Install dependencies @@ -32,7 +32,11 @@ jobs: pnpm install --frozen-lockfile pnpm add puppeteer - sudo apt-get install -y chromium-browser + - name: Install Google Chrome + id: setup-chrome + uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2 + with: + chrome-version: stable - name: Build web run: pnpm buildWeb --standalone --dev @@ -41,7 +45,7 @@ jobs: timeout-minutes: 10 run: | export PATH="$PWD/node_modules/.bin:$PATH" - export CHROMIUM_BIN=$(which chromium-browser) + export CHROMIUM_BIN=${{ steps.setup-chrome.outputs.chrome-path }} esbuild scripts/generateReport.ts > dist/report.mjs node dist/report.mjs >> $GITHUB_STEP_SUMMARY @@ -54,7 +58,7 @@ jobs: if: success() || failure() # even run if previous one failed run: | export PATH="$PWD/node_modules/.bin:$PATH" - export CHROMIUM_BIN=$(which chromium-browser) + export CHROMIUM_BIN=${{ steps.setup-chrome.outputs.chrome-path }} export USE_CANARY=true esbuild scripts/generateReport.ts > dist/report.mjs From 54bb7b96e90ebaee308aebe578122591a27f0727 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 18:58:56 -0300 Subject: [PATCH 040/134] Test Patches: Remove pnpm add puppeteer as it's already in deps --- .github/workflows/reportBrokenPlugins.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/reportBrokenPlugins.yml b/.github/workflows/reportBrokenPlugins.yml index 12cbb0770..39d639988 100644 --- a/.github/workflows/reportBrokenPlugins.yml +++ b/.github/workflows/reportBrokenPlugins.yml @@ -30,7 +30,6 @@ jobs: - name: Install dependencies run: | pnpm install --frozen-lockfile - pnpm add puppeteer - name: Install Google Chrome id: setup-chrome From a98f12bd1eabd0746834225c4ba3e6c755fe5fd1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 19:07:43 -0300 Subject: [PATCH 041/134] SecretRingToneEnabler: Fix patch --- src/plugins/secretRingTone/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/secretRingTone/index.ts b/src/plugins/secretRingTone/index.ts index 8f0176f88..9c3956a80 100644 --- a/src/plugins/secretRingTone/index.ts +++ b/src/plugins/secretRingTone/index.ts @@ -14,10 +14,11 @@ export default definePlugin({ authors: [Devs.AndrewDLO, Devs.FieryFlames], patches: [ { - find: "call_ringing_beat\"", + find: '"call_ringing_beat"', replacement: { - match: /500===\i\(\)\.random\(1,1e3\)/, - replace: "true" + // FIXME Remove === alternative when it hits stable + match: /500(!==|===)\i\(\)\.random\(1,1e3\)/, + replace: (_, predicate) => predicate === "!==" ? "false" : "true", } }, ], From a6c09bc9099832c88a83939bee776fc7d21f1f06 Mon Sep 17 00:00:00 2001 From: dolfies Date: Fri, 3 May 2024 18:21:02 -0400 Subject: [PATCH 042/134] feat(ValidUser): also display badges & banner (#2235) Co-authored-by: V --- src/plugins/validUser/index.tsx | 72 +++++++++++++++++++++++++++++++-- src/webpack/common/utils.ts | 3 +- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index 2fce693e8..7a21ac86b 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -21,12 +21,37 @@ import { Devs } from "@utils/constants"; import { sleep } from "@utils/misc"; import { Queue } from "@utils/Queue"; import definePlugin from "@utils/types"; -import { UserStore, UserUtils, useState } from "@webpack/common"; +import { Constants, FluxDispatcher, RestAPI, UserProfileStore, UserStore, useState } from "@webpack/common"; import type { ComponentType, ReactNode } from "react"; +// LYING to the type checker here +const UserFlags = Constants.UserFlags as Record; +const badges: Record = { + "active_developer": { id: "active_developer", description: "Active Developer", icon: "6bdc42827a38498929a4920da12695d9", link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447" }, + "bug_hunter_level_1": { id: "bug_hunter_level_1", description: "Discord Bug Hunter", icon: "2717692c7dca7289b35297368a940dd0", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, + "bug_hunter_level_2": { id: "bug_hunter_level_2", description: "Discord Bug Hunter", icon: "848f79194d4be5ff5f81505cbd0ce1e6", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, + "certified_moderator": { id: "certified_moderator", description: "Moderator Programs Alumni", icon: "fee1624003e2fee35cb398e125dc479b", link: "https://discord.com/safety" }, + "discord_employee": { id: "staff", description: "Discord Staff", icon: "5e74e9b61934fc1f67c65515d1f7e60d", link: "https://discord.com/company" }, + "hypesquad": { id: "hypesquad", description: "HypeSquad Events", icon: "bf01d1073931f921909045f3a39fd264", link: "https://discord.com/hypesquad" }, + "hypesquad_online_house_1": { id: "hypesquad_house_1", description: "HypeSquad Bravery", icon: "8a88d63823d8a71cd5e390baa45efa02", link: "https://discord.com/settings/hypesquad-online" }, + "hypesquad_online_house_2": { id: "hypesquad_house_2", description: "HypeSquad Brilliance", icon: "011940fd013da3f7fb926e4a1cd2e618", link: "https://discord.com/settings/hypesquad-online" }, + "hypesquad_online_house_3": { id: "hypesquad_house_3", description: "HypeSquad Balance", icon: "3aa41de486fa12454c3761e8e223442e", link: "https://discord.com/settings/hypesquad-online" }, + "partner": { id: "partner", description: "Partnered Server Owner", icon: "3f9748e53446a137a052f3454e2de41e", link: "https://discord.com/partners" }, + "premium": { id: "premium", description: "Subscriber", icon: "2ba85e8026a8614b640c2837bcdfe21b", link: "https://discord.com/settings/premium" }, + "premium_early_supporter": { id: "early_supporter", description: "Early Supporter", icon: "7060786766c9c840eb3019e725d2b358", link: "https://discord.com/settings/premium" }, + "verified_developer": { id: "verified_developer", description: "Early Verified Bot Developer", icon: "6df5892e0f35b051f8b61eace34f4967" }, +}; + const fetching = new Set(); const queue = new Queue(5); +interface ProfileBadge { + id: string; + description: string; + icon: string; + link?: string; +} + interface MentionProps { data: { userId?: string; @@ -43,6 +68,45 @@ interface MentionProps { UserMention: ComponentType; } +async function getUser(id: string) { + let userObj = UserStore.getUser(id); + if (userObj) + return userObj; + + const user: any = await RestAPI.get({ url: `/users/${id}` }).then(response => { + FluxDispatcher.dispatch({ + type: "USER_UPDATE", + user: response.body, + }); + + return response.body; + }); + + // Populate the profile + await FluxDispatcher.dispatch( + { + type: "USER_PROFILE_FETCH_FAILURE", + userId: id, + } + ); + + userObj = UserStore.getUser(id); + const fakeBadges: ProfileBadge[] = Object.entries(UserFlags) + .filter(([_, flag]) => !isNaN(flag) && userObj.hasFlag(flag)) + .map(([key]) => badges[key.toLowerCase()]); + if (user.premium_type || !user.bot && (user.banner || user.avatar?.startsWith?.("a_"))) + fakeBadges.push(badges.premium); + + // Fill in what we can deduce + const profile = UserProfileStore.getUserProfile(id); + profile.accentColor = user.accent_color; + profile.badges = fakeBadges; + profile.banner = user.banner; + profile.premiumType = user.premium_type; + + return userObj; +} + function MentionWrapper({ data, UserMention, RoleMention, parse, props }: MentionProps) { const [userId, setUserId] = useState(data.userId); @@ -85,14 +149,14 @@ function MentionWrapper({ data, UserMention, RoleMention, parse, props }: Mentio fetching.add(id); queue.unshift(() => - UserUtils.getUser(id) + getUser(id) .then(() => { setUserId(id); fetching.delete(id); }) .catch(e => { if (e?.status === 429) { - queue.unshift(() => sleep(1000).then(fetch)); + queue.unshift(() => sleep(e?.body?.retry_after ?? 1000).then(fetch)); fetching.delete(id); } }) @@ -112,7 +176,7 @@ function MentionWrapper({ data, UserMention, RoleMention, parse, props }: Mentio export default definePlugin({ name: "ValidUser", description: "Fix mentions for unknown users showing up as '@unknown-user' (hover over a mention to fix it)", - authors: [Devs.Ven], + authors: [Devs.Ven, Devs.Dolfies], tags: ["MentionCacheFix"], patches: [ diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index f5d30cd76..6d74e9b25 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -23,7 +23,6 @@ import { _resolveReady, filters, findByCodeLazy, findByProps, findByPropsLazy, f import type * as t from "./types/utils"; export let FluxDispatcher: t.FluxDispatcher; - waitFor(["dispatch", "subscribe"], m => { FluxDispatcher = m; // Non import call to avoid circular dependency @@ -40,6 +39,8 @@ export let ComponentDispatch; waitFor(["ComponentDispatch", "ComponentDispatcher"], m => ComponentDispatch = m.ComponentDispatch); +export const Constants = findByPropsLazy("Endpoints"); + export const RestAPI: t.RestAPI = proxyLazyWebpack(() => { const mod = findByProps("getAPIBaseURL"); return mod.HTTP ?? mod; From 04d7cb8797b3f15a97228c7b9f051cd7788aeb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ruiz=20P=C3=A9rez?= <57387907+GabiRP@users.noreply.github.com> Date: Sat, 4 May 2024 01:15:18 +0200 Subject: [PATCH 043/134] NewGuildSettings: add push notifs, highlights & events (#2413) Co-authored-by: V --- src/plugins/newGuildSettings/index.tsx | 34 +++++++++++++++++++++++--- src/utils/constants.ts | 4 +++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/plugins/newGuildSettings/index.tsx b/src/plugins/newGuildSettings/index.tsx index ff6f1c261..d5c3d9206 100644 --- a/src/plugins/newGuildSettings/index.tsx +++ b/src/plugins/newGuildSettings/index.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { definePluginSettings,migratePluginSettings } from "@api/Settings"; +import { definePluginSettings, migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; @@ -31,6 +31,16 @@ const settings = definePluginSettings({ type: OptionType.BOOLEAN, default: true }, + messages: { + description: "Server Notification Settings", + type: OptionType.SELECT, + options: [ + { label: "All messages", value: 0 }, + { label: "Only @mentions", value: 1 }, + { label: "Nothing", value: 2 }, + { label: "Server default", value: 3, default: true } + ], + }, everyone: { description: "Suppress @everyone and @here", type: OptionType.BOOLEAN, @@ -41,6 +51,16 @@ const settings = definePluginSettings({ type: OptionType.BOOLEAN, default: true }, + highlights: { + description: "Suppress Highlights automatically", + type: OptionType.BOOLEAN, + default: true + }, + events: { + description: "Mute New Events automatically", + type: OptionType.BOOLEAN, + default: true + }, showAllChannels: { description: "Show all channels automatically", type: OptionType.BOOLEAN, @@ -53,7 +73,7 @@ export default definePlugin({ name: "NewGuildSettings", description: "Automatically mute new servers and change various other settings upon joining", tags: ["MuteNewGuild", "mute", "server"], - authors: [Devs.Glitch, Devs.Nuckyz, Devs.carince, Devs.Mopi], + authors: [Devs.Glitch, Devs.Nuckyz, Devs.carince, Devs.Mopi, Devs.GabiRP], patches: [ { find: ",acceptInvite(", @@ -78,8 +98,16 @@ export default definePlugin({ { muted: settings.store.guild, suppress_everyone: settings.store.everyone, - suppress_roles: settings.store.role + suppress_roles: settings.store.role, + mute_scheduled_events: settings.store.events, + notify_highlights: settings.store.highlights ? 1 : 0 }); + if (settings.store.messages !== 3) { + updateGuildNotificationSettings(guildId, + { + message_notifications: settings.store.messages, + }); + } if (settings.store.showAllChannels && isOptInEnabledForGuild(guildId)) { toggleShowAllChannels(guildId); } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 8ab0bffb3..cce276ef8 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -449,6 +449,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ PolisanTheEasyNick: { name: "Oleh Polisan", id: 242305263313485825n + }, + GabiRP: { + name: "GabiRP", + id: 507955112027750401n } } satisfies Record); From dfb06e47d01e148646f682734b560ec4d7df34a8 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sat, 4 May 2024 01:39:20 +0200 Subject: [PATCH 044/134] fix overflow when having two rows of badges --- src/plugins/_api/badges/fixBadgeOverflow.css | 3 +++ src/plugins/_api/{badges.tsx => badges/index.tsx} | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 src/plugins/_api/badges/fixBadgeOverflow.css rename src/plugins/_api/{badges.tsx => badges/index.tsx} (99%) diff --git a/src/plugins/_api/badges/fixBadgeOverflow.css b/src/plugins/_api/badges/fixBadgeOverflow.css new file mode 100644 index 000000000..348d0ff38 --- /dev/null +++ b/src/plugins/_api/badges/fixBadgeOverflow.css @@ -0,0 +1,3 @@ +[class*="profileBadges"] { + flex: none; +} diff --git a/src/plugins/_api/badges.tsx b/src/plugins/_api/badges/index.tsx similarity index 99% rename from src/plugins/_api/badges.tsx rename to src/plugins/_api/badges/index.tsx index 3cfbb4d99..5493d4b6a 100644 --- a/src/plugins/_api/badges.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import "./fixBadgeOverflow.css"; + import { BadgePosition, BadgeUserArgs, ProfileBadge } from "@api/Badges"; import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; From 80b738ff3e9418aa950027a503aaa7672d83677b Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 21:15:14 -0300 Subject: [PATCH 045/134] Future proof FakeNitro and Experiments to not brick Discord startup --- src/plugins/experiments/index.tsx | 17 +++++++++--- src/plugins/fakeNitro/index.tsx | 44 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index 344638828..50b9521f9 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -20,10 +20,12 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { ErrorCard } from "@components/ErrorCard"; import { Devs } from "@utils/constants"; +import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { Forms, React } from "@webpack/common"; +import { Forms, React, UserStore } from "@webpack/common"; +import { User } from "discord-types/general"; const KbdStyles = findByPropsLazy("key", "removeBuildOverride"); @@ -68,8 +70,8 @@ export default definePlugin({ predicate: () => settings.store.enableIsStaff, replacement: [ { - match: /=>*?(\i)\.hasFlag\((\i\.\i)\.STAFF\)}/, - replace: (_, user, flags) => `=>Vencord.Webpack.Common.UserStore.getCurrentUser()?.id===${user}.id||${user}.hasFlag(${flags}.STAFF)}` + match: /(?<=>)(\i)\.hasFlag\((\i\.\i)\.STAFF\)(?=})/, + replace: (_, user, flags) => `$self.isStaff(${user},${flags})` }, { match: /hasFreePremium\(\){return this.isStaff\(\)\s*?\|\|/, @@ -86,6 +88,15 @@ export default definePlugin({ } ], + isStaff(user: User, flags: any) { + try { + return UserStore.getCurrentUser()?.id === user.id || user.hasFlag(flags.STAFF); + } catch (err) { + new Logger("Experiments").error(err); + return user.hasFlag(flags.STAFF); + } + }, + settingsAboutComponent: () => { const isMacOS = navigator.platform.includes("Mac"); const modKey = isMacOS ? "cmd" : "ctrl"; diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index adf1f70fb..90ce10f62 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -413,31 +413,35 @@ export default definePlugin({ }, handleProtoChange(proto: any, user: any) { - if (proto == null || typeof proto === "string" || !UserSettingsProtoStore || !PreloadedUserSettingsActionCreators || !AppearanceSettingsActionCreators || !ClientThemeSettingsActionsCreators) return; + try { + if (proto == null || typeof proto === "string") return; - const premiumType: number = user?.premium_type ?? UserStore?.getCurrentUser()?.premiumType ?? 0; + const premiumType: number = user?.premium_type ?? UserStore?.getCurrentUser()?.premiumType ?? 0; - if (premiumType !== 2) { - proto.appearance ??= AppearanceSettingsActionCreators.create(); + if (premiumType !== 2) { + proto.appearance ??= AppearanceSettingsActionCreators.create(); - if (UserSettingsProtoStore.settings.appearance?.theme != null) { - const appearanceSettingsDummy = AppearanceSettingsActionCreators.create({ - theme: UserSettingsProtoStore.settings.appearance.theme - }); + if (UserSettingsProtoStore.settings.appearance?.theme != null) { + const appearanceSettingsDummy = AppearanceSettingsActionCreators.create({ + theme: UserSettingsProtoStore.settings.appearance.theme + }); - proto.appearance.theme = appearanceSettingsDummy.theme; - } - - if (UserSettingsProtoStore.settings.appearance?.clientThemeSettings?.backgroundGradientPresetId?.value != null) { - const clientThemeSettingsDummy = ClientThemeSettingsActionsCreators.create({ - backgroundGradientPresetId: { - value: UserSettingsProtoStore.settings.appearance.clientThemeSettings.backgroundGradientPresetId.value - } - }); - - proto.appearance.clientThemeSettings ??= clientThemeSettingsDummy; - proto.appearance.clientThemeSettings.backgroundGradientPresetId = clientThemeSettingsDummy.backgroundGradientPresetId; + proto.appearance.theme = appearanceSettingsDummy.theme; + } + + if (UserSettingsProtoStore.settings.appearance?.clientThemeSettings?.backgroundGradientPresetId?.value != null) { + const clientThemeSettingsDummy = ClientThemeSettingsActionsCreators.create({ + backgroundGradientPresetId: { + value: UserSettingsProtoStore.settings.appearance.clientThemeSettings.backgroundGradientPresetId.value + } + }); + + proto.appearance.clientThemeSettings ??= clientThemeSettingsDummy; + proto.appearance.clientThemeSettings.backgroundGradientPresetId = clientThemeSettingsDummy.backgroundGradientPresetId; + } } + } catch (err) { + new Logger("FakeNitro").error(err); } }, From a525cd0113b37fbe08512a6e68ecb62b8d74cd72 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 5 May 2024 03:59:57 +0200 Subject: [PATCH 046/134] bump to v1.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1a0a43227..ae4336d36 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.0", + "version": "1.8.1", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 066b872219e247bf6624d07386ada0791c336dbb Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 5 May 2024 18:56:49 +0200 Subject: [PATCH 047/134] fix webpack patch on client using discordapp.com --- src/webpack/patchWebpack.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index d2b569e8d..8dd3dba8b 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -63,7 +63,8 @@ Object.defineProperty(Function.prototype, "O", { // When using react devtools or other extensions, or even when discord loads the sentry, we may also catch their webpack here. // This ensures we actually got the right one // this.e (wreq.e) is the method for loading a chunk, and only the main webpack has it - if (new Error().stack?.includes("discord.com") && String(this.e).includes("Promise.all")) { + const { stack } = new Error(); + if ((stack?.includes("discord.com") || stack?.includes("discordapp.com")) && String(this.e).includes("Promise.all")) { logger.info("Found main WebpackRequire.onChunksLoaded"); delete (Function.prototype as any).O; From ce18000c4e403d2408ecf882568ffea90442336d Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 5 May 2024 18:58:23 +0200 Subject: [PATCH 048/134] fix webpack patch on client using discordapp.com part 2 --- src/webpack/patchWebpack.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 8dd3dba8b..d3de20727 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -121,9 +121,9 @@ Object.defineProperty(Function.prototype, "m", { set(v: any) { // When using react devtools or other extensions, we may also catch their webpack here. // This ensures we actually got the right one - const error = new Error(); - if (error.stack?.includes("discord.com")) { - logger.info("Found Webpack module factory", error.stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? ""); + const { stack } = new Error(); + if (stack?.includes("discord.com") || stack?.includes("discordapp.com")) { + logger.info("Found Webpack module factory", stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? ""); patchFactories(v); } From 60e6fdacfa2b07d27b69b9a0ab52a5e5ccfa689b Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 23:15:33 -0300 Subject: [PATCH 049/134] Resolve PluginSettings circular deps better --- src/components/PluginSettings/index.tsx | 5 +++-- src/plugins/_api/badges/index.tsx | 8 ++------ src/plugins/_core/settings.tsx | 23 +++++++++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 33a472c1a..e6b2cf1fb 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -27,6 +27,7 @@ import PluginModal from "@components/PluginSettings/PluginModal"; import { AddonCard } from "@components/VencordSettings/AddonCard"; import { SettingsTab } from "@components/VencordSettings/shared"; import { ChangeList } from "@utils/ChangeList"; +import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { classes, isObjectEmpty } from "@utils/misc"; @@ -38,8 +39,8 @@ import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextI import Plugins from "~plugins"; -import { startDependenciesRecursive, startPlugin, stopPlugin } from "../../plugins"; - +// Avoid circular dependency +const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins")); const cl = classNameFactory("vc-plugins-"); const logger = new Logger("PluginSettings", "#a6d189"); diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index 5493d4b6a..bbccf0a11 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -23,6 +23,7 @@ import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Heart } from "@components/Heart"; +import { openContributorModal } from "@components/PluginSettings/ContributorModal"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import { isPluginDev } from "@utils/misc"; @@ -37,12 +38,7 @@ const ContributorBadge: ProfileBadge = { image: CONTRIBUTOR_BADGE, position: BadgePosition.START, shouldShow: ({ user }) => isPluginDev(user.id), - onClick(_, { user }) { - // circular import shenanigans - const { openContributorModal } = require("@components/PluginSettings/ContributorModal") as typeof import("@components/PluginSettings/ContributorModal"); - // setImmediate is needed to run on later tick to workaround limitation in proxyLazy - setImmediate(() => openContributorModal(user)); - } + onClick: (_, { user }) => openContributorModal(user) }; let DonorBadges = {} as Record>>; diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 1aea0d6ee..772ee9b64 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -17,6 +17,13 @@ */ import { Settings } from "@api/Settings"; +import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab"; +import CloudTab from "@components/VencordSettings/CloudTab"; +import PatchHelperTab from "@components/VencordSettings/PatchHelperTab"; +import PluginsTab from "@components/VencordSettings/PluginsTab"; +import ThemesTab from "@components/VencordSettings/ThemesTab"; +import UpdaterTab from "@components/VencordSettings/UpdaterTab"; +import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { React } from "@webpack/common"; @@ -36,7 +43,7 @@ export default definePlugin({ match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, replace: (m, component, props) => { props = props.replace(/children:\[.+\]/, ""); - return `${m},Vencord.Plugins.plugins.Settings.makeInfoElements(${component}, ${props})`; + return `${m},$self.makeInfoElements(${component}, ${props})`; } } ] @@ -77,43 +84,43 @@ export default definePlugin({ { section: "VencordSettings", label: "Vencord", - element: require("@components/VencordSettings/VencordTab").default, + element: VencordTab, className: "vc-settings" }, { section: "VencordPlugins", label: "Plugins", - element: require("@components/VencordSettings/PluginsTab").default, + element: PluginsTab, className: "vc-plugins" }, { section: "VencordThemes", label: "Themes", - element: require("@components/VencordSettings/ThemesTab").default, + element: ThemesTab, className: "vc-themes" }, !IS_UPDATER_DISABLED && { section: "VencordUpdater", label: "Updater", - element: require("@components/VencordSettings/UpdaterTab").default, + element: UpdaterTab, className: "vc-updater" }, { section: "VencordCloud", label: "Cloud", - element: require("@components/VencordSettings/CloudTab").default, + element: CloudTab, className: "vc-cloud" }, { section: "VencordSettingsSync", label: "Backup & Restore", - element: require("@components/VencordSettings/BackupAndRestoreTab").default, + element: BackupAndRestoreTab, className: "vc-backup-restore" }, IS_DEV && { section: "VencordPatchHelper", label: "Patch Helper", - element: require("@components/VencordSettings/PatchHelperTab").default, + element: PatchHelperTab, className: "vc-patch-helper" }, ...this.customSections.map(func => func(SectionTypes)), From a090872d8f8b1ccb201b716bc657a90f745f132d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 23:15:46 -0300 Subject: [PATCH 050/134] ImplicitRelationships: Properly test find --- src/plugins/implicitRelationships/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 15165d64a..4faad2a9d 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -19,11 +19,12 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps, findStoreLazy } from "@webpack"; +import { findByPropsLazy, findStoreLazy } from "@webpack"; import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common"; import { Settings } from "Vencord"; const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore"); +const { FriendsSections } = findByPropsLazy("FriendsSections"); interface UserAffinity { user_id: string; @@ -181,7 +182,6 @@ export default definePlugin({ }, start() { - const { FriendsSections } = findByProps("FriendsSections"); FriendsSections.IMPLICIT = "IMPLICIT"; } }); From 45c1e42ce412bdf732b5f21073f6d4d8a00f3528 Mon Sep 17 00:00:00 2001 From: Fafa <87046111+Faf4a@users.noreply.github.com> Date: Sun, 5 May 2024 06:42:15 +0200 Subject: [PATCH 051/134] ReviewDB: Fix context menus being added to folders (#2416) --- src/plugins/reviewDB/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index bcd0f163f..e73bce82c 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -36,6 +36,7 @@ import { settings } from "./settings"; import { showToast } from "./utils"; const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => { + if (!guild) return; children.push( Date: Sun, 5 May 2024 20:15:01 +1200 Subject: [PATCH 052/134] ImageLink: Fix embed showing in gifs (#2417) --- src/plugins/imageLink/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/imageLink/index.ts b/src/plugins/imageLink/index.ts index 73a977fa9..5e8dd23e9 100644 --- a/src/plugins/imageLink/index.ts +++ b/src/plugins/imageLink/index.ts @@ -10,15 +10,15 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "ImageLink", description: "Never hide image links in messages, even if it's the only content", - authors: [Devs.Kyuuhachi], + authors: [Devs.Kyuuhachi, Devs.Sqaaakoi], patches: [ { - find: "isEmbedInline:function()", + find: "unknownUserMentionPlaceholder:", replacement: { - match: /(?<=isEmbedInline:function\(\)\{return )\i(?=\})/, - replace: "()=>false", - }, - }, - ], + match: /\(0,\i\.isEmbedInline\)\(\i\)/, + replace: "false", + } + } + ] }); From ecf6af5884981236ce8be4573e28629962edacc3 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 6 May 2024 05:07:46 -0300 Subject: [PATCH 053/134] FakeNitro: Make disableEmbedPermissionCheck setting not private --- src/plugins/fakeNitro/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 90ce10f62..ad7394dc9 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -166,10 +166,13 @@ const settings = definePluginSettings({ description: "What text the hyperlink should use. {{NAME}} will be replaced with the emoji/sticker name.", type: OptionType.STRING, default: "{{NAME}}" + }, + disableEmbedPermissionCheck: { + description: "Whether to disable the embed permission check when sending fake emojis and stickers", + type: OptionType.BOOLEAN, + default: false } -}).withPrivateSettings<{ - disableEmbedPermissionCheck: boolean; -}>(); +}); function hasPermission(channelId: string, permission: bigint) { const channel = ChannelStore.getChannel(channelId); From 72b17761bbae1823551664f8a72dd0e18aa463ae Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 7 May 2024 04:54:25 +0200 Subject: [PATCH 054/134] upgrade nodejs & pnpm to latest versions --- .github/workflows/build.yml | 10 +- .github/workflows/codeberg-mirror.yml | 2 +- .github/workflows/publish.yml | 8 +- .github/workflows/reportBrokenPlugins.yml | 6 +- .github/workflows/test.yml | 10 +- package.json | 2 +- pnpm-lock.yaml | 4435 +++++++++++---------- scripts/build/common.mjs | 5 +- tsconfig.json | 1 + 9 files changed, 2449 insertions(+), 2030 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ed7d5ca7..c7a2f24e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,14 +18,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json + - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 19 - uses: actions/setup-node@v3 + - name: Use Node.js 20 + uses: actions/setup-node@v4 with: - node-version: 19 + node-version: 20 cache: "pnpm" - name: Install dependencies diff --git a/.github/workflows/codeberg-mirror.yml b/.github/workflows/codeberg-mirror.yml index 1b2266ee7..5acae6a4f 100644 --- a/.github/workflows/codeberg-mirror.yml +++ b/.github/workflows/codeberg-mirror.yml @@ -13,7 +13,7 @@ jobs: if: github.repository == 'Vendicated/Vencord' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 83236c11e..8407e08e2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: check that tag matches package.json version run: | @@ -20,12 +20,12 @@ jobs: exit 1 fi - - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json + - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - name: Use Node.js 19 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 19 + node-version: 20 cache: "pnpm" - name: Install dependencies diff --git a/.github/workflows/reportBrokenPlugins.yml b/.github/workflows/reportBrokenPlugins.yml index 39d639988..d3a882fa3 100644 --- a/.github/workflows/reportBrokenPlugins.yml +++ b/.github/workflows/reportBrokenPlugins.yml @@ -21,10 +21,10 @@ jobs: - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 18 + - name: Use Node.js 20 uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: "pnpm" - name: Install dependencies @@ -35,7 +35,7 @@ jobs: id: setup-chrome uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2 with: - chrome-version: stable + chrome-version: stable - name: Build web run: pnpm buildWeb --standalone --dev diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4746d673..7a2b320bf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,13 +10,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json - - name: Use Node.js 18 - uses: actions/setup-node@v3 + - name: Use Node.js 20 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: "pnpm" - name: Install dependencies diff --git a/package.json b/package.json index ae4336d36..97d3da576 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "zip-local": "^0.3.5", "zustand": "^3.7.2" }, - "packageManager": "pnpm@8.10.2", + "packageManager": "pnpm@9.1.0", "pnpm": { "patchedDependencies": { "eslint-plugin-path-alias@1.0.0": "patches/eslint-plugin-path-alias@1.0.0.patch", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43866f50b..54b3ab8da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false patchedDependencies: eslint-plugin-path-alias@1.0.0: @@ -8,421 +12,318 @@ patchedDependencies: hash: xm46kqcmdgzlmm4aifkfpxaho4 path: patches/eslint@8.46.0.patch -dependencies: - '@sapphi-red/web-noise-suppressor': - specifier: 0.3.3 - version: 0.3.3 - '@vap/core': - specifier: 0.0.12 - version: 0.0.12 - '@vap/shiki': - specifier: 0.10.5 - version: 0.10.5 - eslint-plugin-simple-header: - specifier: ^1.0.2 - version: 1.0.2 - fflate: - specifier: ^0.7.4 - version: 0.7.4 - gifenc: - specifier: github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3 - version: github.com/mattdesl/gifenc/64842fca317b112a8590f8fef2bf3825da8f6fe3 - monaco-editor: - specifier: ^0.43.0 - version: 0.43.0 - nanoid: - specifier: ^4.0.2 - version: 4.0.2 - virtual-merge: - specifier: ^1.0.1 - version: 1.0.1 +importers: -devDependencies: - '@types/chrome': - specifier: ^0.0.246 - version: 0.0.246 - '@types/diff': - specifier: ^5.0.3 - version: 5.0.3 - '@types/lodash': - specifier: ^4.14.194 - version: 4.14.194 - '@types/node': - specifier: ^18.16.3 - version: 18.16.3 - '@types/react': - specifier: ^18.2.0 - version: 18.2.0 - '@types/react-dom': - specifier: ^18.2.1 - version: 18.2.1 - '@types/yazl': - specifier: ^2.4.2 - version: 2.4.2 - '@typescript-eslint/eslint-plugin': - specifier: ^5.59.1 - version: 5.59.1(@typescript-eslint/parser@5.59.1)(eslint@8.46.0)(typescript@5.0.4) - '@typescript-eslint/parser': - specifier: ^5.59.1 - version: 5.59.1(eslint@8.46.0)(typescript@5.0.4) - diff: - specifier: ^5.1.0 - version: 5.1.0 - discord-types: - specifier: ^1.3.26 - version: 1.3.26 - esbuild: - specifier: ^0.15.18 - version: 0.15.18 - eslint: - specifier: ^8.46.0 - version: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) - eslint-import-resolver-alias: - specifier: ^1.1.2 - version: 1.1.2 - eslint-plugin-path-alias: - specifier: ^1.0.0 - version: 1.0.0(patch_hash=m6sma4g6bh67km3q6igf6uxaja)(eslint@8.46.0) - eslint-plugin-simple-import-sort: - specifier: ^10.0.0 - version: 10.0.0(eslint@8.46.0) - eslint-plugin-unused-imports: - specifier: ^2.0.0 - version: 2.0.0(@typescript-eslint/eslint-plugin@5.59.1)(eslint@8.46.0) - highlight.js: - specifier: 10.6.0 - version: 10.6.0 - moment: - specifier: ^2.29.4 - version: 2.29.4 - puppeteer-core: - specifier: ^19.11.1 - version: 19.11.1(typescript@5.0.4) - standalone-electron-types: - specifier: ^1.0.0 - version: 1.0.0 - stylelint: - specifier: ^15.6.0 - version: 15.6.0 - stylelint-config-standard: - specifier: ^33.0.0 - version: 33.0.0(stylelint@15.6.0) - tsx: - specifier: ^3.12.7 - version: 3.12.7 - type-fest: - specifier: ^3.9.0 - version: 3.9.0 - typescript: - specifier: ^5.0.4 - version: 5.0.4 - zip-local: - specifier: ^0.3.5 - version: 0.3.5 - zustand: - specifier: ^3.7.2 - version: 3.7.2 + .: + dependencies: + '@sapphi-red/web-noise-suppressor': + specifier: 0.3.3 + version: 0.3.3 + '@vap/core': + specifier: 0.0.12 + version: 0.0.12 + '@vap/shiki': + specifier: 0.10.5 + version: 0.10.5 + eslint-plugin-simple-header: + specifier: ^1.0.2 + version: 1.0.2 + fflate: + specifier: ^0.7.4 + version: 0.7.4 + gifenc: + specifier: github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3 + version: https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3 + monaco-editor: + specifier: ^0.43.0 + version: 0.43.0 + nanoid: + specifier: ^4.0.2 + version: 4.0.2 + virtual-merge: + specifier: ^1.0.1 + version: 1.0.1 + devDependencies: + '@types/chrome': + specifier: ^0.0.246 + version: 0.0.246 + '@types/diff': + specifier: ^5.0.3 + version: 5.0.3 + '@types/lodash': + specifier: ^4.14.194 + version: 4.14.194 + '@types/node': + specifier: ^18.16.3 + version: 18.16.3 + '@types/react': + specifier: ^18.2.0 + version: 18.2.0 + '@types/react-dom': + specifier: ^18.2.1 + version: 18.2.1 + '@types/yazl': + specifier: ^2.4.2 + version: 2.4.2 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.1 + version: 5.59.1(@typescript-eslint/parser@5.59.1)(eslint@8.46.0)(typescript@5.0.4) + '@typescript-eslint/parser': + specifier: ^5.59.1 + version: 5.59.1(eslint@8.46.0)(typescript@5.0.4) + diff: + specifier: ^5.1.0 + version: 5.1.0 + discord-types: + specifier: ^1.3.26 + version: 1.3.26 + esbuild: + specifier: ^0.15.18 + version: 0.15.18 + eslint: + specifier: ^8.46.0 + version: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) + eslint-import-resolver-alias: + specifier: ^1.1.2 + version: 1.1.2 + eslint-plugin-path-alias: + specifier: ^1.0.0 + version: 1.0.0(patch_hash=m6sma4g6bh67km3q6igf6uxaja)(eslint@8.46.0) + eslint-plugin-simple-import-sort: + specifier: ^10.0.0 + version: 10.0.0(eslint@8.46.0) + eslint-plugin-unused-imports: + specifier: ^2.0.0 + version: 2.0.0(@typescript-eslint/eslint-plugin@5.59.1)(eslint@8.46.0) + highlight.js: + specifier: 10.6.0 + version: 10.6.0 + moment: + specifier: ^2.29.4 + version: 2.29.4 + puppeteer-core: + specifier: ^19.11.1 + version: 19.11.1(typescript@5.0.4) + standalone-electron-types: + specifier: ^1.0.0 + version: 1.0.0 + stylelint: + specifier: ^15.6.0 + version: 15.6.0 + stylelint-config-standard: + specifier: ^33.0.0 + version: 33.0.0(stylelint@15.6.0) + tsx: + specifier: ^3.12.7 + version: 3.12.7 + type-fest: + specifier: ^3.9.0 + version: 3.9.0 + typescript: + specifier: ^5.0.4 + version: 5.0.4 + zip-local: + specifier: ^0.3.5 + version: 0.3.5 + zustand: + specifier: ^3.7.2 + version: 3.7.2 packages: - /@aashutoshrathi/word-wrap@1.2.6: + '@aashutoshrathi/word-wrap@1.2.6': resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} - dev: true - /@babel/code-frame@7.21.4: + '@babel/code-frame@7.21.4': resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true - /@babel/helper-validator-identifier@7.19.1: + '@babel/helper-validator-identifier@7.19.1': resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} - dev: true - /@babel/highlight@7.18.6: + '@babel/highlight@7.18.6': resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@csstools/css-parser-algorithms@2.1.1(@csstools/css-tokenizer@2.1.1): + '@csstools/css-parser-algorithms@2.1.1': resolution: {integrity: sha512-viRnRh02AgO4mwIQb2xQNJju0i+Fh9roNgmbR5xEuG7J3TGgxjnE95HnBLgsFJOJOksvcfxOUCgODcft6Y07cA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: '@csstools/css-tokenizer': ^2.1.1 - dependencies: - '@csstools/css-tokenizer': 2.1.1 - dev: true - /@csstools/css-tokenizer@2.1.1: + '@csstools/css-tokenizer@2.1.1': resolution: {integrity: sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==} engines: {node: ^14 || ^16 || >=18} - dev: true - /@csstools/media-query-list-parser@2.0.4(@csstools/css-parser-algorithms@2.1.1)(@csstools/css-tokenizer@2.1.1): + '@csstools/media-query-list-parser@2.0.4': resolution: {integrity: sha512-GyYot6jHgcSDZZ+tLSnrzkR7aJhF2ZW6d+CXH66mjy5WpAQhZD4HDke2OQ36SivGRWlZJpAz7TzbW6OKlEpxAA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: '@csstools/css-parser-algorithms': ^2.1.1 '@csstools/css-tokenizer': ^2.1.1 - dependencies: - '@csstools/css-parser-algorithms': 2.1.1(@csstools/css-tokenizer@2.1.1) - '@csstools/css-tokenizer': 2.1.1 - dev: true - /@csstools/selector-specificity@2.2.0(postcss-selector-parser@6.0.12): + '@csstools/selector-specificity@2.2.0': resolution: {integrity: sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss-selector-parser: ^6.0.10 - dependencies: - postcss-selector-parser: 6.0.12 - dev: true - /@esbuild-kit/cjs-loader@2.4.2: + '@esbuild-kit/cjs-loader@2.4.2': resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==} - dependencies: - '@esbuild-kit/core-utils': 3.1.0 - get-tsconfig: 4.5.0 - dev: true - /@esbuild-kit/core-utils@3.1.0: + '@esbuild-kit/core-utils@3.1.0': resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==} - dependencies: - esbuild: 0.17.18 - source-map-support: 0.5.21 - dev: true - /@esbuild-kit/esm-loader@2.5.5: + '@esbuild-kit/esm-loader@2.5.5': resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==} - dependencies: - '@esbuild-kit/core-utils': 3.1.0 - get-tsconfig: 4.5.0 - dev: true - /@esbuild/android-arm64@0.17.18: + '@esbuild/android-arm64@0.17.18': resolution: {integrity: sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.15.18: + '@esbuild/android-arm@0.15.18': resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.17.18: + '@esbuild/android-arm@0.17.18': resolution: {integrity: sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.17.18: + '@esbuild/android-x64@0.17.18': resolution: {integrity: sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.17.18: + '@esbuild/darwin-arm64@0.17.18': resolution: {integrity: sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.17.18: + '@esbuild/darwin-x64@0.17.18': resolution: {integrity: sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.17.18: + '@esbuild/freebsd-arm64@0.17.18': resolution: {integrity: sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.17.18: + '@esbuild/freebsd-x64@0.17.18': resolution: {integrity: sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.17.18: + '@esbuild/linux-arm64@0.17.18': resolution: {integrity: sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.17.18: + '@esbuild/linux-arm@0.17.18': resolution: {integrity: sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.17.18: + '@esbuild/linux-ia32@0.17.18': resolution: {integrity: sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.15.18: + '@esbuild/linux-loong64@0.15.18': resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.17.18: + '@esbuild/linux-loong64@0.17.18': resolution: {integrity: sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.17.18: + '@esbuild/linux-mips64el@0.17.18': resolution: {integrity: sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.17.18: + '@esbuild/linux-ppc64@0.17.18': resolution: {integrity: sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.17.18: + '@esbuild/linux-riscv64@0.17.18': resolution: {integrity: sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.17.18: + '@esbuild/linux-s390x@0.17.18': resolution: {integrity: sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.17.18: + '@esbuild/linux-x64@0.17.18': resolution: {integrity: sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.17.18: + '@esbuild/netbsd-x64@0.17.18': resolution: {integrity: sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.17.18: + '@esbuild/openbsd-x64@0.17.18': resolution: {integrity: sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.17.18: + '@esbuild/sunos-x64@0.17.18': resolution: {integrity: sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.17.18: + '@esbuild/win32-arm64@0.17.18': resolution: {integrity: sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.17.18: + '@esbuild/win32-ia32@0.17.18': resolution: {integrity: sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.17.18: + '@esbuild/win32-x64@0.17.18': resolution: {integrity: sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.46.0): + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -430,24 +331,1857 @@ packages: peerDependenciesMeta: eslint: optional: true + + '@eslint-community/regexpp@4.5.1': + resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint-community/regexpp@4.6.2': + resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.1': + resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.46.0': + resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@humanwhocodes/config-array@0.11.10': + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + engines: {node: '>=10.10.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@1.2.1': + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@puppeteer/browsers@0.5.0': + resolution: {integrity: sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==} + engines: {node: '>=14.1.0'} + hasBin: true + peerDependencies: + typescript: '>= 4.7.4' + peerDependenciesMeta: + typescript: + optional: true + + '@sapphi-red/web-noise-suppressor@0.3.3': + resolution: {integrity: sha512-gAC33DCXYwNTI/k1PxOVHmbbzakUSMbb/DHpoV6rn4pKZtPI1dduULSmAAm/y1ipgIlArnk2JcnQzw4n2tCZHw==} + + '@types/chrome@0.0.246': + resolution: {integrity: sha512-MxGxEomGxsJiL9xe/7ZwVgwdn8XVKWbPvxpVQl3nWOjrS0Ce63JsfzxUc4aU3GvRcUPYsfufHmJ17BFyKxeA4g==} + + '@types/diff@5.0.3': + resolution: {integrity: sha512-amrLbRqTU9bXMCc6uX0sWpxsQzRIo9z6MJPkH1pkez/qOxuqSZVuryJAWoBRq94CeG8JxY+VK4Le9HtjQR5T9A==} + + '@types/filesystem@0.0.33': + resolution: {integrity: sha512-2KedRPzwu2K528vFkoXnnWdsG0MtUwPjuA7pRy4vKxlxHEe8qUDZibYHXJKZZr2Cl/ELdCWYqyb/MKwsUuzBWw==} + + '@types/filewriter@0.0.30': + resolution: {integrity: sha512-lB98tui0uxc7erbj0serZfJlHKLNJHwBltPnbmO1WRpL5T325GOHRiQfr2E29V2q+S1brDO63Fpdt6vb3bES9Q==} + + '@types/har-format@1.2.13': + resolution: {integrity: sha512-PwBsCBD3lDODn4xpje3Y1di0aDJp4Ww7aSfMRVw6ysnxD4I7Wmq2mBkSKaDtN403hqH5sp6c9xQUvFYY3+lkBg==} + + '@types/json-schema@7.0.11': + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + + '@types/lodash@4.14.194': + resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==} + + '@types/minimist@1.2.2': + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + + '@types/node@18.16.3': + resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==} + + '@types/normalize-package-data@2.4.1': + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + + '@types/prop-types@15.7.5': + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + + '@types/react-dom@18.2.1': + resolution: {integrity: sha512-8QZEV9+Kwy7tXFmjJrp3XUKQSs9LTnE0KnoUb0YCguWBiNW0Yfb2iBMYZ08WPg35IR6P3Z0s00B15SwZnO26+w==} + + '@types/react@17.0.2': + resolution: {integrity: sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==} + + '@types/react@18.2.0': + resolution: {integrity: sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA==} + + '@types/scheduler@0.16.3': + resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + + '@types/semver@7.3.13': + resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} + + '@types/yauzl@2.10.0': + resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} + + '@types/yazl@2.4.2': + resolution: {integrity: sha512-T+9JH8O2guEjXNxqmybzQ92mJUh2oCwDDMSSimZSe1P+pceZiFROZLYmcbqkzV5EUwz6VwcKXCO2S2yUpra6XQ==} + + '@typescript-eslint/eslint-plugin@5.59.1': + resolution: {integrity: sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + eslint: + optional: true + typescript: + optional: true + + '@typescript-eslint/parser@5.59.1': + resolution: {integrity: sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + eslint: + optional: true + typescript: + optional: true + + '@typescript-eslint/scope-manager@5.59.1': + resolution: {integrity: sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/type-utils@5.59.1': + resolution: {integrity: sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + eslint: + optional: true + typescript: + optional: true + + '@typescript-eslint/types@5.59.1': + resolution: {integrity: sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/typescript-estree@5.59.1': + resolution: {integrity: sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@5.59.1': + resolution: {integrity: sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + eslint: + optional: true + + '@typescript-eslint/visitor-keys@5.59.1': + resolution: {integrity: sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@vap/core@0.0.12': + resolution: {integrity: sha512-3csHpkE1zUSRTZwl7xIf2uXg1cD4IhhtUm0F6K/dWydc95R5Nj+krB4OTNATuqkewIv/ViCbwjPfkafAgvZQSg==} + + '@vap/shiki@0.10.5': + resolution: {integrity: sha512-5BHVGvQT8qonbLSASon5aQFQ18OZU4FxSl9tLSj6oJ0sap3KdMbYcfGq25M9zFZR1g1dJN7fgjmZXBIS5omIdw==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + + arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + chromium-bidi@0.4.7: + resolution: {integrity: sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==} + peerDependencies: + devtools-protocol: '*' + + class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + component-emitter@1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + + cosmiconfig@8.1.3: + resolution: {integrity: sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==} + engines: {node: '>=14'} + + cross-fetch@3.1.5: + resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + css-functions-list@3.1.0: + resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==} + engines: {node: '>=12.22'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decode-uri-component@0.2.0: + resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} + engines: {node: '>=0.10'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + + define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + + define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + + devtools-protocol@0.0.1107588: + resolution: {integrity: sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==} + + diff@5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + discord-types@1.3.26: + resolution: {integrity: sha512-ToG51AOCH+JTQf7b+8vuYQe5Iqwz7nZ7StpECAZ/VZcI1ZhQk13pvt9KkRTfRv1xNvwJ2qib4e3+RifQlo8VPQ==} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + esbuild-android-64@0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + esbuild-android-arm64@0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + esbuild-darwin-64@0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + esbuild-darwin-arm64@0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + esbuild-freebsd-64@0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + esbuild-freebsd-arm64@0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + esbuild-linux-32@0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + esbuild-linux-64@0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + esbuild-linux-arm64@0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + esbuild-linux-arm@0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + esbuild-linux-mips64le@0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + esbuild-linux-ppc64le@0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + esbuild-linux-riscv64@0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + esbuild-linux-s390x@0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + esbuild-netbsd-64@0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + esbuild-openbsd-64@0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + esbuild-sunos-64@0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + esbuild-windows-32@0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + esbuild-windows-64@0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + esbuild-windows-arm64@0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + esbuild@0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.17.18: + resolution: {integrity: sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-import-resolver-alias@1.1.2: + resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} + engines: {node: '>= 4'} + peerDependencies: + eslint-plugin-import: '>=1.4.0' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + + eslint-plugin-path-alias@1.0.0: + resolution: {integrity: sha512-FXus57yC+Zd3sMv46pbloXYwFeNVNHJqlACr9V68FG/IzGFBBokGJpmjDbEjpt8ZCeVSndUubeDWWl2A8sCNVQ==} + peerDependencies: + eslint: ^7 + peerDependenciesMeta: + eslint: + optional: true + + eslint-plugin-simple-header@1.0.2: + resolution: {integrity: sha512-K1EJ/ueBIjPRA8qR44Ymo+GDmPYYmfoODtainGxVr7PSbX6QiaY+pTuGCrOhO+AtVsYJs8GLSVdGUTXyAxAtOA==} + + eslint-plugin-simple-import-sort@10.0.0: + resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} + peerDependencies: + eslint: '>=5.0.0' + peerDependenciesMeta: + eslint: + optional: true + + eslint-plugin-unused-imports@2.0.0: + resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 + eslint: ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + eslint: + optional: true + + eslint-rule-composer@0.3.0: + resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} + engines: {node: '>=4.0.0'} + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.2: + resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.46.0: + resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + fastq@1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fflate@0.7.4: + resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-tsconfig@4.5.0: + resolution: {integrity: sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==} + + get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + + gifenc@https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3: + resolution: {tarball: https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3} + name: gifenc + version: 1.0.3 + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + + has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + + has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + + has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + + has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + + highlight.js@10.6.0: + resolution: {integrity: sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ==} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + is-accessor-descriptor@0.1.6: + resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} + engines: {node: '>=0.10.0'} + + is-accessor-descriptor@1.0.0: + resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} + engines: {node: '>=0.10.0'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-core-module@2.12.0: + resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} + + is-data-descriptor@0.1.4: + resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} + engines: {node: '>=0.10.0'} + + is-data-descriptor@1.0.0: + resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} + engines: {node: '>=0.10.0'} + + is-descriptor@0.1.6: + resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} + engines: {node: '>=0.10.0'} + + is-descriptor@1.0.2: + resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} + engines: {node: '>=0.10.0'} + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + + jszip@2.7.0: + resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==} + + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + + kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + + kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + known-css-properties@0.27.0: + resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + + mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + meow@9.0.0: + resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} + engines: {node: '>=10'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + mitt@3.0.0: + resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==} + + mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + moment@2.29.4: + resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + + monaco-editor@0.43.0: + resolution: {integrity: sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@4.0.2: + resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + + nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-fetch@2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + + object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + + postcss-resolve-nested-selector@0.1.1: + resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} + + postcss-safe-parser@6.0.0: + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + + postcss-selector-parser@6.0.12: + resolution: {integrity: sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.23: + resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + + punycode@2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + + puppeteer-core@19.11.1: + resolution: {integrity: sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==} + engines: {node: '>=14.14.0'} + peerDependencies: + typescript: '>= 4.7.4' + peerDependenciesMeta: + typescript: + optional: true + + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + + resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + + ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + + semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + + semver@7.5.0: + resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==} + engines: {node: '>=10'} + hasBin: true + + set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.0.1: + resolution: {integrity: sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + + source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.13: + resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} + + split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + + standalone-electron-types@1.0.0: + resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} + + static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + style-search@0.1.0: + resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} + + stylelint-config-recommended@12.0.0: + resolution: {integrity: sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==} + peerDependencies: + stylelint: ^15.5.0 + + stylelint-config-standard@33.0.0: + resolution: {integrity: sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==} + peerDependencies: + stylelint: ^15.5.0 + + stylelint@15.6.0: + resolution: {integrity: sha512-Cqzpc8tvJm77KaM8qUbhpJ/UYK55Ia0whQXj4b9IId9dlPICO7J8Lyo15SZWiHxKjlvy3p5FQor/3n6i8ignXg==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-hyperlinks@3.0.0: + resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + engines: {node: '>=14.18'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + + tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + + tsx@3.12.7: + resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@3.9.0: + resolution: {integrity: sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA==} + engines: {node: '>=14.16'} + + typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + + union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + + unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + + use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + v8-compile-cache@2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + virtual-merge@1.0.1: + resolution: {integrity: sha512-h7rzV6n5fZJbDu2lP4iu+IOtsZ00uqECFUxFePK1uY0pz/S5B7FNDJpmdDVfyGL7poyJECEHfTaIpJaknNkU0Q==} + + vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + + vscode-textmate@5.2.0: + resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.1: + resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zip-local@0.3.5: + resolution: {integrity: sha512-GRV3D5TJY+/PqyeRm5CYBs7xVrKTKzljBoEXvocZu0HJ7tPEcgpSOYa2zFIsCZWgKWMuc4U3yMFgFkERGFIB9w==} + + zustand@3.7.2: + resolution: {integrity: sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==} + engines: {node: '>=12.7.0'} + peerDependencies: + react: '>=16.8' + peerDependenciesMeta: + react: + optional: true + +snapshots: + + '@aashutoshrathi/word-wrap@1.2.6': {} + + '@babel/code-frame@7.21.4': + dependencies: + '@babel/highlight': 7.18.6 + + '@babel/helper-validator-identifier@7.19.1': {} + + '@babel/highlight@7.18.6': + dependencies: + '@babel/helper-validator-identifier': 7.19.1 + chalk: 2.4.2 + js-tokens: 4.0.0 + + '@csstools/css-parser-algorithms@2.1.1(@csstools/css-tokenizer@2.1.1)': + dependencies: + '@csstools/css-tokenizer': 2.1.1 + + '@csstools/css-tokenizer@2.1.1': {} + + '@csstools/media-query-list-parser@2.0.4(@csstools/css-parser-algorithms@2.1.1)(@csstools/css-tokenizer@2.1.1)': + dependencies: + '@csstools/css-parser-algorithms': 2.1.1(@csstools/css-tokenizer@2.1.1) + '@csstools/css-tokenizer': 2.1.1 + + '@csstools/selector-specificity@2.2.0(postcss-selector-parser@6.0.12)': + dependencies: + postcss-selector-parser: 6.0.12 + + '@esbuild-kit/cjs-loader@2.4.2': + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.5.0 + + '@esbuild-kit/core-utils@3.1.0': + dependencies: + esbuild: 0.17.18 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.5.5': + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.5.0 + + '@esbuild/android-arm64@0.17.18': + optional: true + + '@esbuild/android-arm@0.15.18': + optional: true + + '@esbuild/android-arm@0.17.18': + optional: true + + '@esbuild/android-x64@0.17.18': + optional: true + + '@esbuild/darwin-arm64@0.17.18': + optional: true + + '@esbuild/darwin-x64@0.17.18': + optional: true + + '@esbuild/freebsd-arm64@0.17.18': + optional: true + + '@esbuild/freebsd-x64@0.17.18': + optional: true + + '@esbuild/linux-arm64@0.17.18': + optional: true + + '@esbuild/linux-arm@0.17.18': + optional: true + + '@esbuild/linux-ia32@0.17.18': + optional: true + + '@esbuild/linux-loong64@0.15.18': + optional: true + + '@esbuild/linux-loong64@0.17.18': + optional: true + + '@esbuild/linux-mips64el@0.17.18': + optional: true + + '@esbuild/linux-ppc64@0.17.18': + optional: true + + '@esbuild/linux-riscv64@0.17.18': + optional: true + + '@esbuild/linux-s390x@0.17.18': + optional: true + + '@esbuild/linux-x64@0.17.18': + optional: true + + '@esbuild/netbsd-x64@0.17.18': + optional: true + + '@esbuild/openbsd-x64@0.17.18': + optional: true + + '@esbuild/sunos-x64@0.17.18': + optional: true + + '@esbuild/win32-arm64@0.17.18': + optional: true + + '@esbuild/win32-ia32@0.17.18': + optional: true + + '@esbuild/win32-x64@0.17.18': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.46.0)': dependencies: eslint: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint-visitor-keys: 3.4.2 - dev: true - /@eslint-community/regexpp@4.5.1: - resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true + '@eslint-community/regexpp@4.5.1': {} - /@eslint-community/regexpp@4.6.2: - resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true + '@eslint-community/regexpp@4.6.2': {} - /@eslint/eslintrc@2.1.1: - resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@2.1.1': dependencies: ajv: 6.12.6 debug: 4.3.4 @@ -460,63 +2194,34 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: true - /@eslint/js@8.46.0: - resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + '@eslint/js@8.46.0': {} - /@humanwhocodes/config-array@0.11.10: - resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} - engines: {node: '>=10.10.0'} + '@humanwhocodes/config-array@0.11.10': dependencies: '@humanwhocodes/object-schema': 1.2.1 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - dev: true - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true + '@humanwhocodes/module-importer@1.0.1': {} - /@humanwhocodes/object-schema@1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - dev: true + '@humanwhocodes/object-schema@1.2.1': {} - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.13.0 - dev: true - /@puppeteer/browsers@0.5.0(typescript@5.0.4): - resolution: {integrity: sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==} - engines: {node: '>=14.1.0'} - hasBin: true - peerDependencies: - typescript: '>= 4.7.4' - peerDependenciesMeta: - typescript: - optional: true + '@puppeteer/browsers@0.5.0(typescript@5.0.4)': dependencies: debug: 4.3.4 extract-zip: 2.0.1 @@ -529,116 +2234,65 @@ packages: yargs: 17.7.1 transitivePeerDependencies: - supports-color - dev: true - /@sapphi-red/web-noise-suppressor@0.3.3: - resolution: {integrity: sha512-gAC33DCXYwNTI/k1PxOVHmbbzakUSMbb/DHpoV6rn4pKZtPI1dduULSmAAm/y1ipgIlArnk2JcnQzw4n2tCZHw==} - dev: false + '@sapphi-red/web-noise-suppressor@0.3.3': {} - /@types/chrome@0.0.246: - resolution: {integrity: sha512-MxGxEomGxsJiL9xe/7ZwVgwdn8XVKWbPvxpVQl3nWOjrS0Ce63JsfzxUc4aU3GvRcUPYsfufHmJ17BFyKxeA4g==} + '@types/chrome@0.0.246': dependencies: '@types/filesystem': 0.0.33 '@types/har-format': 1.2.13 - dev: true - /@types/diff@5.0.3: - resolution: {integrity: sha512-amrLbRqTU9bXMCc6uX0sWpxsQzRIo9z6MJPkH1pkez/qOxuqSZVuryJAWoBRq94CeG8JxY+VK4Le9HtjQR5T9A==} - dev: true + '@types/diff@5.0.3': {} - /@types/filesystem@0.0.33: - resolution: {integrity: sha512-2KedRPzwu2K528vFkoXnnWdsG0MtUwPjuA7pRy4vKxlxHEe8qUDZibYHXJKZZr2Cl/ELdCWYqyb/MKwsUuzBWw==} + '@types/filesystem@0.0.33': dependencies: '@types/filewriter': 0.0.30 - dev: true - /@types/filewriter@0.0.30: - resolution: {integrity: sha512-lB98tui0uxc7erbj0serZfJlHKLNJHwBltPnbmO1WRpL5T325GOHRiQfr2E29V2q+S1brDO63Fpdt6vb3bES9Q==} - dev: true + '@types/filewriter@0.0.30': {} - /@types/har-format@1.2.13: - resolution: {integrity: sha512-PwBsCBD3lDODn4xpje3Y1di0aDJp4Ww7aSfMRVw6ysnxD4I7Wmq2mBkSKaDtN403hqH5sp6c9xQUvFYY3+lkBg==} - dev: true + '@types/har-format@1.2.13': {} - /@types/json-schema@7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true + '@types/json-schema@7.0.11': {} - /@types/lodash@4.14.194: - resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==} - dev: true + '@types/lodash@4.14.194': {} - /@types/minimist@1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: true + '@types/minimist@1.2.2': {} - /@types/node@18.16.3: - resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==} - dev: true + '@types/node@18.16.3': {} - /@types/normalize-package-data@2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true + '@types/normalize-package-data@2.4.1': {} - /@types/prop-types@15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - dev: true + '@types/prop-types@15.7.5': {} - /@types/react-dom@18.2.1: - resolution: {integrity: sha512-8QZEV9+Kwy7tXFmjJrp3XUKQSs9LTnE0KnoUb0YCguWBiNW0Yfb2iBMYZ08WPg35IR6P3Z0s00B15SwZnO26+w==} + '@types/react-dom@18.2.1': dependencies: '@types/react': 18.2.0 - dev: true - /@types/react@17.0.2: - resolution: {integrity: sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA==} + '@types/react@17.0.2': dependencies: '@types/prop-types': 15.7.5 csstype: 3.1.2 - dev: true - /@types/react@18.2.0: - resolution: {integrity: sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA==} + '@types/react@18.2.0': dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.3 csstype: 3.1.2 - dev: true - /@types/scheduler@0.16.3: - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} - dev: true + '@types/scheduler@0.16.3': {} - /@types/semver@7.3.13: - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - dev: true + '@types/semver@7.3.13': {} - /@types/yauzl@2.10.0: - resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} - requiresBuild: true + '@types/yauzl@2.10.0': dependencies: '@types/node': 18.16.3 - dev: true optional: true - /@types/yazl@2.4.2: - resolution: {integrity: sha512-T+9JH8O2guEjXNxqmybzQ92mJUh2oCwDDMSSimZSe1P+pceZiFROZLYmcbqkzV5EUwz6VwcKXCO2S2yUpra6XQ==} + '@types/yazl@2.4.2': dependencies: '@types/node': 18.16.3 - dev: true - /@typescript-eslint/eslint-plugin@5.59.1(@typescript-eslint/parser@5.59.1)(eslint@8.46.0)(typescript@5.0.4): - resolution: {integrity: sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - eslint: - optional: true - typescript: - optional: true + '@typescript-eslint/eslint-plugin@5.59.1(@typescript-eslint/parser@5.59.1)(eslint@8.46.0)(typescript@5.0.4)': dependencies: '@eslint-community/regexpp': 4.5.1 '@typescript-eslint/parser': 5.59.1(eslint@8.46.0)(typescript@5.0.4) @@ -655,19 +2309,8 @@ packages: typescript: 5.0.4 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/parser@5.59.1(eslint@8.46.0)(typescript@5.0.4): - resolution: {integrity: sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - eslint: - optional: true - typescript: - optional: true + '@typescript-eslint/parser@5.59.1(eslint@8.46.0)(typescript@5.0.4)': dependencies: '@typescript-eslint/scope-manager': 5.59.1 '@typescript-eslint/types': 5.59.1 @@ -677,27 +2320,13 @@ packages: typescript: 5.0.4 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/scope-manager@5.59.1: - resolution: {integrity: sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/scope-manager@5.59.1': dependencies: '@typescript-eslint/types': 5.59.1 '@typescript-eslint/visitor-keys': 5.59.1 - dev: true - /@typescript-eslint/type-utils@5.59.1(eslint@8.46.0)(typescript@5.0.4): - resolution: {integrity: sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - eslint: - optional: true - typescript: - optional: true + '@typescript-eslint/type-utils@5.59.1(eslint@8.46.0)(typescript@5.0.4)': dependencies: '@typescript-eslint/typescript-estree': 5.59.1(typescript@5.0.4) '@typescript-eslint/utils': 5.59.1(eslint@8.46.0)(typescript@5.0.4) @@ -707,21 +2336,10 @@ packages: typescript: 5.0.4 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/types@5.59.1: - resolution: {integrity: sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + '@typescript-eslint/types@5.59.1': {} - /@typescript-eslint/typescript-estree@5.59.1(typescript@5.0.4): - resolution: {integrity: sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/typescript-estree@5.59.1(typescript@5.0.4)': dependencies: '@typescript-eslint/types': 5.59.1 '@typescript-eslint/visitor-keys': 5.59.1 @@ -733,16 +2351,8 @@ packages: typescript: 5.0.4 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/utils@5.59.1(eslint@8.46.0)(typescript@5.0.4): - resolution: {integrity: sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - eslint: - optional: true + '@typescript-eslint/utils@5.59.1(eslint@8.46.0)(typescript@5.0.4)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@types/json-schema': 7.0.11 @@ -756,154 +2366,85 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: true - /@typescript-eslint/visitor-keys@5.59.1: - resolution: {integrity: sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/visitor-keys@5.59.1': dependencies: '@typescript-eslint/types': 5.59.1 eslint-visitor-keys: 3.4.0 - dev: true - /@vap/core@0.0.12: - resolution: {integrity: sha512-3csHpkE1zUSRTZwl7xIf2uXg1cD4IhhtUm0F6K/dWydc95R5Nj+krB4OTNATuqkewIv/ViCbwjPfkafAgvZQSg==} + '@vap/core@0.0.12': dependencies: eventemitter3: 4.0.7 - dev: false - /@vap/shiki@0.10.5: - resolution: {integrity: sha512-5BHVGvQT8qonbLSASon5aQFQ18OZU4FxSl9tLSj6oJ0sap3KdMbYcfGq25M9zFZR1g1dJN7fgjmZXBIS5omIdw==} + '@vap/shiki@0.10.5': dependencies: jsonc-parser: 3.2.0 vscode-oniguruma: 1.7.0 vscode-textmate: 5.2.0 - dev: false - /acorn-jsx@5.3.2(acorn@8.10.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-jsx@5.3.2(acorn@8.10.0): dependencies: acorn: 8.10.0 - dev: true - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn@8.10.0: {} - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + agent-base@6.0.2: dependencies: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.12.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 - dev: true - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + ansi-regex@5.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: true - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true + argparse@2.0.1: {} - /arr-diff@4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - dev: true + arr-diff@4.0.0: {} - /arr-union@3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - dev: true + arr-union@3.1.0: {} - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true + array-union@2.1.0: {} - /array-unique@0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - dev: true + array-unique@0.3.2: {} - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true + arrify@1.0.1: {} - /assign-symbols@1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - dev: true + assign-symbols@1.0.0: {} - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true + astral-regex@2.0.0: {} - /async@1.5.2: - resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} - dev: true + async@1.5.2: {} - /atob@2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - dev: true + atob@2.1.2: {} - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true + balanced-match@1.0.2: {} - /balanced-match@2.0.0: - resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - dev: true + balanced-match@2.0.0: {} - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true + base64-js@1.5.1: {} - /base@0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} + base@0.11.2: dependencies: cache-base: 1.0.1 class-utils: 0.3.6 @@ -912,48 +2453,32 @@ packages: isobject: 3.0.1 mixin-deep: 1.3.2 pascalcase: 0.1.1 - dev: true - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true + buffer-crc32@0.2.13: {} - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true + buffer-from@1.1.2: {} - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: true - /cache-base@1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} + cache-base@1.0.1: dependencies: collection-visit: 1.0.0 component-emitter: 1.3.0 @@ -964,470 +2489,223 @@ packages: to-object-path: 0.3.0 union-value: 1.0.1 unset-value: 1.0.0 - dev: true - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true + callsites@3.1.0: {} - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + camelcase-keys@6.2.2: dependencies: camelcase: 5.3.1 map-obj: 4.3.0 quick-lru: 4.0.1 - dev: true - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true + camelcase@5.3.1: {} - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - dev: true + chownr@1.1.4: {} - /chromium-bidi@0.4.7(devtools-protocol@0.0.1107588): - resolution: {integrity: sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==} - peerDependencies: - devtools-protocol: '*' + chromium-bidi@0.4.7(devtools-protocol@0.0.1107588): dependencies: devtools-protocol: 0.0.1107588 mitt: 3.0.0 - dev: true - /class-utils@0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} + class-utils@0.3.6: dependencies: arr-union: 3.1.0 define-property: 0.2.5 isobject: 3.0.1 static-extend: 0.1.2 - dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /collection-visit@1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} + collection-visit@1.0.0: dependencies: map-visit: 1.0.0 object-visit: 1.0.1 - dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - dev: true + colord@2.9.3: {} - /component-emitter@1.3.0: - resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} - dev: true + component-emitter@1.3.0: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + concat-map@0.0.1: {} - /copy-descriptor@0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - dev: true + copy-descriptor@0.1.1: {} - /cosmiconfig@8.1.3: - resolution: {integrity: sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==} - engines: {node: '>=14'} + cosmiconfig@8.1.3: dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - dev: true - /cross-fetch@3.1.5: - resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} + cross-fetch@3.1.5: dependencies: node-fetch: 2.6.7 transitivePeerDependencies: - encoding - dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - /css-functions-list@3.1.0: - resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==} - engines: {node: '>=12.22'} - dev: true + css-functions-list@3.1.0: {} - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-tree@2.3.1: dependencies: mdn-data: 2.0.30 source-map-js: 1.0.2 - dev: true - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true + cssesc@3.0.0: {} - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true + csstype@3.1.2: {} - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@2.6.9: dependencies: ms: 2.0.0 - dev: true - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4: dependencies: ms: 2.1.2 - dev: true - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 map-obj: 1.0.1 - dev: true - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true + decamelize@1.2.0: {} - /decode-uri-component@0.2.0: - resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} - engines: {node: '>=0.10'} - dev: true + decode-uri-component@0.2.0: {} - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true + deep-is@0.1.4: {} - /define-property@0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} + define-property@0.2.5: dependencies: is-descriptor: 0.1.6 - dev: true - /define-property@1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} + define-property@1.0.0: dependencies: is-descriptor: 1.0.2 - dev: true - /define-property@2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} + define-property@2.0.2: dependencies: is-descriptor: 1.0.2 isobject: 3.0.1 - dev: true - /devtools-protocol@0.0.1107588: - resolution: {integrity: sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==} - dev: true + devtools-protocol@0.0.1107588: {} - /diff@5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} - dev: true + diff@5.1.0: {} - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dev: true - /discord-types@1.3.26: - resolution: {integrity: sha512-ToG51AOCH+JTQf7b+8vuYQe5Iqwz7nZ7StpECAZ/VZcI1ZhQk13pvt9KkRTfRv1xNvwJ2qib4e3+RifQlo8VPQ==} + discord-types@1.3.26: dependencies: '@types/react': 17.0.2 moment: 2.29.4 - dev: true - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} + doctrine@3.0.0: dependencies: esutils: 2.0.3 - dev: true - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-of-stream@1.4.4: dependencies: once: 1.4.0 - dev: true - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - dev: true - /esbuild-android-64@0.15.18: - resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true + esbuild-android-64@0.15.18: optional: true - /esbuild-android-arm64@0.15.18: - resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true + esbuild-android-arm64@0.15.18: optional: true - /esbuild-darwin-64@0.15.18: - resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true + esbuild-darwin-64@0.15.18: optional: true - /esbuild-darwin-arm64@0.15.18: - resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true + esbuild-darwin-arm64@0.15.18: optional: true - /esbuild-freebsd-64@0.15.18: - resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true + esbuild-freebsd-64@0.15.18: optional: true - /esbuild-freebsd-arm64@0.15.18: - resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true + esbuild-freebsd-arm64@0.15.18: optional: true - /esbuild-linux-32@0.15.18: - resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-32@0.15.18: optional: true - /esbuild-linux-64@0.15.18: - resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-64@0.15.18: optional: true - /esbuild-linux-arm64@0.15.18: - resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-arm64@0.15.18: optional: true - /esbuild-linux-arm@0.15.18: - resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-arm@0.15.18: optional: true - /esbuild-linux-mips64le@0.15.18: - resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-mips64le@0.15.18: optional: true - /esbuild-linux-ppc64le@0.15.18: - resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-ppc64le@0.15.18: optional: true - /esbuild-linux-riscv64@0.15.18: - resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-riscv64@0.15.18: optional: true - /esbuild-linux-s390x@0.15.18: - resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true + esbuild-linux-s390x@0.15.18: optional: true - /esbuild-netbsd-64@0.15.18: - resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true + esbuild-netbsd-64@0.15.18: optional: true - /esbuild-openbsd-64@0.15.18: - resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true + esbuild-openbsd-64@0.15.18: optional: true - /esbuild-sunos-64@0.15.18: - resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true + esbuild-sunos-64@0.15.18: optional: true - /esbuild-windows-32@0.15.18: - resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true + esbuild-windows-32@0.15.18: optional: true - /esbuild-windows-64@0.15.18: - resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true + esbuild-windows-64@0.15.18: optional: true - /esbuild-windows-arm64@0.15.18: - resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true + esbuild-windows-arm64@0.15.18: optional: true - /esbuild@0.15.18: - resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esbuild@0.15.18: optionalDependencies: '@esbuild/android-arm': 0.15.18 '@esbuild/linux-loong64': 0.15.18 @@ -1451,13 +2729,8 @@ packages: esbuild-windows-32: 0.15.18 esbuild-windows-64: 0.15.18 esbuild-windows-arm64: 0.15.18 - dev: true - /esbuild@0.17.18: - resolution: {integrity: sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esbuild@0.17.18: optionalDependencies: '@esbuild/android-arm': 0.17.18 '@esbuild/android-arm64': 0.17.18 @@ -1481,115 +2754,51 @@ packages: '@esbuild/win32-arm64': 0.17.18 '@esbuild/win32-ia32': 0.17.18 '@esbuild/win32-x64': 0.17.18 - dev: true - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true + escalade@3.1.1: {} - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true + escape-string-regexp@1.0.5: {} - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true + escape-string-regexp@4.0.0: {} - /eslint-import-resolver-alias@1.1.2: - resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} - engines: {node: '>= 4'} - peerDependencies: - eslint-plugin-import: '>=1.4.0' - peerDependenciesMeta: - eslint-plugin-import: - optional: true - dev: true + eslint-import-resolver-alias@1.1.2: {} - /eslint-plugin-path-alias@1.0.0(patch_hash=m6sma4g6bh67km3q6igf6uxaja)(eslint@8.46.0): - resolution: {integrity: sha512-FXus57yC+Zd3sMv46pbloXYwFeNVNHJqlACr9V68FG/IzGFBBokGJpmjDbEjpt8ZCeVSndUubeDWWl2A8sCNVQ==} - peerDependencies: - eslint: ^7 - peerDependenciesMeta: - eslint: - optional: true + eslint-plugin-path-alias@1.0.0(patch_hash=m6sma4g6bh67km3q6igf6uxaja)(eslint@8.46.0): dependencies: eslint: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) nanomatch: 1.2.13 transitivePeerDependencies: - supports-color - dev: true - patched: true - /eslint-plugin-simple-header@1.0.2: - resolution: {integrity: sha512-K1EJ/ueBIjPRA8qR44Ymo+GDmPYYmfoODtainGxVr7PSbX6QiaY+pTuGCrOhO+AtVsYJs8GLSVdGUTXyAxAtOA==} - dev: false + eslint-plugin-simple-header@1.0.2: {} - /eslint-plugin-simple-import-sort@10.0.0(eslint@8.46.0): - resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} - peerDependencies: - eslint: '>=5.0.0' - peerDependenciesMeta: - eslint: - optional: true + eslint-plugin-simple-import-sort@10.0.0(eslint@8.46.0): dependencies: eslint: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) - dev: true - /eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.59.1)(eslint@8.46.0): - resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - eslint: - optional: true + eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@5.59.1)(eslint@8.46.0): dependencies: '@typescript-eslint/eslint-plugin': 5.59.1(@typescript-eslint/parser@5.59.1)(eslint@8.46.0)(typescript@5.0.4) eslint: 8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint-rule-composer: 0.3.0 - dev: true - /eslint-rule-composer@0.3.0: - resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} - engines: {node: '>=4.0.0'} - dev: true + eslint-rule-composer@0.3.0: {} - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 estraverse: 4.3.0 - dev: true - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - dev: true - /eslint-visitor-keys@3.4.0: - resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + eslint-visitor-keys@3.4.0: {} - /eslint-visitor-keys@3.4.2: - resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + eslint-visitor-keys@3.4.2: {} - /eslint@8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4): - resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + eslint@8.46.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@eslint-community/regexpp': 4.6.2 @@ -1630,70 +2839,39 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color - dev: true - patched: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + espree@9.6.1: dependencies: acorn: 8.10.0 acorn-jsx: 5.3.2(acorn@8.10.0) eslint-visitor-keys: 3.4.2 - dev: true - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} + esquery@1.5.0: dependencies: estraverse: 5.3.0 - dev: true - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 - dev: true - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true + estraverse@4.3.0: {} - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true + estraverse@5.3.0: {} - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true + esutils@2.0.3: {} - /eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: false + eventemitter3@4.0.7: {} - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} + extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 - dev: true - /extend-shallow@3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} + extend-shallow@3.0.2: dependencies: assign-symbols: 1.0.0 is-extendable: 1.0.1 - dev: true - /extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true + extract-zip@2.0.1: dependencies: debug: 4.3.4 get-stream: 5.2.0 @@ -1702,163 +2880,94 @@ packages: '@types/yauzl': 2.10.0 transitivePeerDependencies: - supports-color - dev: true - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true + fast-deep-equal@3.1.3: {} - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} + fast-glob@3.2.12: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true + fast-json-stable-stringify@2.1.0: {} - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true + fast-levenshtein@2.0.6: {} - /fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - dev: true + fastest-levenshtein@1.0.16: {} - /fastq@1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + fastq@1.13.0: dependencies: reusify: 1.0.4 - dev: true - /fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fd-slicer@1.1.0: dependencies: pend: 1.2.0 - dev: true - /fflate@0.7.4: - resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} - dev: false + fflate@0.7.4: {} - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.0.4 - dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: true - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true - /flat-cache@3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@3.0.4: dependencies: flatted: 3.2.7 rimraf: 3.0.2 - dev: true - /flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - dev: true + flatted@3.2.7: {} - /for-in@1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - dev: true + for-in@1.0.2: {} - /fragment-cache@0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} + fragment-cache@0.2.1: dependencies: map-cache: 0.2.2 - dev: true - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: true + fs-constants@1.0.0: {} - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true + fs.realpath@1.0.0: {} - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fsevents@2.3.2: optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true + function-bind@1.1.1: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} + get-stream@5.2.0: dependencies: pump: 3.0.0 - dev: true - /get-tsconfig@4.5.0: - resolution: {integrity: sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==} - dev: true + get-tsconfig@4.5.0: {} - /get-value@2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - dev: true + get-value@2.0.6: {} - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + gifenc@https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3: {} + + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + glob@7.2.3: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -1866,34 +2975,22 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} + global-modules@2.0.0: dependencies: global-prefix: 3.0.0 - dev: true - /global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} + global-prefix@3.0.0: dependencies: ini: 1.3.8 kind-of: 6.0.3 which: 1.3.1 - dev: true - /globals@13.20.0: - resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} - engines: {node: '>=8'} + globals@13.20.0: dependencies: type-fest: 0.20.2 - dev: true - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -1901,441 +2998,235 @@ packages: ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 - dev: true - /globjoin@0.1.4: - resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} - dev: true + globjoin@0.1.4: {} - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true + graceful-fs@4.2.11: {} - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true + grapheme-splitter@1.0.4: {} - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true + graphemer@1.4.0: {} - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true + hard-rejection@2.1.0: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /has-value@0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} + has-value@0.3.1: dependencies: get-value: 2.0.6 has-values: 0.1.4 isobject: 2.1.0 - dev: true - /has-value@1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} + has-value@1.0.0: dependencies: get-value: 2.0.6 has-values: 1.0.0 isobject: 3.0.1 - dev: true - /has-values@0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - dev: true + has-values@0.1.4: {} - /has-values@1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} + has-values@1.0.0: dependencies: is-number: 3.0.0 kind-of: 4.0.0 - dev: true - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + has@1.0.3: dependencies: function-bind: 1.1.1 - dev: true - /highlight.js@10.6.0: - resolution: {integrity: sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ==} - dev: true + highlight.js@10.6.0: {} - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true + hosted-git-info@2.8.9: {} - /hosted-git-info@4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} - engines: {node: '>=10'} + hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 - dev: true - /html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} - dev: true + html-tags@3.3.1: {} - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true + ieee754@1.2.1: {} - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - dev: true + ignore@5.2.4: {} - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true - /import-lazy@4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - dev: true + import-lazy@4.0.0: {} - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true + imurmurhash@0.1.4: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + indent-string@4.0.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true + inherits@2.0.4: {} - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true + ini@1.3.8: {} - /is-accessor-descriptor@0.1.6: - resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} - engines: {node: '>=0.10.0'} + is-accessor-descriptor@0.1.6: dependencies: kind-of: 3.2.2 - dev: true - /is-accessor-descriptor@1.0.0: - resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} - engines: {node: '>=0.10.0'} + is-accessor-descriptor@1.0.0: dependencies: kind-of: 6.0.3 - dev: true - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-arrayish@0.2.1: {} - /is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: true + is-buffer@1.1.6: {} - /is-core-module@2.12.0: - resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} + is-core-module@2.12.0: dependencies: has: 1.0.3 - dev: true - /is-data-descriptor@0.1.4: - resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} - engines: {node: '>=0.10.0'} + is-data-descriptor@0.1.4: dependencies: kind-of: 3.2.2 - dev: true - /is-data-descriptor@1.0.0: - resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} - engines: {node: '>=0.10.0'} + is-data-descriptor@1.0.0: dependencies: kind-of: 6.0.3 - dev: true - /is-descriptor@0.1.6: - resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} - engines: {node: '>=0.10.0'} + is-descriptor@0.1.6: dependencies: is-accessor-descriptor: 0.1.6 is-data-descriptor: 0.1.4 kind-of: 5.1.0 - dev: true - /is-descriptor@1.0.2: - resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} - engines: {node: '>=0.10.0'} + is-descriptor@1.0.2: dependencies: is-accessor-descriptor: 1.0.0 is-data-descriptor: 1.0.0 kind-of: 6.0.3 - dev: true - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: true + is-extendable@0.1.1: {} - /is-extendable@1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} + is-extendable@1.0.1: dependencies: is-plain-object: 2.0.4 - dev: true - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: true - /is-number@3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} + is-number@3.0.0: dependencies: kind-of: 3.2.2 - dev: true - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true + is-path-inside@3.0.3: {} - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true + is-plain-obj@1.1.0: {} - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} + is-plain-object@2.0.4: dependencies: isobject: 3.0.1 - dev: true - /is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - dev: true + is-plain-object@5.0.0: {} - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true + is-windows@1.0.2: {} - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true + isarray@1.0.0: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + isexe@2.0.0: {} - /isobject@2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} + isobject@2.1.0: dependencies: isarray: 1.0.0 - dev: true - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true + isobject@3.0.1: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + js-tokens@4.0.0: {} - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - dev: true - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + json-parse-even-better-errors@2.3.1: {} - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true + json-schema-traverse@0.4.1: {} - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true + json-schema-traverse@1.0.0: {} - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true + json-stable-stringify-without-jsonify@1.0.1: {} - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: false + jsonc-parser@3.2.0: {} - /jszip@2.7.0: - resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==} + jszip@2.7.0: dependencies: pako: 1.0.11 - dev: true - /kind-of@3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} + kind-of@3.2.2: dependencies: is-buffer: 1.1.6 - dev: true - /kind-of@4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} + kind-of@4.0.0: dependencies: is-buffer: 1.1.6 - dev: true - /kind-of@5.1.0: - resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} - engines: {node: '>=0.10.0'} - dev: true + kind-of@5.1.0: {} - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true + kind-of@6.0.3: {} - /known-css-properties@0.27.0: - resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==} - dev: true + known-css-properties@0.27.0: {} - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + lines-and-columns@1.2.4: {} - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: true - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - dev: true - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true + lodash.merge@4.6.2: {} - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true + lodash.truncate@4.4.2: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - dev: true - /map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - dev: true + map-cache@0.2.2: {} - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true + map-obj@1.0.1: {} - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true + map-obj@4.3.0: {} - /map-visit@1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} + map-visit@1.0.0: dependencies: object-visit: 1.0.1 - dev: true - /mathml-tag-names@2.1.3: - resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} - dev: true + mathml-tag-names@2.1.3: {} - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true + mdn-data@2.0.30: {} - /meow@9.0.0: - resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} - engines: {node: '>=10'} + meow@9.0.0: dependencies: '@types/minimist': 1.2.2 camelcase-keys: 6.2.2 @@ -2349,88 +3240,48 @@ packages: trim-newlines: 3.0.1 type-fest: 0.18.1 yargs-parser: 20.2.9 - dev: true - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true + merge2@1.4.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromatch@4.0.5: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true + min-indent@1.0.1: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - dev: true - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} + minimist-options@4.1.0: dependencies: arrify: 1.0.1 is-plain-obj: 1.1.0 kind-of: 6.0.3 - dev: true - /mitt@3.0.0: - resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==} - dev: true + mitt@3.0.0: {} - /mixin-deep@1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} + mixin-deep@1.3.2: dependencies: for-in: 1.0.2 is-extendable: 1.0.1 - dev: true - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - dev: true + mkdirp-classic@0.5.3: {} - /moment@2.29.4: - resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} - dev: true + moment@2.29.4: {} - /monaco-editor@0.43.0: - resolution: {integrity: sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==} - dev: false + monaco-editor@0.43.0: {} - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true + ms@2.0.0: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + ms@2.1.2: {} - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true + nanoid@3.3.6: {} - /nanoid@4.0.2: - resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - dev: false + nanoid@4.0.2: {} - /nanomatch@1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} + nanomatch@1.2.13: dependencies: arr-diff: 4.0.0 array-unique: 0.3.2 @@ -2445,84 +3296,50 @@ packages: to-regex: 3.0.2 transitivePeerDependencies: - supports-color - dev: true - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true + natural-compare-lite@1.4.0: {} - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true + natural-compare@1.4.0: {} - /node-fetch@2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + node-fetch@2.6.7: dependencies: whatwg-url: 5.0.0 - dev: true - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.2 semver: 5.7.1 validate-npm-package-license: 3.0.4 - dev: true - /normalize-package-data@3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} - engines: {node: '>=10'} + normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.12.0 semver: 7.5.0 validate-npm-package-license: 3.0.4 - dev: true - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + normalize-path@3.0.0: {} - /object-copy@0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} + object-copy@0.1.0: dependencies: copy-descriptor: 0.1.1 define-property: 0.2.5 kind-of: 3.2.2 - dev: true - /object-visit@1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} + object-visit@1.0.1: dependencies: isobject: 3.0.1 - dev: true - /object.pick@1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} + object.pick@1.3.0: dependencies: isobject: 3.0.1 - dev: true - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: true - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} + optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 @@ -2530,176 +3347,91 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: true - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - dev: true - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: true - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - dev: true - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true + p-try@2.2.0: {} - /pako@1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: true + pako@1.0.11: {} - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + parent-module@1.0.1: dependencies: callsites: 3.1.0 - dev: true - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.21.4 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true - /pascalcase@0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - dev: true + pascalcase@0.1.1: {} - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true + path-is-absolute@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true + path-parse@1.0.7: {} - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true + path-type@4.0.0: {} - /pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: true + pend@1.2.0: {} - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true + picocolors@1.0.0: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /postcss-media-query-parser@0.2.3: - resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} - dev: true + postcss-media-query-parser@0.2.3: {} - /postcss-resolve-nested-selector@0.1.1: - resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} - dev: true + postcss-resolve-nested-selector@0.1.1: {} - /postcss-safe-parser@6.0.0(postcss@8.4.23): - resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.3.3 + postcss-safe-parser@6.0.0(postcss@8.4.23): dependencies: postcss: 8.4.23 - dev: true - /postcss-selector-parser@6.0.12: - resolution: {integrity: sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==} - engines: {node: '>=4'} + postcss-selector-parser@6.0.12: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: true - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true + postcss-value-parser@4.2.0: {} - /postcss@8.4.23: - resolution: {integrity: sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==} - engines: {node: ^10 || ^12 || >=14} + postcss@8.4.23: dependencies: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true + prelude-ls@1.2.1: {} - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true + progress@2.0.3: {} - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true + proxy-from-env@1.1.0: {} - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + pump@3.0.0: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - dev: true - /punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: true + punycode@2.1.1: {} - /puppeteer-core@19.11.1(typescript@5.0.4): - resolution: {integrity: sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==} - engines: {node: '>=14.14.0'} - peerDependencies: - typescript: '>= 4.7.4' - peerDependenciesMeta: - typescript: - optional: true + puppeteer-core@19.11.1(typescript@5.0.4): dependencies: '@puppeteer/browsers': 0.5.0(typescript@5.0.4) chromium-bidi: 0.4.7(devtools-protocol@0.0.1107588) @@ -2718,190 +3450,106 @@ packages: - encoding - supports-color - utf-8-validate - dev: true - /q@1.5.1: - resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} - engines: {node: '>=0.6.0', teleport: '>=0.2.0'} - dev: true + q@1.5.1: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true + queue-microtask@1.2.3: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true + quick-lru@4.0.1: {} - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 read-pkg: 5.2.0 type-fest: 0.8.1 - dev: true - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + read-pkg@5.2.0: dependencies: '@types/normalize-package-data': 2.4.1 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 - dev: true - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 - dev: true - /regex-not@1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} + regex-not@1.0.2: dependencies: extend-shallow: 3.0.2 safe-regex: 1.1.0 - dev: true - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + require-directory@2.1.1: {} - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true + require-from-string@2.0.2: {} - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true + resolve-from@4.0.0: {} - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true + resolve-from@5.0.0: {} - /resolve-url@0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - dev: true + resolve-url@0.2.1: {} - /resolve@1.22.2: - resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} - hasBin: true + resolve@1.22.2: dependencies: is-core-module: 2.12.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true - /ret@0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} - dev: true + ret@0.1.15: {} - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true + reusify@1.0.4: {} - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true + rimraf@3.0.2: dependencies: glob: 7.2.3 - dev: true - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: true - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + safe-buffer@5.2.1: {} - /safe-regex@1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + safe-regex@1.1.0: dependencies: ret: 0.1.15 - dev: true - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true + semver@5.7.1: {} - /semver@7.5.0: - resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==} - engines: {node: '>=10'} - hasBin: true + semver@7.5.0: dependencies: lru-cache: 6.0.0 - dev: true - /set-value@2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} + set-value@2.0.1: dependencies: extend-shallow: 2.0.1 is-extendable: 0.1.1 is-plain-object: 2.0.4 split-string: 3.1.0 - dev: true - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true + shebang-regex@3.0.0: {} - /signal-exit@4.0.1: - resolution: {integrity: sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==} - engines: {node: '>=14'} - dev: true + signal-exit@4.0.1: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + slash@3.0.0: {} - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + slice-ansi@4.0.0: dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - dev: true - /snapdragon@0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} + snapdragon@0.8.2: dependencies: base: 0.11.2 debug: 2.6.9 @@ -2913,148 +3561,87 @@ packages: use: 3.1.1 transitivePeerDependencies: - supports-color - dev: true - /source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: true + source-map-js@1.0.2: {} - /source-map-resolve@0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated + source-map-resolve@0.5.3: dependencies: atob: 2.1.2 decode-uri-component: 0.2.0 resolve-url: 0.2.1 source-map-url: 0.4.1 urix: 0.1.0 - dev: true - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map-url@0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - dev: true + source-map-url@0.4.1: {} - /source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.5.7: {} - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.6.1: {} - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.13 - dev: true - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true + spdx-exceptions@2.3.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.13 - dev: true - /spdx-license-ids@3.0.13: - resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} - dev: true + spdx-license-ids@3.0.13: {} - /split-string@3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} + split-string@3.1.0: dependencies: extend-shallow: 3.0.2 - dev: true - /standalone-electron-types@1.0.0: - resolution: {integrity: sha512-0HOi/tlTz3mjWhsAz4uRbpQcHMZ+ifj1JzWW9nugykOHClBBG77ps8QinrzX1eow4Iw2pnC+RFaSYRgufF4BOg==} + standalone-electron-types@1.0.0: dependencies: '@types/node': 18.16.3 - dev: true - /static-extend@0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} + static-extend@0.1.2: dependencies: define-property: 0.2.5 object-copy: 0.1.0 - dev: true - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: true - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 - dev: true - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true + strip-json-comments@3.1.1: {} - /style-search@0.1.0: - resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} - dev: true + style-search@0.1.0: {} - /stylelint-config-recommended@12.0.0(stylelint@15.6.0): - resolution: {integrity: sha512-x6x8QNARrGO2sG6iURkzqL+Dp+4bJorPMMRNPScdvaUK8PsynriOcMW7AFDKqkWAS5wbue/u8fUT/4ynzcmqdQ==} - peerDependencies: - stylelint: ^15.5.0 + stylelint-config-recommended@12.0.0(stylelint@15.6.0): dependencies: stylelint: 15.6.0 - dev: true - /stylelint-config-standard@33.0.0(stylelint@15.6.0): - resolution: {integrity: sha512-eyxnLWoXImUn77+ODIuW9qXBDNM+ALN68L3wT1lN2oNspZ7D9NVGlNHb2QCUn4xDug6VZLsh0tF8NyoYzkgTzg==} - peerDependencies: - stylelint: ^15.5.0 + stylelint-config-standard@33.0.0(stylelint@15.6.0): dependencies: stylelint: 15.6.0 stylelint-config-recommended: 12.0.0(stylelint@15.6.0) - dev: true - /stylelint@15.6.0: - resolution: {integrity: sha512-Cqzpc8tvJm77KaM8qUbhpJ/UYK55Ia0whQXj4b9IId9dlPICO7J8Lyo15SZWiHxKjlvy3p5FQor/3n6i8ignXg==} - engines: {node: ^14.13.1 || >=16.0.0} - hasBin: true + stylelint@15.6.0: dependencies: '@csstools/css-parser-algorithms': 2.1.1(@csstools/css-tokenizer@2.1.1) '@csstools/css-tokenizer': 2.1.1 @@ -3100,324 +3687,180 @@ packages: write-file-atomic: 5.0.1 transitivePeerDependencies: - supports-color - dev: true - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - dev: true - /supports-hyperlinks@3.0.0: - resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} - engines: {node: '>=14.18'} + supports-hyperlinks@3.0.0: dependencies: has-flag: 4.0.0 supports-color: 7.2.0 - dev: true - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true + supports-preserve-symlinks-flag@1.0.0: {} - /svg-tags@1.0.0: - resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - dev: true + svg-tags@1.0.0: {} - /table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} + table@6.8.1: dependencies: ajv: 8.12.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + tar-fs@2.1.1: dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 pump: 3.0.0 tar-stream: 2.2.0 - dev: true - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} + tar-stream@2.2.0: dependencies: bl: 4.1.0 end-of-stream: 1.4.4 fs-constants: 1.0.0 inherits: 2.0.4 readable-stream: 3.6.2 - dev: true - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true + text-table@0.2.0: {} - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true + through@2.3.8: {} - /to-object-path@0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} + to-object-path@0.3.0: dependencies: kind-of: 3.2.2 - dev: true - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /to-regex@3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} + to-regex@3.0.2: dependencies: define-property: 2.0.2 extend-shallow: 3.0.2 regex-not: 1.0.2 safe-regex: 1.1.0 - dev: true - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true + tr46@0.0.3: {} - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true + trim-newlines@3.0.1: {} - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true + tslib@1.14.1: {} - /tsutils@3.21.0(typescript@5.0.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + tsutils@3.21.0(typescript@5.0.4): dependencies: tslib: 1.14.1 typescript: 5.0.4 - dev: true - /tsx@3.12.7: - resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==} - hasBin: true + tsx@3.12.7: dependencies: '@esbuild-kit/cjs-loader': 2.4.2 '@esbuild-kit/core-utils': 3.1.0 '@esbuild-kit/esm-loader': 2.5.5 optionalDependencies: fsevents: 2.3.2 - dev: true - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - dev: true - /type-fest@0.18.1: - resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} - engines: {node: '>=10'} - dev: true + type-fest@0.18.1: {} - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true + type-fest@0.20.2: {} - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true + type-fest@0.6.0: {} - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true + type-fest@0.8.1: {} - /type-fest@3.9.0: - resolution: {integrity: sha512-hR8JP2e8UiH7SME5JZjsobBlEiatFoxpzCP+R3ZeCo7kAaG1jXQE5X/buLzogM6GJu8le9Y4OcfNuIQX0rZskA==} - engines: {node: '>=14.16'} - dev: true + type-fest@3.9.0: {} - /typescript@5.0.4: - resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} - engines: {node: '>=12.20'} - hasBin: true - dev: true + typescript@5.0.4: {} - /unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + unbzip2-stream@1.4.3: dependencies: buffer: 5.7.1 through: 2.3.8 - dev: true - /union-value@1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} + union-value@1.0.1: dependencies: arr-union: 3.1.0 get-value: 2.0.6 is-extendable: 0.1.1 set-value: 2.0.1 - dev: true - /unset-value@1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} + unset-value@1.0.0: dependencies: has-value: 0.3.1 isobject: 3.0.1 - dev: true - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-js@4.4.1: dependencies: punycode: 2.1.1 - dev: true - /urix@0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - dev: true + urix@0.1.0: {} - /use@3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - dev: true + use@3.1.1: {} - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true + util-deprecate@1.0.2: {} - /v8-compile-cache@2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true + v8-compile-cache@2.3.0: {} - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - dev: true - /virtual-merge@1.0.1: - resolution: {integrity: sha512-h7rzV6n5fZJbDu2lP4iu+IOtsZ00uqECFUxFePK1uY0pz/S5B7FNDJpmdDVfyGL7poyJECEHfTaIpJaknNkU0Q==} - dev: false + virtual-merge@1.0.1: {} - /vscode-oniguruma@1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - dev: false + vscode-oniguruma@1.7.0: {} - /vscode-textmate@5.2.0: - resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} - dev: false + vscode-textmate@5.2.0: {} - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true + webidl-conversions@3.0.1: {} - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + which@1.3.1: dependencies: isexe: 2.0.0 - dev: true - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true + wrappy@1.0.2: {} - /write-file-atomic@5.0.1: - resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 signal-exit: 4.0.1 - dev: true - /ws@8.13.0: - resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@8.13.0: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yallist@4.0.0: {} - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true + yargs-parser@20.2.9: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true + yargs-parser@21.1.1: {} - /yargs@17.7.1: - resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} - engines: {node: '>=12'} + yargs@17.7.1: dependencies: cliui: 8.0.1 escalade: 3.1.1 @@ -3426,45 +3869,19 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true - /yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 - dev: true - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} - /zip-local@0.3.5: - resolution: {integrity: sha512-GRV3D5TJY+/PqyeRm5CYBs7xVrKTKzljBoEXvocZu0HJ7tPEcgpSOYa2zFIsCZWgKWMuc4U3yMFgFkERGFIB9w==} + zip-local@0.3.5: dependencies: async: 1.5.2 graceful-fs: 4.2.11 jszip: 2.7.0 q: 1.5.1 - dev: true - /zustand@3.7.2: - resolution: {integrity: sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==} - engines: {node: '>=12.7.0'} - peerDependencies: - react: '>=16.8' - peerDependenciesMeta: - react: - optional: true - dev: true - - github.com/mattdesl/gifenc/64842fca317b112a8590f8fef2bf3825da8f6fe3: - resolution: {tarball: https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3} - name: gifenc - version: 1.0.3 - dev: false - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false + zustand@3.7.2: {} diff --git a/scripts/build/common.mjs b/scripts/build/common.mjs index 5c34ad038..e2c901226 100644 --- a/scripts/build/common.mjs +++ b/scripts/build/common.mjs @@ -25,10 +25,11 @@ import { access, readdir, readFile } from "fs/promises"; import { join, relative } from "path"; import { promisify } from "util"; -// wtf is this assert syntax -import PackageJSON from "../../package.json" assert { type: "json" }; import { getPluginTarget } from "../utils.mjs"; +/** @type {import("../../package.json")} */ +const PackageJSON = JSON.parse(readFileSync("package.json")); + export const VERSION = PackageJSON.version; // https://reproducible-builds.org/docs/source-date-epoch/ export const BUILD_TIMESTAMP = Number(process.env.SOURCE_DATE_EPOCH) || Date.now(); diff --git a/tsconfig.json b/tsconfig.json index e9c926408..96c904766 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "skipLibCheck": true, From 0e66c4a1f598d3ec8efa9e5314bbb600c71165ec Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 02:46:52 -0300 Subject: [PATCH 055/134] Fix subscribing to plugin flux events twice --- src/plugins/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 2d5e3e5a4..488847d15 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -36,6 +36,7 @@ export const patches = [] as Patch[]; /** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */ let enabledPluginsSubscribedFlux = false; +const subscribedFluxEventsPlugins = new Set(); const settings = Settings.plugins; @@ -123,7 +124,9 @@ export function startDependenciesRecursive(p: Plugin) { } export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) { - if (p.flux) { + if (p.flux && !subscribedFluxEventsPlugins.has(p.name)) { + subscribedFluxEventsPlugins.add(p.name); + logger.debug("Subscribing to flux events of plugin", p.name); for (const [event, handler] of Object.entries(p.flux)) { fluxDispatcher.subscribe(event as FluxEvents, handler); @@ -133,6 +136,8 @@ export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Flux export function unsubscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) { if (p.flux) { + subscribedFluxEventsPlugins.delete(p.name); + logger.debug("Unsubscribing from flux events of plugin", p.name); for (const [event, handler] of Object.entries(p.flux)) { fluxDispatcher.unsubscribe(event as FluxEvents, handler); From 75847147d132ff5eb432dbdd7f12fdc0a03c86a1 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 03:20:56 -0300 Subject: [PATCH 056/134] FakeNitro: Add custom notifications sound bypass --- src/plugins/fakeNitro/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index ad7394dc9..03feda0a8 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -400,6 +400,14 @@ export default definePlugin({ match: /(?<=type:"(?:SOUNDBOARD_SOUNDS_RECEIVED|GUILD_SOUNDBOARD_SOUND_CREATE|GUILD_SOUNDBOARD_SOUND_UPDATE|GUILD_SOUNDBOARD_SOUNDS_UPDATE)".+?available:)\i\.available/g, replace: "true" } + }, + // Allow using custom notification sounds + { + find: "canUseCustomNotificationSounds:function", + replacement: { + match: /canUseCustomNotificationSounds:function\(\i\){/, + replace: "$&return true;" + } } ], From 97acffafcc75676330d7939a94930001614fe975 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 7 May 2024 16:32:19 +0200 Subject: [PATCH 057/134] fix useStateFromStores JSDoc Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com> --- src/webpack/common/stores.ts | 14 +++----------- src/webpack/common/types/stores.d.ts | 7 +++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 2f9786bc5..be5721ff3 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -64,23 +64,15 @@ export let DraftStore: t.DraftStore; /** * React hook that returns stateful data for one or more stores * You might need a custom comparator (4th argument) if your store data is an object - * * @param stores The stores to listen to * @param mapper A function that returns the data you need - * @param idk some thing, idk just pass null + * @param dependencies An array of reactive values which the hook depends on. Use this if your mapper or equality function depends on the value of another hook * @param isEqual A custom comparator for the data returned by mapper * * @example const user = useStateFromStores([UserStore], () => UserStore.getCurrentUser(), null, (old, current) => old.id === current.id); */ -export const { useStateFromStores }: { - useStateFromStores: ( - stores: t.FluxStore[], - mapper: () => T, - idk?: any, - isEqual?: (old: T, newer: T) => boolean - ) => T; -} - = findByPropsLazy("useStateFromStores"); +// eslint-disable-next-line prefer-destructuring +export const useStateFromStores: t.useStateFromStores = findByPropsLazy("useStateFromStores").useStateFromStores; waitForStore("DraftStore", s => DraftStore = s); waitForStore("UserStore", s => UserStore = s); diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 8e89a6e20..d6bf3aaf3 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -182,3 +182,10 @@ export class GuildStore extends FluxStore { getRoles(guildId: string): Record; getAllGuildRoles(): Record>; } + +export type useStateFromStores = ( + stores: t.FluxStore[], + mapper: () => T, + dependencies?: any, + isEqual?: (old: T, newer: T) => boolean +) => T; From 799b903da94447bb6e62871977f1cd102cf9e06f Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 7 May 2024 22:40:14 +0200 Subject: [PATCH 058/134] Revert "messageLogger: fix niche bug ignoring edits when content is same (#2403)" This reverts commit 85d6d74a3e14ed4a1cc83c8131b83c08cfdce04a. As suspected, this code was actually necessary --- src/plugins/messageLogger/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 988cd8e39..c3a25e1b6 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -255,7 +255,7 @@ export default definePlugin({ replace: "$1" + ".update($3,m =>" + " (($2.message.flags & 64) === 64 || $self.shouldIgnore($2.message, true)) ? m :" + - " $2.message.content !== m.content ?" + + " $2.message.content !== m.editHistory?.[0]?.content && $2.message.content !== m.content ?" + " m.set('editHistory',[...(m.editHistory || []), $self.makeEdit($2.message, m)]) :" + " m" + ")" + From 53dda32fb045a0cb6ea7d65edda0111d61a8ba6f Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 21:36:40 -0300 Subject: [PATCH 059/134] BetterFolders: Fix broken patch --- src/plugins/betterFolders/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 70e4070cd..0b06d035c 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -127,7 +127,7 @@ export default definePlugin({ }, // If we are rendering the Better Folders sidebar, we filter out everything but the scroller for the guild list from the GuildsBar Tree children { - match: /unreadMentionsIndicatorBottom,barClassName.+?}\)\]/, + match: /unreadMentionsIndicatorBottom,.+?}\)\]/, replace: "$&.filter($self.makeGuildsBarTreeFilter(!!arguments[0].isBetterFolders))" }, // Export the isBetterFolders variable to the folders component From 21d2019e6032d78a922273ecba1c04c6576d9d53 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 02:43:46 +0200 Subject: [PATCH 060/134] improve SupportHelper --- src/plugins/_core/supportHelper.tsx | 118 ++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 674be8e53..63f32cbd2 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -16,20 +16,24 @@ * along with this program. If not, see . */ -import { DataStore } from "@api/index"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Link } from "@components/Link"; +import { openUpdaterModal } from "@components/VencordSettings/UpdaterTab"; import { Devs, SUPPORT_CHANNEL_ID } from "@utils/constants"; +import { Margins } from "@utils/margins"; import { isPluginDev } from "@utils/misc"; +import { relaunch } from "@utils/native"; import { makeCodeblock } from "@utils/text"; import definePlugin from "@utils/types"; -import { isOutdated } from "@utils/updater"; -import { Alerts, Forms, UserStore } from "@webpack/common"; +import { isOutdated, update } from "@utils/updater"; +import { Alerts, Card, ChannelStore, Forms, GuildMemberStore, NavigationRouter, Parser, RelationshipStore, UserStore } from "@webpack/common"; import gitHash from "~git-hash"; import plugins from "~plugins"; import settings from "./settings"; -const REMEMBER_DISMISS_KEY = "Vencord-SupportHelper-Dismiss"; +const VENCORD_GUILD_ID = "1015060230222131221"; const AllowedChannelIds = [ SUPPORT_CHANNEL_ID, @@ -37,6 +41,12 @@ const AllowedChannelIds = [ "1033680203433660458", // Vencord > #v ]; +const TrustedRolesIds = [ + "1026534353167208489", // contributor + "1026504932959977532", // regular + "1042507929485586532", // donor +]; + export default definePlugin({ name: "SupportHelper", required: true, @@ -44,6 +54,14 @@ export default definePlugin({ authors: [Devs.Ven], dependencies: ["CommandsAPI"], + patches: [{ + find: ".BEGINNING_DM.format", + replacement: { + match: /BEGINNING_DM\.format\(\{.+?\}\),(?=.{0,100}userId:(\i\.getRecipientId\(\)))/, + replace: "$& $self.ContributorDmWarningCard({ userId: $1 })," + } + }], + commands: [{ name: "vencord-debug", description: "Send Vencord Debug info", @@ -64,15 +82,13 @@ export default definePlugin({ const isApiPlugin = (plugin: string) => plugin.endsWith("API") || plugins[plugin].required; const enabledPlugins = Object.keys(plugins).filter(p => Vencord.Plugins.isPluginEnabled(p) && !isApiPlugin(p)); - const enabledApiPlugins = Object.keys(plugins).filter(p => Vencord.Plugins.isPluginEnabled(p) && isApiPlugin(p)); const info = { - Vencord: `v${VERSION} • ${gitHash}${settings.additionalInfo} - ${Intl.DateTimeFormat("en-GB", { dateStyle: "medium" }).format(BUILD_TIMESTAMP)}`, - "Discord Branch": RELEASE_CHANNEL, - Client: client, - Platform: window.navigator.platform, - Outdated: isOutdated, - OpenAsar: "openasar" in window, + Vencord: + `v${VERSION} • [${gitHash}]()` + + `${settings.additionalInfo} - ${Intl.DateTimeFormat("en-GB", { dateStyle: "medium" }).format(BUILD_TIMESTAMP)}`, + Client: `${RELEASE_CHANNEL} ~ ${client}`, + Platform: window.navigator.platform }; if (IS_DISCORD_DESKTOP) { @@ -80,11 +96,10 @@ export default definePlugin({ } const debugInfo = ` -**Vencord Debug Info** ->>> ${Object.entries(info).map(([k, v]) => `${k}: ${v}`).join("\n")} +>>> ${Object.entries(info).map(([k, v]) => `**${k}**: ${v}`).join("\n")} -Enabled Plugins (${enabledPlugins.length + enabledApiPlugins.length}): -${makeCodeblock(enabledPlugins.join(", ") + "\n\n" + enabledApiPlugins.join(", "))} +Enabled Plugins (${enabledPlugins.length}): +${makeCodeblock(enabledPlugins.join(", "))} `; return { @@ -97,24 +112,75 @@ ${makeCodeblock(enabledPlugins.join(", ") + "\n\n" + enabledApiPlugins.join(", " async CHANNEL_SELECT({ channelId }) { if (channelId !== SUPPORT_CHANNEL_ID) return; - if (isPluginDev(UserStore.getCurrentUser().id)) return; + const selfId = UserStore.getCurrentUser()?.id; + if (!selfId || isPluginDev(selfId)) return; - if (isOutdated && gitHash !== await DataStore.get(REMEMBER_DISMISS_KEY)) { - const rememberDismiss = () => DataStore.set(REMEMBER_DISMISS_KEY, gitHash); - - Alerts.show({ + if (isOutdated) { + return Alerts.show({ title: "Hold on!", body:
You are using an outdated version of Vencord! Chances are, your issue is already fixed. - - Please first update using the Updater Page in Settings, or use the VencordInstaller (Update Vencord Button) - to do so, in case you can't access the Updater page. + + Please first update before asking for support!
, - onCancel: rememberDismiss, - onConfirm: rememberDismiss + onCancel: () => openUpdaterModal!(), + cancelText: "View Updates", + confirmText: "Update & Restart Now", + async onConfirm() { + await update(); + relaunch(); + }, + secondaryConfirmText: "I know what I'm doing or I can't update" + }); + } + + // @ts-ignore outdated type + const roles = GuildMemberStore.getSelfMember(VENCORD_GUILD_ID)?.roles; + if (!roles || TrustedRolesIds.some(id => roles.includes(id))) return; + + if (IS_UPDATER_DISABLED) { + return Alerts.show({ + title: "Hold on!", + body:
+ You are using an externally updated Vencord version, which we do not provide support for! + + Please either switch to an officially supported version of Vencord, or + contact your package maintainer for support instead. + +
, + onCloseCallback: () => setTimeout(() => NavigationRouter.back(), 50) + }); + } + + const repo = await VencordNative.updater.getRepo(); + if (repo.ok && !repo.value.includes("Vendicated/Vencord")) { + return Alerts.show({ + title: "Hold on!", + body:
+ You are using a fork of Vencord, which we do not provide support for! + + Please either switch to an officially supported version of Vencord, or + contact your package maintainer for support instead. + +
, + onCloseCallback: () => setTimeout(() => NavigationRouter.back(), 50) }); } } - } + }, + + ContributorDmWarningCard: ErrorBoundary.wrap(({ userId }) => { + if (!isPluginDev(userId)) return null; + if (RelationshipStore.isFriend(userId)) return null; + + return ( + + Please do not private message Vencord plugin developers for support! +
+ Instead, use the Vencord support channel: {Parser.parse("https://discord.com/channels/1015060230222131221/1026515880080842772")} + {!ChannelStore.getChannel(SUPPORT_CHANNEL_ID) && " (Click the link to join)"} +
+ ); + }, { noop: true }) }); From e2dc9e75d162c54f20cf4a5d717d9688d125b482 Mon Sep 17 00:00:00 2001 From: kaitlynkitty <87152313+kaitlynkittyy@users.noreply.github.com> Date: Tue, 7 May 2024 21:17:42 -0400 Subject: [PATCH 061/134] new plugin WebScreenShareFixes: remove low stream bitrate limit (#2405) --- src/plugins/webScreenShareFixes.web/index.ts | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/plugins/webScreenShareFixes.web/index.ts diff --git a/src/plugins/webScreenShareFixes.web/index.ts b/src/plugins/webScreenShareFixes.web/index.ts new file mode 100644 index 000000000..8d1ab5821 --- /dev/null +++ b/src/plugins/webScreenShareFixes.web/index.ts @@ -0,0 +1,30 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +export default definePlugin({ + name: "WebScreenShareFixes", + authors: [Devs.Kaitlyn], + description: "Removes 2500kbps bitrate cap on chromium and vesktop clients.", + enabledByDefault: true, + patches: [ + { + find: "x-google-max-bitrate", + replacement: [ + { + match: /"x-google-max-bitrate=".concat\(\i\)/, + replace: '"x-google-max-bitrate=".concat("80_000")' + }, + { + match: /;level-asymmetry-allowed=1/, + replace: ";b=AS:800000;level-asymmetry-allowed=1" + } + ] + } + ] +}); From efca196deda743b4295b90b4e5e52320c8bd3d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Han=20Seung=20Min=20-=20=ED=95=9C=EC=8A=B9=EB=AF=BC?= Date: Wed, 8 May 2024 10:25:32 +0900 Subject: [PATCH 062/134] new plugin MessageLatency: indicator for other people's latency (#2353) --- src/plugins/messageLatency/README.md | 31 ++++++ src/plugins/messageLatency/index.tsx | 147 +++++++++++++++++++++++++++ src/utils/constants.ts | 4 + 3 files changed, 182 insertions(+) create mode 100644 src/plugins/messageLatency/README.md create mode 100644 src/plugins/messageLatency/index.tsx diff --git a/src/plugins/messageLatency/README.md b/src/plugins/messageLatency/README.md new file mode 100644 index 000000000..8d2a776cd --- /dev/null +++ b/src/plugins/messageLatency/README.md @@ -0,0 +1,31 @@ +# MessageLatency + +Displays an indicator for messages that took ≥n seconds to send. + +> **NOTE** +> +> - This plugin only applies to messages received after opening the channel +> - False positives can exist if the user's system clock has drifted. +> - Grouped messages only display latency of the first message + +## Demo + +### Chat View + +![chat-view](https://github.com/Vendicated/Vencord/assets/82430093/69430881-60b3-422f-aa3d-c62953837566) + +### Clock -ve Drift + +![pissbot-on-top](https://github.com/Vendicated/Vencord/assets/82430093/d9248b66-e761-4872-8829-e8bf4fea6ec8) + +### Clock +ve Drift + +![dumb-ai](https://github.com/Vendicated/Vencord/assets/82430093/0e9783cf-51d5-4559-ae10-42399e7d4099) + +### Connection Delay + +![who-this](https://github.com/Vendicated/Vencord/assets/82430093/fd68873d-8630-42cc-a166-e9063d2718b2) + +### Icons + +![icons](https://github.com/Vendicated/Vencord/assets/82430093/17630bd9-44ee-4967-bcdf-3315eb6eca85) diff --git a/src/plugins/messageLatency/index.tsx b/src/plugins/messageLatency/index.tsx new file mode 100644 index 000000000..0b6d75033 --- /dev/null +++ b/src/plugins/messageLatency/index.tsx @@ -0,0 +1,147 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import { isNonNullish } from "@utils/guards"; +import definePlugin, { OptionType } from "@utils/types"; +import { findExportedComponentLazy } from "@webpack"; +import { SnowflakeUtils, Tooltip } from "@webpack/common"; +import { Message } from "discord-types/general"; + +type FillValue = ("status-danger" | "status-warning" | "text-muted"); +type Fill = [FillValue, FillValue, FillValue]; +type DiffKey = keyof Diff; + +interface Diff { + days: number, + hours: number, + minutes: number, + seconds: number; +} + +const HiddenVisually = findExportedComponentLazy("HiddenVisually"); + +export default definePlugin({ + name: "MessageLatency", + description: "Displays an indicator for messages that took ≥n seconds to send", + authors: [Devs.arHSM], + settings: definePluginSettings({ + latency: { + type: OptionType.NUMBER, + description: "Threshold in seconds for latency indicator", + default: 2 + } + }), + patches: [ + { + find: "showCommunicationDisabledStyles", + replacement: { + match: /(message:(\i),avatar:\i,username:\(0,\i.jsxs\)\(\i.Fragment,\{children:\[)(\i&&)/, + replace: "$1$self.Tooltip()({ message: $2 }),$3" + } + } + ], + stringDelta(delta: number) { + const diff: Diff = { + days: Math.round(delta / (60 * 60 * 24)), + hours: Math.round((delta / (60 * 60)) % 24), + minutes: Math.round((delta / (60)) % 60), + seconds: Math.round(delta % 60), + }; + + const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${k}` : null; + const keys = Object.keys(diff) as DiffKey[]; + + return keys.map(str).filter(isNonNullish).join(" ") || "0 seconds"; + }, + latencyTooltipData(message: Message) { + const { id, nonce } = message; + + // Message wasn't received through gateway + if (!isNonNullish(nonce)) return null; + + const delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000); + + // Thanks dziurwa (I hate you) + // This is when the user's clock is ahead + // Can't do anything if the clock is behind + const abs = Math.abs(delta); + const ahead = abs !== delta; + + const stringDelta = this.stringDelta(abs); + + // Also thanks dziurwa + // 2 minutes + const TROLL_LIMIT = 2 * 60; + const { latency } = this.settings.store; + + const fill: Fill = delta >= TROLL_LIMIT || ahead ? ["text-muted", "text-muted", "text-muted"] : delta >= (latency * 2) ? ["status-danger", "text-muted", "text-muted"] : ["status-warning", "status-warning", "text-muted"]; + + return abs >= latency ? { delta: stringDelta, ahead: abs !== delta, fill } : null; + }, + Tooltip() { + return ErrorBoundary.wrap(({ message }: { message: Message; }) => { + + const d = this.latencyTooltipData(message); + + if (!isNonNullish(d)) return null; + + return + { + props => <> + {} + {/* Time Out indicator uses this, I think this is for a11y */} + Delayed Message + + } + ; + }); + }, + Icon({ delta, fill, props }: { + delta: string; + fill: Fill, + props: { + onClick(): void; + onMouseEnter(): void; + onMouseLeave(): void; + onContextMenu(): void; + onFocus(): void; + onBlur(): void; + "aria-label"?: string; + }; + }) { + return + + + + ; + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index cce276ef8..ab6c0bb70 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -266,6 +266,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "Dziurwa", id: 1001086404203389018n }, + arHSM: { + name: "arHSM", + id: 841509053422632990n + }, F53: { name: "F53", id: 280411966126948353n From d3acd7edc7d7972888f06ea6c919587d11e825ff Mon Sep 17 00:00:00 2001 From: Kyuuhachi <1547062+Kyuuhachi@users.noreply.github.com> Date: Wed, 8 May 2024 03:32:09 +0200 Subject: [PATCH 063/134] new plugin ReplyTimestamp: show timestamps of replied messages (#2296) Co-authored-by: vee --- src/plugins/replyTimestamp/README.md | 5 ++ src/plugins/replyTimestamp/index.tsx | 77 ++++++++++++++++++++++++++++ src/plugins/replyTimestamp/style.css | 3 ++ 3 files changed, 85 insertions(+) create mode 100644 src/plugins/replyTimestamp/README.md create mode 100644 src/plugins/replyTimestamp/index.tsx create mode 100644 src/plugins/replyTimestamp/style.css diff --git a/src/plugins/replyTimestamp/README.md b/src/plugins/replyTimestamp/README.md new file mode 100644 index 000000000..b7952bf3a --- /dev/null +++ b/src/plugins/replyTimestamp/README.md @@ -0,0 +1,5 @@ +# ReplyTimestamp + +Shows timestamps on the previews of replied-to messages. Pretty simple. + +![](https://github.com/Vendicated/Vencord/assets/1547062/62e2b67a-e567-4c7a-884d-4640f897f7e0) diff --git a/src/plugins/replyTimestamp/index.tsx b/src/plugins/replyTimestamp/index.tsx new file mode 100644 index 000000000..05ec28b1b --- /dev/null +++ b/src/plugins/replyTimestamp/index.tsx @@ -0,0 +1,77 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./style.css"; + +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { Timestamp } from "@webpack/common"; +import type { Message } from "discord-types/general"; +import type { HTMLAttributes } from "react"; + +const { getMessageTimestampId } = findByPropsLazy("getMessageTimestampId"); +const { calendarFormat, dateFormat, isSameDay } = findByPropsLazy("calendarFormat", "dateFormat", "isSameDay", "accessibilityLabelCalendarFormat"); +const MessageClasses = findByPropsLazy("separator", "latin24CompactTimeStamp"); + +function Sep(props: HTMLAttributes) { + return ; +} + +const enum ReferencedMessageState { + LOADED = 0, + NOT_LOADED = 1, + DELETED = 2, +} + +type ReferencedMessage = { state: ReferencedMessageState.LOADED; message: Message; } | { state: ReferencedMessageState.NOT_LOADED | ReferencedMessageState.DELETED; }; + +function ReplyTimestamp({ + referencedMessage, + baseMessage, +}: { + referencedMessage: ReferencedMessage, + baseMessage: Message; +}) { + if (referencedMessage.state !== ReferencedMessageState.LOADED) return null; + const refTimestamp = referencedMessage.message.timestamp as any; + const baseTimestamp = baseMessage.timestamp as any; + return ( + + [ + {isSameDay(refTimestamp, baseTimestamp) + ? dateFormat(refTimestamp, "LT") + : calendarFormat(refTimestamp) + } + ] + + ); +} + +export default definePlugin({ + name: "ReplyTimestamp", + description: "Shows a timestamp on replied-message previews", + authors: [Devs.Kyuuhachi], + + patches: [ + { + find: "renderSingleLineMessage:function()", + replacement: { + match: /(?<="aria-label":\i,children:\[)(?=\i,\i,\i\])/, + replace: "$self.ReplyTimestamp(arguments[0])," + } + } + ], + + ReplyTimestamp: ErrorBoundary.wrap(ReplyTimestamp, { noop: true }), +}); diff --git a/src/plugins/replyTimestamp/style.css b/src/plugins/replyTimestamp/style.css new file mode 100644 index 000000000..f42371717 --- /dev/null +++ b/src/plugins/replyTimestamp/style.css @@ -0,0 +1,3 @@ +.vc-reply-timestamp { + margin-right: 0.25em; +} From 1317222c35a4f6dd2b7329507c7b7ac5a9854d9e Mon Sep 17 00:00:00 2001 From: puv Date: Wed, 8 May 2024 04:44:57 +0300 Subject: [PATCH 064/134] feat(plugin): VoiceDownload (#2280) Co-authored-by: vee --- src/plugins/voiceDownload/index.tsx | 53 +++++++++++++++++++++++++++++ src/plugins/voiceDownload/style.css | 12 +++++++ src/utils/constants.ts | 4 +++ 3 files changed, 69 insertions(+) create mode 100644 src/plugins/voiceDownload/index.tsx create mode 100644 src/plugins/voiceDownload/style.css diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx new file mode 100644 index 000000000..453a522d3 --- /dev/null +++ b/src/plugins/voiceDownload/index.tsx @@ -0,0 +1,53 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./style.css"; + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + +export default definePlugin({ + name: "VoiceDownload", + description: "Adds a download to voice messages. (Opens a new browser tab)", + authors: [Devs.puv], + patches: [ + { + find: "rippleContainer,children", + replacement: { + match: /\(0,\i\.jsx\).{0,150},children:.{0,50}\("source",{src:(\i)}\)}\)/, + replace: "[$&, $self.renderDownload($1)]" + } + } + ], + + renderDownload(src: string) { + return ( + e.stopPropagation()} + aria-label="Download voice message" + > + + + ); + }, + + Icon: () => ( + + + + ), +}); diff --git a/src/plugins/voiceDownload/style.css b/src/plugins/voiceDownload/style.css new file mode 100644 index 000000000..2b776023f --- /dev/null +++ b/src/plugins/voiceDownload/style.css @@ -0,0 +1,12 @@ +.vc-voice-download { + width: 24px; + height: 24px; + color: var(--interactive-normal); + margin-left: 12px; + cursor: pointer; + position: relative; +} + +.vc-voice-download:hover { + color: var(--interactive-active); +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index ab6c0bb70..a0c4752dc 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -430,6 +430,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "newwares", id: 421405303951851520n }, + puv: { + name: "puv", + id: 469441552251355137n + }, Kodarru: { name: "Kodarru", id: 785227396218748949n From 5c787145e3a83dfe99ff4e595711298b96efe5d2 Mon Sep 17 00:00:00 2001 From: dolfies Date: Tue, 7 May 2024 21:50:26 -0400 Subject: [PATCH 065/134] showHiddenThings: also show ModView & hidden discovery servers (#2415) Co-authored-by: vee --- src/plugins/showHiddenThings/README.md | 6 ++++++ src/plugins/showHiddenThings/index.ts | 28 +++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/plugins/showHiddenThings/README.md b/src/plugins/showHiddenThings/README.md index b41e2d94d..e969391e4 100644 --- a/src/plugins/showHiddenThings/README.md +++ b/src/plugins/showHiddenThings/README.md @@ -9,3 +9,9 @@ Displays various moderator-only elements regardless of permissions. - Show the invites paused tooltip in the server list ![](https://github.com/Vendicated/Vencord/assets/47677887/b6a923d2-ac55-40d9-b4f8-fa6fc117148b) + +- Show the member mod view context menu item in all servers + +![](https://github.com/Vendicated/Vencord/assets/47677887/3dac95dd-841c-4c15-ad87-2db7bd1e4dab) + +- Disable filters in Server Discovery search that hide servers that don't meet discovery criteria diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index e7be929bf..1858582a8 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -31,12 +31,22 @@ const settings = definePluginSettings({ description: "Show the invites paused tooltip in the server list.", default: true, }, + showModView: { + type: OptionType.BOOLEAN, + description: "Show the member mod view context menu item in all servers.", + default: true, + }, + disableDiscoveryFilters: { + type: OptionType.BOOLEAN, + description: "Disable filters in Server Discovery search that hide servers that don't meet discovery criteria.", + default: true, + }, }); migratePluginSettings("ShowHiddenThings", "ShowTimeouts"); export default definePlugin({ name: "ShowHiddenThings", - tags: ["ShowTimeouts", "ShowInvitesPaused"], + tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"], description: "Displays various moderator-only elements regardless of permissions.", authors: [Devs.Dolfies], patches: [ @@ -55,6 +65,22 @@ export default definePlugin({ match: /\i\.\i\.can\(\i\.Permissions.MANAGE_GUILD,\i\)/, replace: "true", }, + }, + { + find: "canAccessGuildMemberModViewWithExperiment:", + predicate: () => settings.store.showModView, + replacement: { + match: /return \i\.hasAny\(\i\.computePermissions\(\{user:\i,context:\i,checkElevated:!1\}\),\i\.MemberSafetyPagePermissions\)/, + replace: "return true", + } + }, + { + find: "auto_removed:", + predicate: () => settings.store.disableDiscoveryFilters, + replacement: { + match: /filters:\i\.join\(" AND "\),facets:\[/, + replace: "facets:[" + } } ], settings, From dd3b7e534651bbe42fdd80b12c8b5815026760b7 Mon Sep 17 00:00:00 2001 From: KK2-5 <120592920+KK2-5@users.noreply.github.com> Date: Tue, 7 May 2024 22:55:32 -0300 Subject: [PATCH 066/134] LastfmRichPresence: Add option to use album name as status name (#2400) Co-authored-by: vee --- src/plugins/lastfm/index.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/lastfm/index.tsx b/src/plugins/lastfm/index.tsx index 5dfec8a32..1213ece29 100644 --- a/src/plugins/lastfm/index.tsx +++ b/src/plugins/lastfm/index.tsx @@ -77,7 +77,8 @@ const enum NameFormat { ArtistFirst = "artist-first", SongFirst = "song-first", ArtistOnly = "artist", - SongOnly = "song" + SongOnly = "song", + AlbumName = "album" } const applicationId = "1108588077900898414"; @@ -147,6 +148,10 @@ const settings = definePluginSettings({ { label: "Use song name only", value: NameFormat.SongOnly + }, + { + label: "Use album name (falls back to custom status text if song has no album)", + value: NameFormat.AlbumName } ], }, @@ -313,6 +318,8 @@ export default definePlugin({ return trackData.artist; case NameFormat.SongOnly: return trackData.name; + case NameFormat.AlbumName: + return trackData.album || settings.store.statusName; default: return settings.store.statusName; } From 449f95500ae3124f55bb51fe7e8f8e29e7fb10a2 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 03:56:25 +0200 Subject: [PATCH 067/134] bump to v1.8.2 --- package.json | 2 +- src/plugins/voiceDownload/index.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 97d3da576..9fd84f9b8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.1", + "version": "1.8.2", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index 453a522d3..8586b9f91 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -39,7 +39,6 @@ export default definePlugin({ Icon: () => ( Date: Wed, 8 May 2024 17:12:13 -0300 Subject: [PATCH 068/134] BetterFolders: Fix component erroring --- src/plugins/betterFolders/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 0b06d035c..d252682f8 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -279,7 +279,7 @@ export default definePlugin({ makeGuildsBarTreeFilter(isBetterFolders: boolean) { return child => { if (isBetterFolders) { - return "onScroll" in child.props; + return child?.props?.onScroll != null; } return true; }; From b1cc67a860fe2b6546900797dfa49a936b97f7dd Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:42:04 +0200 Subject: [PATCH 069/134] fix(BetterSettings): do not catch errors of other ui --- src/plugins/betterSettings/index.tsx | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 7d81c6f5c..5836734ef 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -6,8 +6,8 @@ import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; @@ -124,12 +124,23 @@ export default definePlugin({ } ], + // This is the very outer layer of the entire ui, so we can't wrap this in an ErrorBoundary + // without possibly also catching unrelated errors of children. + // + // Thus, we sanity check webpack modules & do this really hacky try catch to hopefully prevent hard crashes if something goes wrong. + // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but + // not in children Layer(props: LayerProps) { - return ( - props.children as any}> - - - ); + try { + if (!FocusLock || !ComponentDispatch) + throw new Error("Failed to fetch some webpack modules"); + + return Layer(props); + } catch (e) { + new Logger("BetterSettings").error("Failed to render Layer", e); + } + + return props.children; }, wrapMenu(list: SettingsEntry[]) { From 025193533d1baf0e37df236cbda97f2f539e8b20 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:49:47 +0200 Subject: [PATCH 070/134] VoiceDownload: fix doing nothing on discord desktop app --- src/plugins/voiceDownload/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/voiceDownload/index.tsx b/src/plugins/voiceDownload/index.tsx index 8586b9f91..571c3d0e9 100644 --- a/src/plugins/voiceDownload/index.tsx +++ b/src/plugins/voiceDownload/index.tsx @@ -28,9 +28,12 @@ export default definePlugin({ e.stopPropagation()} aria-label="Download voice message" + {...IS_DISCORD_DESKTOP + ? { target: "_blank" } // open externally + : { download: "voice-message.ogg" } // download directly (not supported on discord desktop) + } > From 6bd0898efe489901178e45012a586c991947a068 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 8 May 2024 23:52:28 +0200 Subject: [PATCH 071/134] fix(SupportHelper): dont flag vencord web as externally updated --- src/plugins/_core/supportHelper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index 63f32cbd2..c7377833a 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -139,7 +139,7 @@ ${makeCodeblock(enabledPlugins.join(", "))} const roles = GuildMemberStore.getSelfMember(VENCORD_GUILD_ID)?.roles; if (!roles || TrustedRolesIds.some(id => roles.includes(id))) return; - if (IS_UPDATER_DISABLED) { + if (!IS_WEB && IS_UPDATER_DISABLED) { return Alerts.show({ title: "Hold on!", body:
From 840a8f1fdd6e9f16c8ac44a2f21b09fb873a141f Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 18:37:27 -0300 Subject: [PATCH 072/134] CrashHandler: Increment timeout for trying to recover --- src/plugins/crashHandler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index f8c76d7f7..10053021f 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -104,7 +104,7 @@ export default definePlugin({ shouldAttemptRecover = false; // This is enough to avoid a crash loop - setTimeout(() => shouldAttemptRecover = true, 500); + setTimeout(() => shouldAttemptRecover = true, 1000); } catch { } try { From a2acce55c34ddf3e0eafdfe7ecf747dcee859fb5 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:04:03 +0200 Subject: [PATCH 073/134] BetterSettings: fix error handling crashing in some niche cases --- src/plugins/betterSettings/index.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 5836734ef..c9bf070fa 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -131,16 +131,11 @@ export default definePlugin({ // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but // not in children Layer(props: LayerProps) { - try { - if (!FocusLock || !ComponentDispatch) - throw new Error("Failed to fetch some webpack modules"); - - return Layer(props); - } catch (e) { - new Logger("BetterSettings").error("Failed to render Layer", e); + if (!FocusLock || !ComponentDispatch) { + new Logger("BetterSettings").error("Failed to find some components"); } - return props.children; + return ; }, wrapMenu(list: SettingsEntry[]) { From 251ee32e01ab70a6ec1c6a6a003c89682edca21b Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:10:07 +0200 Subject: [PATCH 074/134] new plugin ShowTimeoutDuration ~ shows how much longer a user's timeout will last --- src/plugins/showTimeoutDuration/README.md | 8 ++ src/plugins/showTimeoutDuration/index.tsx | 106 +++++++++++++++++++++ src/plugins/showTimeoutDuration/styles.css | 4 + 3 files changed, 118 insertions(+) create mode 100644 src/plugins/showTimeoutDuration/README.md create mode 100644 src/plugins/showTimeoutDuration/index.tsx create mode 100644 src/plugins/showTimeoutDuration/styles.css diff --git a/src/plugins/showTimeoutDuration/README.md b/src/plugins/showTimeoutDuration/README.md new file mode 100644 index 000000000..137802473 --- /dev/null +++ b/src/plugins/showTimeoutDuration/README.md @@ -0,0 +1,8 @@ +# ShowTimeoutDuration + +Displays how much longer a user's timeout will last. +Either in the timeout icon tooltip, or next to it, configurable via settings! + +![indicator in tooltip](https://github.com/Vendicated/Vencord/assets/45497981/606588a3-2646-40d9-8800-b6307f650136) + +![indicator next to timeout icon](https://github.com/Vendicated/Vencord/assets/45497981/ab9d2101-0fdc-4143-9310-9488f056eeee) diff --git a/src/plugins/showTimeoutDuration/index.tsx b/src/plugins/showTimeoutDuration/index.tsx new file mode 100644 index 000000000..f57ee0fc9 --- /dev/null +++ b/src/plugins/showTimeoutDuration/index.tsx @@ -0,0 +1,106 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import "./styles.css"; + +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import { Margins } from "@utils/margins"; +import definePlugin, { OptionType } from "@utils/types"; +import { findComponentLazy } from "@webpack"; +import { ChannelStore, Forms, GuildMemberStore, i18n, Text, Tooltip } from "@webpack/common"; +import { Message } from "discord-types/general"; + +const CountDown = findComponentLazy(m => m.prototype?.render?.toString().includes(".MAX_AGE_NEVER")); + +const enum DisplayStyle { + Tooltip = "tooltip", + Inline = "ssalggnikool" +} + +const settings = definePluginSettings({ + displayStyle: { + description: "How to display the timeout duration", + type: OptionType.SELECT, + restartNeeded: true, + options: [ + { label: "In the Tooltip", value: DisplayStyle.Tooltip }, + { label: "Next to the timeout icon", value: DisplayStyle.Inline, default: true }, + ], + } +}); + +function renderTimeout(message: Message, inline: boolean) { + const guildId = ChannelStore.getChannel(message.channel_id)?.guild_id; + if (!guildId) return null; + + const member = GuildMemberStore.getMember(guildId, message.author.id); + if (!member?.communicationDisabledUntil) return null; + + const countdown = () => ( + + ); + + return inline + ? countdown() + : i18n.Messages.GUILD_ENABLE_COMMUNICATION_TIME_REMAINING.format({ + username: message.author.username, + countdown + }); +} + +export default definePlugin({ + name: "ShowTimeoutDuration", + description: "Shows how much longer a user's timeout will last, either in the timeout icon tooltip or next to it", + authors: [Devs.Ven], + + settings, + + patches: [ + { + find: ".GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY", + replacement: [ + { + match: /(\i)\.Tooltip,{(text:.{0,30}\.Messages\.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY)/, + get replace() { + if (settings.store.displayStyle === DisplayStyle.Inline) + return "$self.TooltipWrapper,{vcProps:arguments[0],$2"; + + return "$1.Tooltip,{text:$self.renderTimeoutDuration(arguments[0])"; + } + } + ] + } + ], + + renderTimeoutDuration: ErrorBoundary.wrap(({ message }: { message: Message; }) => { + return ( + <> + {i18n.Messages.GUILD_COMMUNICATION_DISABLED_ICON_TOOLTIP_BODY} + + {renderTimeout(message, false)} + + + ); + }, { noop: true }), + + TooltipWrapper: ErrorBoundary.wrap(({ vcProps: { message }, ...tooltipProps }: { vcProps: { message: Message; }; }) => { + return ( +
+ + + + {renderTimeout(message, true)} timeout remaining + +
+ ); + }, { noop: true }) +}); diff --git a/src/plugins/showTimeoutDuration/styles.css b/src/plugins/showTimeoutDuration/styles.css new file mode 100644 index 000000000..70a826e10 --- /dev/null +++ b/src/plugins/showTimeoutDuration/styles.css @@ -0,0 +1,4 @@ +.vc-std-wrapper { + display: flex; + align-items: center; +} From 14e68d9a246006122d2b1a4e2a17a53d955cbbca Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:12:11 +0200 Subject: [PATCH 075/134] im the dumbest dumdum --- src/plugins/betterSettings/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index c9bf070fa..5064bd538 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -9,14 +9,15 @@ import { classNameFactory } from "@api/Styles"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { waitFor } from "@webpack"; import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; type SettingsEntry = { section: string, label: string; }; const cl = classNameFactory(""); -const Classes = findByPropsLazy("animating", "baseLayer", "bg", "layer", "layers"); +let Classes: Record; +waitFor(["animating", "baseLayer", "bg", "layer", "layers"], m => Classes = m); const settings = definePluginSettings({ disableFade: { @@ -131,8 +132,9 @@ export default definePlugin({ // try catch will only catch errors in the Layer function (hence why it's called as a plain function rather than a component), but // not in children Layer(props: LayerProps) { - if (!FocusLock || !ComponentDispatch) { + if (!FocusLock || !ComponentDispatch || !Classes) { new Logger("BetterSettings").error("Failed to find some components"); + return props.children; } return ; From 1a3a378fb15adae9d0240773dd301ff88fe434da Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 9 May 2024 03:14:20 -0300 Subject: [PATCH 076/134] ErrorBoundary some more components --- src/plugins/betterNotes/index.tsx | 5 ++++- .../imageZoom/components/Magnifier.tsx | 5 +++-- src/plugins/mutualGroupDMs/index.tsx | 5 +++-- src/plugins/pauseInvitesForever/index.tsx | 20 ++++++++++--------- .../readAllNotificationsButton/index.tsx | 3 ++- src/plugins/showMeYourName/index.tsx | 11 +++++----- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index 2183d98e2..5ebca1f8b 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -17,6 +17,7 @@ */ import { Settings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; @@ -83,7 +84,9 @@ export default definePlugin({ patchPadding(lastSection: any) { if (!lastSection) return; return ( -
+ +
+
); } }); diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index 816717350..aadd0903a 100644 --- a/src/plugins/imageZoom/components/Magnifier.tsx +++ b/src/plugins/imageZoom/components/Magnifier.tsx @@ -17,6 +17,7 @@ */ import { classNameFactory } from "@api/Styles"; +import ErrorBoundary from "@components/ErrorBoundary"; import { FluxDispatcher, React, useRef, useState } from "@webpack/common"; import { ELEMENT_ID } from "../constants"; @@ -36,7 +37,7 @@ export interface MagnifierProps { const cl = classNameFactory("vc-imgzoom-"); -export const Magnifier: React.FC = ({ instance, size: initialSize, zoom: initalZoom }) => { +export const Magnifier = ErrorBoundary.wrap(({ instance, size: initialSize, zoom: initalZoom }) => { const [ready, setReady] = useState(false); const [lensPosition, setLensPosition] = useState({ x: 0, y: 0 }); @@ -199,4 +200,4 @@ export const Magnifier: React.FC = ({ instance, size: initialSiz )}
); -}; +}, { noop: true }); diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index 1753fefbc..e787fefb4 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { isNonNullish } from "@utils/guards"; import definePlugin from "@utils/types"; @@ -60,7 +61,7 @@ export default definePlugin({ } ], - renderMutualGDMs(user: User, onClose: () => void) { + renderMutualGDMs: ErrorBoundary.wrap((user: User, onClose: () => void) => { const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => ( ); - } + }) }); diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 81f18fd6e..1e71a4ed1 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -16,12 +16,12 @@ * along with this program. If not, see . */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { GuildStore, RestAPI } from "@webpack/common"; +import { GuildStore, i18n, RestAPI } from "@webpack/common"; -const Messages = findByPropsLazy("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); export default definePlugin({ @@ -62,13 +62,15 @@ export default definePlugin({ renderInvitesLabel(guildId: string, setChecked: Function) { return ( -
- {Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} - {this.showDisableInvites(guildId) && { - setChecked(true); - this.disableInvites(guildId); - }}> Pause Indefinitely.} -
+ +
+ {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {this.showDisableInvites(guildId) && { + setChecked(true); + this.disableInvites(guildId); + }}> Pause Indefinitely.} +
+
); } }); diff --git a/src/plugins/readAllNotificationsButton/index.tsx b/src/plugins/readAllNotificationsButton/index.tsx index ae66e11a4..3bf53f993 100644 --- a/src/plugins/readAllNotificationsButton/index.tsx +++ b/src/plugins/readAllNotificationsButton/index.tsx @@ -19,6 +19,7 @@ import "./style.css"; import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common"; @@ -64,7 +65,7 @@ export default definePlugin({ authors: [Devs.kemo], dependencies: ["ServerListAPI"], - renderReadAllButton: () => , + renderReadAllButton: ErrorBoundary.wrap(ReadAllButton, { noop: true }), start() { addServerListElement(ServerListRenderPosition.Above, this.renderReadAllButton); diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index a9db1af9a..7ba245da5 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -7,6 +7,7 @@ import "./styles.css"; import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Message, User } from "discord-types/general"; @@ -56,7 +57,7 @@ export default definePlugin({ ], settings, - renderUsername: ({ author, message, isRepliedMessage, withMentionPrefix, userOverride }: UsernameProps) => { + renderUsername: ErrorBoundary.wrap(({ author, message, isRepliedMessage, withMentionPrefix, userOverride }: UsernameProps) => { try { const user = userOverride ?? message.author; let { username } = user; @@ -66,14 +67,14 @@ export default definePlugin({ const { nick } = author; const prefix = withMentionPrefix ? "@" : ""; if (username === nick || isRepliedMessage && !settings.store.inReplies) - return prefix + nick; + return <>{prefix}{nick}; if (settings.store.mode === "user-nick") return <>{prefix}{username} {nick}; if (settings.store.mode === "nick-user") return <>{prefix}{nick} {username}; - return prefix + username; + return <>{prefix}{username}; } catch { - return author?.nick; + return <>{author?.nick}; } - }, + }, { noop: true }), }); From 395b0007bf15255f6c3e29586d4e56ffc16d3624 Mon Sep 17 00:00:00 2001 From: DShadow <62884000+CatGirlDShadow@users.noreply.github.com> Date: Sat, 11 May 2024 18:43:34 +0300 Subject: [PATCH 077/134] permissionsViewer: add role & user context menus to copy id (#2436) Co-authored-by: V --- .../components/RolesAndUsersPermissions.tsx | 69 ++++++++++++++----- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx index c2e50cedd..963750fa3 100644 --- a/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx +++ b/src/plugins/permissionsViewer/components/RolesAndUsersPermissions.tsx @@ -21,7 +21,7 @@ import { Flex } from "@components/Flex"; import { InfoIcon, OwnerCrownIcon } from "@components/Icons"; import { getUniqueUsername } from "@utils/discord"; import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, Menu, PermissionsBits, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common"; +import { Clipboard, ContextMenuApi, FluxDispatcher, GuildMemberStore, GuildStore, i18n, Menu, PermissionsBits, Text, Tooltip, useEffect, UserStore, useState, useStateFromStores } from "@webpack/common"; import type { Guild } from "discord-types/general"; import { settings } from ".."; @@ -112,7 +112,7 @@ function RolesAndUsersPermissionsComponent({ permissions, guild, modalProps, hea
{ - if ((settings.store as any).unsafeViewAsRole && permission.type === PermissionType.Role) + if (permission.type === PermissionType.Role) ContextMenuApi.openContextMenu(e, () => ( )); + else if (permission.type === PermissionType.User) { + ContextMenuApi.openContextMenu(e, () => ( + + )); + } }} > {(permission.type === PermissionType.Role || permission.type === PermissionType.Owner) && ( @@ -200,24 +208,53 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str aria-label="Role Options" > { - const role = GuildStore.getRole(guild.id, roleId); - if (!role) return; + Clipboard.copy(roleId); + }} + /> - onClose(); + {(settings.store as any).unsafeViewAsRole && ( + { + const role = GuildStore.getRole(guild.id, roleId); + if (!role) return; - FluxDispatcher.dispatch({ - type: "IMPERSONATE_UPDATE", - guildId: guild.id, - data: { - type: "ROLES", - roles: { - [roleId]: role + onClose(); + + FluxDispatcher.dispatch({ + type: "IMPERSONATE_UPDATE", + guildId: guild.id, + data: { + type: "ROLES", + roles: { + [roleId]: role + } } - } - }); + }); + } + } + /> + )} + + ); +} + +function UserContextMenu({ userId, onClose }: { userId: string; onClose: () => void; }) { + return ( + + { + Clipboard.copy(userId); }} /> From fbaa4ad5bcd32788a1d9f891be56dd71f93c9448 Mon Sep 17 00:00:00 2001 From: nyan <24845294+nyakowint@users.noreply.github.com> Date: Sat, 11 May 2024 12:05:22 -0400 Subject: [PATCH 078/134] XSOverlay: add settings for different notification types (#2055) Co-authored-by: vee --- src/plugins/xsOverlay.desktop/index.ts | 69 ++++++++++++++++++-------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts index 763f6a782..b666d1168 100644 --- a/src/plugins/xsOverlay.desktop/index.ts +++ b/src/plugins/xsOverlay.desktop/index.ts @@ -1,6 +1,6 @@ /* * Vencord, a Discord client mod - * Copyright (c) 2023 Vendicated and contributors + * Copyright (c) 2024 Vendicated and contributors * SPDX-License-Identifier: GPL-3.0-or-later */ @@ -13,10 +13,7 @@ import { findByPropsLazy } from "@webpack"; import { ChannelStore, GuildStore, UserStore } from "@webpack/common"; import type { Channel, Embed, GuildMember, MessageAttachment, User } from "discord-types/general"; -const enum ChannelTypes { - DM = 1, - GROUP_DM = 3 -} +const { ChannelTypes } = findByPropsLazy("ChannelTypes"); interface Message { guild_id: string, @@ -72,14 +69,35 @@ interface Call { } const MuteStore = findByPropsLazy("isSuppressEveryoneEnabled"); +const Notifs = findByPropsLazy("makeTextChatNotification"); const XSLog = new Logger("XSOverlay"); const settings = definePluginSettings({ - ignoreBots: { + botNotifications: { type: OptionType.BOOLEAN, - description: "Ignore messages from bots", + description: "Allow bot notifications", default: false }, + serverNotifications: { + type: OptionType.BOOLEAN, + description: "Allow server notifications", + default: true + }, + dmNotifications: { + type: OptionType.BOOLEAN, + description: "Allow Direct Message notifications", + default: true + }, + groupDmNotifications: { + type: OptionType.BOOLEAN, + description: "Allow Group DM notifications", + default: true + }, + callNotifications: { + type: OptionType.BOOLEAN, + description: "Allow call notifications", + default: true + }, pingColor: { type: OptionType.STRING, description: "User mention color", @@ -100,6 +118,11 @@ const settings = definePluginSettings({ description: "Notif duration (secs)", default: 1.0, }, + timeoutPerCharacter: { + type: OptionType.NUMBER, + description: "Duration multiplier per character", + default: 0.5 + }, opacity: { type: OptionType.SLIDER, description: "Notif opacity", @@ -124,7 +147,7 @@ export default definePlugin({ settings, flux: { CALL_UPDATE({ call }: { call: Call; }) { - if (call?.ringing?.includes(UserStore.getCurrentUser().id)) { + if (call?.ringing?.includes(UserStore.getCurrentUser().id) && settings.store.callNotifications) { const channel = ChannelStore.getChannel(call.channel_id); sendOtherNotif("Incoming call", `${channel.name} is calling you...`); } @@ -134,7 +157,7 @@ export default definePlugin({ try { if (optimistic) return; const channel = ChannelStore.getChannel(message.channel_id); - if (!shouldNotify(message, channel)) return; + if (!shouldNotify(message, message.channel_id)) return; const pingColor = settings.store.pingColor.replaceAll("#", "").trim(); const channelPingColor = settings.store.channelPingColor.replaceAll("#", "").trim(); @@ -194,6 +217,7 @@ export default definePlugin({ finalMsg = finalMsg.replace(/<@!?(\d{17,20})>/g, (_, id) => `@${UserStore.getUser(id)?.username || "unknown-user"}`); } + // color role mentions (unity styling btw lol) if (message.mention_roles.length > 0) { for (const roleId of message.mention_roles) { const role = GuildStore.getRole(channel.guild_id, roleId); @@ -213,6 +237,7 @@ export default definePlugin({ } } + // color channel mentions if (channelMatches) { for (const cMatch of channelMatches) { let channelId = cMatch.split("<#")[1]; @@ -221,6 +246,7 @@ export default definePlugin({ } } + if (shouldIgnoreForChannelType(channel)) return; sendMsgNotif(titleString, finalMsg, message); } catch (err) { XSLog.error(`Failed to catch MESSAGE_CREATE: ${err}`); @@ -229,13 +255,20 @@ export default definePlugin({ } }); +function shouldIgnoreForChannelType(channel: Channel) { + if (channel.type === ChannelTypes.DM && settings.store.dmNotifications) return false; + if (channel.type === ChannelTypes.GROUP_DM && settings.store.groupDmNotifications) return false; + else return !settings.store.serverNotifications; +} + function sendMsgNotif(titleString: string, content: string, message: Message) { + const timeout = Math.max(settings.store.timeout, content.length * settings.store.timeoutPerCharacter); fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => { const msgData = { messageType: 1, index: 0, - timeout: settings.store.timeout, - height: calculateHeight(cleanMessage(content)), + timeout, + height: calculateHeight(content), opacity: settings.store.opacity, volume: settings.store.volume, audioPath: settings.store.soundPath, @@ -254,7 +287,7 @@ function sendOtherNotif(content: string, titleString: string) { messageType: 1, index: 0, timeout: settings.store.timeout, - height: calculateHeight(cleanMessage(content)), + height: calculateHeight(content), opacity: settings.store.opacity, volume: settings.store.volume, audioPath: settings.store.soundPath, @@ -267,13 +300,11 @@ function sendOtherNotif(content: string, titleString: string) { Native.sendToOverlay(msgData); } -function shouldNotify(message: Message, channel: Channel) { +function shouldNotify(message: Message, channel: string) { const currentUser = UserStore.getCurrentUser(); if (message.author.id === currentUser.id) return false; - if (message.author.bot && settings.store.ignoreBots) return false; - if (MuteStore.allowAllMessages(channel) || message.mention_everyone && !MuteStore.isSuppressEveryoneEnabled(message.guild_id)) return true; - - return message.mentions.some(m => m.id === currentUser.id); + if (message.author.bot && !settings.store.botNotifications) return false; + return Notifs.shouldNotify(message, channel); } function calculateHeight(content: string) { @@ -282,7 +313,3 @@ function calculateHeight(content: string) { if (content.length <= 300) return 200; return 250; } - -function cleanMessage(content: string) { - return content.replace(new RegExp("<[^>]*>", "g"), ""); -} From 6b88eaccbb82dee8ff4bedbc29adad7cd1782be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Han=20Seung=20Min=20-=20=ED=95=9C=EC=8A=B9=EB=AF=BC?= Date: Sun, 12 May 2024 01:09:48 +0900 Subject: [PATCH 079/134] messageLatency: fix grammar & add aliucord/kotlin client tooltip (#2426) --- src/plugins/messageLatency/index.tsx | 35 ++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/plugins/messageLatency/index.tsx b/src/plugins/messageLatency/index.tsx index 0b6d75033..48b57863e 100644 --- a/src/plugins/messageLatency/index.tsx +++ b/src/plugins/messageLatency/index.tsx @@ -13,7 +13,7 @@ import { findExportedComponentLazy } from "@webpack"; import { SnowflakeUtils, Tooltip } from "@webpack/common"; import { Message } from "discord-types/general"; -type FillValue = ("status-danger" | "status-warning" | "text-muted"); +type FillValue = ("status-danger" | "status-warning" | "status-positive" | "text-muted"); type Fill = [FillValue, FillValue, FillValue]; type DiffKey = keyof Diff; @@ -54,10 +54,24 @@ export default definePlugin({ seconds: Math.round(delta % 60), }; - const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${k}` : null; + const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${diff[k] > 1 ? k : k.substring(0, k.length - 1)}` : null; const keys = Object.keys(diff) as DiffKey[]; - return keys.map(str).filter(isNonNullish).join(" ") || "0 seconds"; + const ts = keys.reduce((prev, k) => { + const s = str(k); + + return prev + ( + isNonNullish(s) + ? (prev !== "" + ? k === "seconds" + ? " and " + : " " + : "") + s + : "" + ); + }, ""); + + return [ts || "0 seconds", diff.days === 17 && diff.hours === 1] as const; }, latencyTooltipData(message: Message) { const { id, nonce } = message; @@ -73,16 +87,23 @@ export default definePlugin({ const abs = Math.abs(delta); const ahead = abs !== delta; - const stringDelta = this.stringDelta(abs); + const [stringDelta, isSuspectedKotlinDiscord] = this.stringDelta(abs); + const isKotlinDiscord = ahead && isSuspectedKotlinDiscord; // Also thanks dziurwa // 2 minutes const TROLL_LIMIT = 2 * 60; const { latency } = this.settings.store; - const fill: Fill = delta >= TROLL_LIMIT || ahead ? ["text-muted", "text-muted", "text-muted"] : delta >= (latency * 2) ? ["status-danger", "text-muted", "text-muted"] : ["status-warning", "status-warning", "text-muted"]; + const fill: Fill = isKotlinDiscord + ? ["status-positive", "status-positive", "text-muted"] + : delta >= TROLL_LIMIT || ahead + ? ["text-muted", "text-muted", "text-muted"] + : delta >= (latency * 2) + ? ["status-danger", "text-muted", "text-muted"] + : ["status-warning", "status-warning", "text-muted"]; - return abs >= latency ? { delta: stringDelta, ahead: abs !== delta, fill } : null; + return abs >= latency ? { delta: stringDelta, ahead, fill, isKotlinDiscord } : null; }, Tooltip() { return ErrorBoundary.wrap(({ message }: { message: Message; }) => { @@ -92,7 +113,7 @@ export default definePlugin({ if (!isNonNullish(d)) return null; return { From 2eb8ba18410188715ecdeea80b4b5b046204e153 Mon Sep 17 00:00:00 2001 From: Im_Banana <67657872+ImBonana@users.noreply.github.com> Date: Sat, 11 May 2024 23:49:00 +0300 Subject: [PATCH 080/134] SilentTyping: add chat input context menu option to toggle (#2386) Co-authored-by: vee --- src/plugins/silentTyping/index.tsx | 36 +++++++++++++++++++++++++++--- src/utils/constants.ts | 4 ++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index 8b59c6ace..2a6a64283 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -18,10 +18,11 @@ import { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatButtons"; import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; +import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { FluxDispatcher, React } from "@webpack/common"; +import { FluxDispatcher, Menu, React } from "@webpack/common"; const settings = definePluginSettings({ showIcon: { @@ -30,6 +31,11 @@ const settings = definePluginSettings({ description: "Show an icon for toggling the plugin", restartNeeded: true, }, + contextMenu: { + type: OptionType.BOOLEAN, + description: "Add option to toggle the functionality in the chat input context menu", + default: true + }, isEnabled: { type: OptionType.BOOLEAN, description: "Toggle functionality", @@ -56,13 +62,37 @@ const SilentTypingToggle: ChatBarButton = ({ isMainChat }) => { ); }; + +const ChatBarContextCheckbox: NavContextMenuPatchCallback = children => { + const { isEnabled, contextMenu } = settings.use(["isEnabled", "contextMenu"]); + if (!contextMenu) return; + + const group = findGroupChildrenByChildId("submit-button", children); + + if (!group) return; + + const idx = group.findIndex(c => c?.props?.id === "submit-button"); + + group.splice(idx + 1, 0, + settings.store.isEnabled = !settings.store.isEnabled} + /> + ); +}; + + export default definePlugin({ name: "SilentTyping", - authors: [Devs.Ven, Devs.Rini], + authors: [Devs.Ven, Devs.Rini, Devs.ImBanana], description: "Hide that you are typing", dependencies: ["CommandsAPI", "ChatInputButtonAPI"], settings, - + contextMenus: { + "textarea-context": ChatBarContextCheckbox + }, patches: [ { find: '.dispatch({type:"TYPING_START_LOCAL"', diff --git a/src/utils/constants.ts b/src/utils/constants.ts index a0c4752dc..6d9950a98 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -461,6 +461,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ GabiRP: { name: "GabiRP", id: 507955112027750401n + }, + ImBanana: { + name: "Im_Banana", + id: 635250116688871425n } } satisfies Record); From 9b328da4ce2363fa0e9e2fc24795d09597df1ab7 Mon Sep 17 00:00:00 2001 From: Overcast Warmth System <110815694+OvercastWarmth@users.noreply.github.com> Date: Sun, 12 May 2024 06:57:48 +1000 Subject: [PATCH 081/134] ThemeAttributes: add data-author-username to messages (#2422) --- src/plugins/themeAttributes/README.md | 1 + src/plugins/themeAttributes/index.ts | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/themeAttributes/README.md b/src/plugins/themeAttributes/README.md index 110eca574..87cb803c5 100644 --- a/src/plugins/themeAttributes/README.md +++ b/src/plugins/themeAttributes/README.md @@ -15,6 +15,7 @@ This allows themes to more easily theme those elements or even do things that ot ### Chat Messages - `data-author-id` contains the id of the author +- `data-author-username` contains the username of the author - `data-is-self` is a boolean indicating whether this is the current user's message ![image](https://github.com/Vendicated/Vencord/assets/45497981/34bd5053-3381-402f-82b2-9c812cc7e122) diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index 8afc2121f..b8ceac621 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -36,10 +36,12 @@ export default definePlugin({ ], getMessageProps(props: { message: Message; }) { - const authorId = props.message?.author?.id; + const author = props.message?.author; + const authorId = author?.id; return { "data-author-id": authorId, - "data-is-self": authorId && authorId === UserStore.getCurrentUser()?.id + "data-author-username": author?.username, + "data-is-self": authorId && authorId === UserStore.getCurrentUser()?.id, }; } }); From 207fe846367afc7ed75104968e52d47550a1cc08 Mon Sep 17 00:00:00 2001 From: nin0dev Date: Sat, 11 May 2024 17:29:31 -0400 Subject: [PATCH 082/134] CustomRPC: show warning when game activity is disabled (#2245) Co-authored-by: V --- src/plugins/customRPC/index.tsx | 30 +++++++++++++++++++++++++++--- src/utils/constants.ts | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index 334372e38..f1b2fbf53 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -17,13 +17,16 @@ */ import { definePluginSettings, Settings } from "@api/Settings"; +import { ErrorCard } from "@components/ErrorCard"; import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; import { isTruthy } from "@utils/guards"; +import { Margins } from "@utils/margins"; +import { classes } from "@utils/misc"; import { useAwaiter } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; -import { ApplicationAssetUtils, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; +import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, StatusSettingsStores, UserStore } from "@webpack/common"; const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color"); const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile"); @@ -386,17 +389,36 @@ async function setRpc(disable?: boolean) { export default definePlugin({ name: "CustomRPC", description: "Allows you to set a custom rich presence.", - authors: [Devs.captain, Devs.AutumnVN], + authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev], start: setRpc, stop: () => setRpc(true), settings, settingsAboutComponent: () => { const activity = useAwaiter(createActivity); + const gameActivityEnabled = StatusSettingsStores.ShowCurrentGame.useSetting(); const { profileThemeStyle } = useProfileThemeStyle({}); return ( <> + {!gameActivityEnabled && ( + + Notice + Game activity isn't enabled, people won't be able to see your custom rich presence! + + + + )} + Go to Discord Developer Portal to create an application and get the application ID. @@ -407,7 +429,9 @@ export default definePlugin({ If you want to use image link, download your image and reupload the image to Imgur and get the image link by right-clicking the image and select "Copy image address". - + + +
{activity[0] && Date: Sat, 11 May 2024 18:34:47 -0300 Subject: [PATCH 083/134] FakeNitro: Update description --- src/plugins/fakeNitro/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 03feda0a8..ea171c833 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -190,7 +190,7 @@ const hasAttachmentPerms = (channelId: string) => hasPermission(channelId, Permi export default definePlugin({ name: "FakeNitro", authors: [Devs.Arjix, Devs.D3SOX, Devs.Ven, Devs.fawn, Devs.captain, Devs.Nuckyz, Devs.AutumnVN], - description: "Allows you to stream in nitro quality, send fake emojis/stickers and use client themes.", + description: "Allows you to stream in nitro quality, send fake emojis/stickers, use client themes and custom Discord notifications.", dependencies: ["MessageEventsAPI"], settings, From cc5e39c9a96aca4dfbd29f83e7377f942888dc1b Mon Sep 17 00:00:00 2001 From: Fafa <87046111+Faf4a@users.noreply.github.com> Date: Sat, 11 May 2024 23:50:29 +0200 Subject: [PATCH 084/134] Dearrow: allow configuring which elements get dearrowd (#2414) Co-authored-by: Vendicated --- src/plugins/dearrow/index.tsx | 38 +++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/plugins/dearrow/index.tsx b/src/plugins/dearrow/index.tsx index b02c80d3d..888e2bb45 100644 --- a/src/plugins/dearrow/index.tsx +++ b/src/plugins/dearrow/index.tsx @@ -6,10 +6,11 @@ import "./styles.css"; +import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import definePlugin from "@utils/types"; +import definePlugin, { OptionType } from "@utils/types"; import { Tooltip } from "@webpack/common"; import type { Component } from "react"; @@ -34,11 +35,19 @@ interface Props { }; } +const enum ReplaceElements { + ReplaceAllElements, + ReplaceTitlesOnly, + ReplaceThumbnailsOnly +} + const embedUrlRe = /https:\/\/www\.youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/; async function embedDidMount(this: Component) { try { const { embed } = this.props; + const { replaceElements } = settings.store; + if (!embed || embed.dearrow || embed.provider?.name !== "YouTube" || !embed.video?.url) return; const videoId = embedUrlRe.exec(embed.video.url)?.[1]; @@ -58,12 +67,12 @@ async function embedDidMount(this: Component) { enabled: true }; - if (hasTitle) { + if (hasTitle && replaceElements !== ReplaceElements.ReplaceThumbnailsOnly) { embed.dearrow.oldTitle = embed.rawTitle; embed.rawTitle = titles[0].title.replace(/ >(\S)/g, " $1"); } - if (hasThumb) { + if (hasThumb && replaceElements !== ReplaceElements.ReplaceTitlesOnly) { embed.dearrow.oldThumb = embed.thumbnail.proxyURL; embed.thumbnail.proxyURL = `https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=${videoId}&time=${thumbnails[0].timestamp}`; } @@ -128,10 +137,30 @@ function DearrowButton({ component }: { component: Component; }) { ); } +const settings = definePluginSettings({ + hideButton: { + description: "Hides the Dearrow button from YouTube embeds", + type: OptionType.BOOLEAN, + default: false, + restartNeeded: true + }, + replaceElements: { + description: "Choose which elements of the embed will be replaced", + type: OptionType.SELECT, + restartNeeded: true, + options: [ + { label: "Everything (Titles & Thumbnails)", value: ReplaceElements.ReplaceAllElements, default: true }, + { label: "Titles", value: ReplaceElements.ReplaceTitlesOnly }, + { label: "Thumbnails", value: ReplaceElements.ReplaceThumbnailsOnly }, + ], + } +}); + export default definePlugin({ name: "Dearrow", description: "Makes YouTube embed titles and thumbnails less sensationalist, powered by Dearrow", authors: [Devs.Ven], + settings, embedDidMount, renderButton(component: Component) { @@ -154,7 +183,8 @@ export default definePlugin({ // add dearrow button { match: /children:\[(?=null!=\i\?\i\.renderSuppressButton)/, - replace: "children:[$self.renderButton(this)," + replace: "children:[$self.renderButton(this),", + predicate: () => !settings.store.hideButton } ] }], From b22bfc80fdafcca52b5b547b4fa74212fba82283 Mon Sep 17 00:00:00 2001 From: Elvyra <88881326+EdVraz@users.noreply.github.com> Date: Sun, 12 May 2024 01:23:51 +0200 Subject: [PATCH 085/134] pronounDB: Update to API v2 (#2355) Co-authored-by: vee --- src/plugins/pronoundb/index.ts | 2 +- src/plugins/pronoundb/pronoundbUtils.ts | 44 ++++++++++++++----------- src/plugins/pronoundb/types.ts | 34 +++++++++---------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index b14b26572..a5891d2e8 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -33,7 +33,7 @@ const PRONOUN_TOOLTIP_PATCH = { export default definePlugin({ name: "PronounDB", - authors: [Devs.Tyman, Devs.TheKodeToad, Devs.Ven], + authors: [Devs.Tyman, Devs.TheKodeToad, Devs.Ven, Devs.Elvyra], description: "Adds pronouns to user messages using pronoundb", patches: [ { diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts index 6373c56a0..d4fdb09d3 100644 --- a/src/plugins/pronoundb/pronoundbUtils.ts +++ b/src/plugins/pronoundb/pronoundbUtils.ts @@ -24,7 +24,7 @@ import { useAwaiter } from "@utils/react"; import { UserProfileStore, UserStore } from "@webpack/common"; import { settings } from "./settings"; -import { PronounCode, PronounMapping, PronounsResponse } from "./types"; +import { CachePronouns, PronounCode, PronounMapping, PronounsResponse } from "./types"; type PronounsWithSource = [string | null, string]; const EmptyPronouns: PronounsWithSource = [null, ""]; @@ -40,9 +40,9 @@ export const enum PronounSource { } // A map of cached pronouns so the same request isn't sent twice -const cache: Record = {}; +const cache: Record = {}; // A map of ids and callbacks that should be triggered on fetch -const requestQueue: Record void)[]> = {}; +const requestQueue: Record void)[]> = {}; // Executes all queued requests and calls their callbacks const bulkFetch = debounce(async () => { @@ -50,7 +50,7 @@ const bulkFetch = debounce(async () => { const pronouns = await bulkFetchPronouns(ids); for (const id of ids) { // Call all callbacks for the id - requestQueue[id]?.forEach(c => c(pronouns[id])); + requestQueue[id]?.forEach(c => c(pronouns[id] ? extractPronouns(pronouns[id].sets) : "")); delete requestQueue[id]; } }); @@ -78,8 +78,8 @@ export function useFormattedPronouns(id: string, useGlobalProfile: boolean = fal if (settings.store.pronounSource === PronounSource.PreferDiscord && discordPronouns) return [discordPronouns, "Discord"]; - if (result && result !== "unspecified") - return [formatPronouns(result), "PronounDB"]; + if (result && result !== PronounMapping.unspecified) + return [result, "PronounDB"]; return [discordPronouns, "Discord"]; } @@ -98,8 +98,9 @@ const NewLineRe = /\n+/g; // Gets the cached pronouns, if you're too impatient for a promise! export function getCachedPronouns(id: string): string | null { - const cached = cache[id]; - if (cached && cached !== "unspecified") return cached; + const cached = cache[id] ? extractPronouns(cache[id].sets) : undefined; + + if (cached && cached !== PronounMapping.unspecified) return cached; return cached || null; } @@ -125,7 +126,7 @@ async function bulkFetchPronouns(ids: string[]): Promise { params.append("ids", ids.join(",")); try { - const req = await fetch("https://pronoundb.org/api/v1/lookup-bulk?" + params.toString(), { + const req = await fetch("https://pronoundb.org/api/v2/lookup?" + params.toString(), { method: "GET", headers: { "Accept": "application/json", @@ -140,21 +141,24 @@ async function bulkFetchPronouns(ids: string[]): Promise { } catch (e) { // If the request errors, treat it as if no pronouns were found for all ids, and log it console.error("PronounDB fetching failed: ", e); - const dummyPronouns = Object.fromEntries(ids.map(id => [id, "unspecified"] as const)); + const dummyPronouns = Object.fromEntries(ids.map(id => [id, { sets: {} }] as const)); Object.assign(cache, dummyPronouns); return dummyPronouns; } } -export function formatPronouns(pronouns: string): string { +export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[] }): string { + if (!pronounSet || !pronounSet.en) return PronounMapping.unspecified; + // PronounDB returns an empty set instead of {sets: {en: ["unspecified"]}}. + const pronouns = pronounSet.en; const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; }; - // For capitalized pronouns, just return the mapping (it is by default capitalized) - if (pronounsFormat === PronounsFormat.Capitalized) return PronounMapping[pronouns]; - // If it is set to lowercase and a special code (any, ask, avoid), then just return the capitalized text - else if ( - pronounsFormat === PronounsFormat.Lowercase - && ["any", "ask", "avoid", "other"].includes(pronouns) - ) return PronounMapping[pronouns]; - // Otherwise (lowercase and not a special code), then convert the mapping to lowercase - else return PronounMapping[pronouns].toLowerCase(); + + if (pronouns.length === 1) { + // For capitalized pronouns or special codes (any, ask, avoid), we always return the normal (capitalized) string + if (pronounsFormat === PronounsFormat.Capitalized || ["any", "ask", "avoid", "other", "unspecified"].includes(pronouns[0])) + return PronounMapping[pronouns[0]]; + else return PronounMapping[pronouns[0]].toLowerCase(); + } + const pronounString = pronouns.map(p => p[0].toUpperCase() + p.slice(1)).join("/"); + return pronounsFormat === PronounsFormat.Capitalized ? pronounString : pronounString.toLowerCase(); } diff --git a/src/plugins/pronoundb/types.ts b/src/plugins/pronoundb/types.ts index 9cfd77c8a..d099a7de8 100644 --- a/src/plugins/pronoundb/types.ts +++ b/src/plugins/pronoundb/types.ts @@ -26,31 +26,29 @@ export interface UserProfilePronounsProps { } export interface PronounsResponse { - [id: string]: PronounCode; + [id: string]: { + sets?: { + [locale: string]: PronounCode[]; + } + } +} + +export interface CachePronouns { + sets?: { + [locale: string]: PronounCode[]; + } } export type PronounCode = keyof typeof PronounMapping; export const PronounMapping = { - hh: "He/Him", - hi: "He/It", - hs: "He/She", - ht: "He/They", - ih: "It/Him", - ii: "It/Its", - is: "It/She", - it: "It/They", - shh: "She/He", - sh: "She/Her", - si: "She/It", - st: "She/They", - th: "They/He", - ti: "They/It", - ts: "They/She", - tt: "They/Them", + he: "He/Him", + it: "It/Its", + she: "She/Her", + they: "They/Them", any: "Any pronouns", other: "Other pronouns", ask: "Ask me my pronouns", avoid: "Avoid pronouns, use my name", - unspecified: "Unspecified" + unspecified: "No pronouns specified.", } as const; From 0f9acba59ed4096eb6fc6a73da3c4c252c494c21 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 12 May 2024 02:00:29 +0200 Subject: [PATCH 086/134] settingsSync: include date in filename for better sorting Co-authored-by: cd CreepArghhh_ <65649991+cd-CreepArghhh@users.noreply.github.com> --- src/plugins/fakeNitro/index.tsx | 4 ++-- src/utils/settingsSync.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index ea171c833..087928e9f 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -111,7 +111,7 @@ const hyperLinkRegex = /\[.+?\]\((https?:\/\/.+?)\)/; const settings = definePluginSettings({ enableEmojiBypass: { - description: "Allow sending fake emojis", + description: "Allows sending fake emojis (also bypasses missing permission to use custom emojis)", type: OptionType.BOOLEAN, default: true, restartNeeded: true @@ -129,7 +129,7 @@ const settings = definePluginSettings({ restartNeeded: true }, enableStickerBypass: { - description: "Allow sending fake stickers", + description: "Allows sending fake stickers (also bypasses missing permission to use stickers)", type: OptionType.BOOLEAN, default: true, restartNeeded: true diff --git a/src/utils/settingsSync.ts b/src/utils/settingsSync.ts index 843922f2f..f19928ac4 100644 --- a/src/utils/settingsSync.ts +++ b/src/utils/settingsSync.ts @@ -18,7 +18,7 @@ import { showNotification } from "@api/Notifications"; import { PlainSettings, Settings } from "@api/Settings"; -import { Toasts } from "@webpack/common"; +import { moment, Toasts } from "@webpack/common"; import { deflateSync, inflateSync } from "fflate"; import { getCloudAuth, getCloudUrl } from "./cloud"; @@ -49,7 +49,7 @@ export async function exportSettings({ minify }: { minify?: boolean; } = {}) { } export async function downloadSettingsBackup() { - const filename = "vencord-settings-backup.json"; + const filename = `vencord-settings-backup-${moment().format("YYYY-MM-DD")}.json`; const backup = await exportSettings(); const data = new TextEncoder().encode(backup); From f21db5cb011202a50dc6b7fd5695e15e5dea564c Mon Sep 17 00:00:00 2001 From: Claire Date: Sat, 11 May 2024 17:08:17 -0700 Subject: [PATCH 087/134] add Native settings implementation (#2346) Co-authored-by: vee --- src/api/Commands/commandHelpers.ts | 2 +- src/api/Settings.ts | 2 +- src/main/settings.ts | 18 +++++++++++++++++- src/utils/mergeDefaults.ts | 24 ++++++++++++++++++++++++ src/utils/misc.tsx | 19 ------------------- 5 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 src/utils/mergeDefaults.ts diff --git a/src/api/Commands/commandHelpers.ts b/src/api/Commands/commandHelpers.ts index dc5ecfd67..2f7039137 100644 --- a/src/api/Commands/commandHelpers.ts +++ b/src/api/Commands/commandHelpers.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { mergeDefaults } from "@utils/misc"; +import { mergeDefaults } from "@utils/mergeDefaults"; import { findByPropsLazy } from "@webpack"; import { MessageActions, SnowflakeUtils } from "@webpack/common"; import { Message } from "discord-types/general"; diff --git a/src/api/Settings.ts b/src/api/Settings.ts index 696c12c28..490e6ef7f 100644 --- a/src/api/Settings.ts +++ b/src/api/Settings.ts @@ -20,7 +20,7 @@ import { debounce } from "@shared/debounce"; import { SettingsStore as SettingsStoreClass } from "@shared/SettingsStore"; import { localStorage } from "@utils/localStorage"; import { Logger } from "@utils/Logger"; -import { mergeDefaults } from "@utils/misc"; +import { mergeDefaults } from "@utils/mergeDefaults"; import { putCloudSettings } from "@utils/settingsSync"; import { DefinedSettings, OptionType, SettingsChecks, SettingsDefinition } from "@utils/types"; import { React } from "@webpack/common"; diff --git a/src/main/settings.ts b/src/main/settings.ts index 96efdd672..3d367a945 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -7,6 +7,7 @@ import type { Settings } from "@api/Settings"; import { IpcEvents } from "@shared/IpcEvents"; import { SettingsStore } from "@shared/SettingsStore"; +import { mergeDefaults } from "@utils/mergeDefaults"; import { ipcMain } from "electron"; import { mkdirSync, readFileSync, writeFileSync } from "fs"; @@ -42,7 +43,22 @@ ipcMain.handle(IpcEvents.SET_SETTINGS, (_, data: Settings, pathToNotify?: string RendererSettings.setData(data, pathToNotify); }); -export const NativeSettings = new SettingsStore(readSettings("native", NATIVE_SETTINGS_FILE)); +export interface NativeSettings { + plugins: { + [plugin: string]: { + [setting: string]: any; + }; + }; +} + +const DefaultNativeSettings: NativeSettings = { + plugins: {} +}; + +const nativeSettings = readSettings("native", NATIVE_SETTINGS_FILE); +mergeDefaults(nativeSettings, DefaultNativeSettings); + +export const NativeSettings = new SettingsStore(nativeSettings); NativeSettings.addGlobalChangeListener(() => { try { diff --git a/src/utils/mergeDefaults.ts b/src/utils/mergeDefaults.ts new file mode 100644 index 000000000..58ba136dd --- /dev/null +++ b/src/utils/mergeDefaults.ts @@ -0,0 +1,24 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/** + * Recursively merges defaults into an object and returns the same object + * @param obj Object + * @param defaults Defaults + * @returns obj + */ +export function mergeDefaults(obj: T, defaults: T): T { + for (const key in defaults) { + const v = defaults[key]; + if (typeof v === "object" && !Array.isArray(v)) { + obj[key] ??= {} as any; + mergeDefaults(obj[key], v); + } else { + obj[key] ??= v; + } + } + return obj; +} diff --git a/src/utils/misc.tsx b/src/utils/misc.tsx index 32010e59b..fb08c93f6 100644 --- a/src/utils/misc.tsx +++ b/src/utils/misc.tsx @@ -20,25 +20,6 @@ import { Clipboard, Toasts } from "@webpack/common"; import { DevsById } from "./constants"; -/** - * Recursively merges defaults into an object and returns the same object - * @param obj Object - * @param defaults Defaults - * @returns obj - */ -export function mergeDefaults(obj: T, defaults: T): T { - for (const key in defaults) { - const v = defaults[key]; - if (typeof v === "object" && !Array.isArray(v)) { - obj[key] ??= {} as any; - mergeDefaults(obj[key], v); - } else { - obj[key] ??= v; - } - } - return obj; -} - /** * Calls .join(" ") on the arguments * classes("one", "two") => "one two" From d6507947f57b84e7ed51c73d7596ab7df667d5de Mon Sep 17 00:00:00 2001 From: HAHALOSAH <67280050+HAHALOSAH@users.noreply.github.com> Date: Sat, 11 May 2024 17:32:44 -0700 Subject: [PATCH 088/134] Plugin Settings: fix text overflow for long plugin names (#2383) Co-authored-by: V --- src/components/VencordSettings/AddonCard.tsx | 20 ++++++++++-- src/components/VencordSettings/addonCard.css | 33 ++++++++++++++++++++ src/utils/constants.ts | 4 +++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/components/VencordSettings/AddonCard.tsx b/src/components/VencordSettings/AddonCard.tsx index c4c3aaca9..1161a6411 100644 --- a/src/components/VencordSettings/AddonCard.tsx +++ b/src/components/VencordSettings/AddonCard.tsx @@ -21,7 +21,7 @@ import "./addonCard.css"; import { classNameFactory } from "@api/Styles"; import { Badge } from "@components/Badge"; import { Switch } from "@components/Switch"; -import { Text } from "@webpack/common"; +import { Text, useRef } from "@webpack/common"; import type { MouseEventHandler, ReactNode } from "react"; const cl = classNameFactory("vc-addon-"); @@ -42,6 +42,8 @@ interface Props { } export function AddonCard({ disabled, isNew, name, infoButton, footer, author, enabled, setEnabled, description, onMouseEnter, onMouseLeave }: Props) { + const titleRef = useRef(null); + const titleContainerRef = useRef(null); return (
- {name}{isNew && } +
+
{ + const title = titleRef.current!; + const titleContainer = titleContainerRef.current!; + + title.style.setProperty("--offset", `${titleContainer.clientWidth - title.scrollWidth}px`); + title.style.setProperty("--duration", `${Math.max(0.5, (title.scrollWidth - titleContainer.clientWidth) / 7)}s`); + }} + > + {name} +
+
{isNew && }
{!!author && ( diff --git a/src/components/VencordSettings/addonCard.css b/src/components/VencordSettings/addonCard.css index f2dee11d9..e46e4c29c 100644 --- a/src/components/VencordSettings/addonCard.css +++ b/src/components/VencordSettings/addonCard.css @@ -62,3 +62,36 @@ .vc-addon-author::before { content: "by "; } + +.vc-addon-title-container { + width: 100%; + overflow: hidden; + height: 1.25em; + position: relative; +} + +.vc-addon-title { + position: absolute; + inset: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +@keyframes vc-addon-title { + 0% { + transform: translateX(0); + } + + 50% { + transform: translateX(var(--offset)); + } + + 100% { + transform: translateX(0); + } +} + +.vc-addon-title:hover { + overflow: visible; + animation: vc-addon-title var(--duration) linear infinite; +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 09c27d15f..c1e2cea2c 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -462,6 +462,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "Oleh Polisan", id: 242305263313485825n }, + HAHALOSAH: { + name: "HAHALOSAH", + id: 903418691268513883n + }, GabiRP: { name: "GabiRP", id: 507955112027750401n From a99354503f81cd41b6f3f8f33ee76c653f358560 Mon Sep 17 00:00:00 2001 From: Cats <42129397+Cats1337@users.noreply.github.com> Date: Sat, 11 May 2024 20:44:06 -0400 Subject: [PATCH 089/134] feat(Translate): add toggle for chat bar icon (#2418) --- src/plugins/translate/TranslateIcon.tsx | 4 ++-- src/plugins/translate/settings.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/translate/TranslateIcon.tsx b/src/plugins/translate/TranslateIcon.tsx index cc0ed5e93..b22c488eb 100644 --- a/src/plugins/translate/TranslateIcon.tsx +++ b/src/plugins/translate/TranslateIcon.tsx @@ -40,9 +40,9 @@ export function TranslateIcon({ height = 24, width = 24, className }: { height?: } export const TranslateChatBarIcon: ChatBarButton = ({ isMainChat }) => { - const { autoTranslate } = settings.use(["autoTranslate"]); + const { autoTranslate, showChatBarButton } = settings.use(["autoTranslate", "showChatBarButton"]); - if (!isMainChat) return null; + if (!isMainChat || !showChatBarButton) return null; const toggle = () => { const newState = !autoTranslate; diff --git a/src/plugins/translate/settings.ts b/src/plugins/translate/settings.ts index cef003a83..65d845353 100644 --- a/src/plugins/translate/settings.ts +++ b/src/plugins/translate/settings.ts @@ -48,6 +48,11 @@ export const settings = definePluginSettings({ type: OptionType.BOOLEAN, description: "Automatically translate your messages before sending. You can also shift/right click the translate button to toggle this", default: false + }, + showChatBarButton: { + type: OptionType.BOOLEAN, + description: "Show translate button in chat bar", + default: true } }).withPrivateSettings<{ showAutoTranslateAlert: boolean; From bbec51fd19a23d5ab41cfa637901ece5d83f683c Mon Sep 17 00:00:00 2001 From: Vendicated Date: Sun, 12 May 2024 03:23:00 +0200 Subject: [PATCH 090/134] but here's the bumper (v1.8.3) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9fd84f9b8..0e5845987 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.2", + "version": "1.8.3", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 5c7fa5578ce97b8f5c59e38a963d0e240eec833e Mon Sep 17 00:00:00 2001 From: nyan <24845294+nyakowint@users.noreply.github.com> Date: Sun, 12 May 2024 18:54:08 -0400 Subject: [PATCH 091/134] XSOverlay: Adjust message length timeout (#2445) --- src/plugins/xsOverlay.desktop/index.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts index b666d1168..5251959f2 100644 --- a/src/plugins/xsOverlay.desktop/index.ts +++ b/src/plugins/xsOverlay.desktop/index.ts @@ -68,7 +68,6 @@ interface Call { ringing: string[]; } -const MuteStore = findByPropsLazy("isSuppressEveryoneEnabled"); const Notifs = findByPropsLazy("makeTextChatNotification"); const XSLog = new Logger("XSOverlay"); @@ -115,13 +114,13 @@ const settings = definePluginSettings({ }, timeout: { type: OptionType.NUMBER, - description: "Notif duration (secs)", - default: 1.0, + description: "Notification duration (secs)", + default: 3, }, - timeoutPerCharacter: { - type: OptionType.NUMBER, - description: "Duration multiplier per character", - default: 0.5 + lengthBasedTimeout: { + type: OptionType.BOOLEAN, + description: "Extend duration with message length", + default: true }, opacity: { type: OptionType.SLIDER, @@ -262,12 +261,11 @@ function shouldIgnoreForChannelType(channel: Channel) { } function sendMsgNotif(titleString: string, content: string, message: Message) { - const timeout = Math.max(settings.store.timeout, content.length * settings.store.timeoutPerCharacter); fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => { const msgData = { messageType: 1, index: 0, - timeout, + timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout, height: calculateHeight(content), opacity: settings.store.opacity, volume: settings.store.volume, @@ -286,7 +284,7 @@ function sendOtherNotif(content: string, titleString: string) { const msgData = { messageType: 1, index: 0, - timeout: settings.store.timeout, + timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout, height: calculateHeight(content), opacity: settings.store.opacity, volume: settings.store.volume, @@ -313,3 +311,10 @@ function calculateHeight(content: string) { if (content.length <= 300) return 200; return 250; } + +function calculateTimeout(content: string) { + if (content.length <= 100) return 3; + if (content.length <= 200) return 4; + if (content.length <= 300) return 5; + return 6; +} From fd7dafb15327efa95eedc313998e6900715f67f4 Mon Sep 17 00:00:00 2001 From: dolfies Date: Sun, 12 May 2024 19:07:12 -0400 Subject: [PATCH 092/134] fix(MessageLatency): Adjust for Discord kotlin clients (#2443) --- src/plugins/messageLatency/index.tsx | 47 +++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/plugins/messageLatency/index.tsx b/src/plugins/messageLatency/index.tsx index 48b57863e..301e605fb 100644 --- a/src/plugins/messageLatency/index.tsx +++ b/src/plugins/messageLatency/index.tsx @@ -24,19 +24,27 @@ interface Diff { seconds: number; } +const DISCORD_KT_DELAY = 1471228.928; const HiddenVisually = findExportedComponentLazy("HiddenVisually"); export default definePlugin({ name: "MessageLatency", description: "Displays an indicator for messages that took ≥n seconds to send", authors: [Devs.arHSM], + settings: definePluginSettings({ latency: { type: OptionType.NUMBER, description: "Threshold in seconds for latency indicator", default: 2 + }, + detectDiscordKotlin: { + type: OptionType.BOOLEAN, + description: "Detect old Discord Android clients", + default: true } }), + patches: [ { find: "showCommunicationDisabledStyles", @@ -46,6 +54,7 @@ export default definePlugin({ } } ], + stringDelta(delta: number) { const diff: Diff = { days: Math.round(delta / (60 * 60 * 24)), @@ -71,15 +80,25 @@ export default definePlugin({ ); }, ""); - return [ts || "0 seconds", diff.days === 17 && diff.hours === 1] as const; + return ts || "0 seconds"; }, + latencyTooltipData(message: Message) { + const { latency, detectDiscordKotlin } = this.settings.store; const { id, nonce } = message; // Message wasn't received through gateway if (!isNonNullish(nonce)) return null; - const delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000); + let isDiscordKotlin = false; + let delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000); + + // Old Discord Android clients have a delay of around 17 days + // This is a workaround for that + if (-delta >= DISCORD_KT_DELAY - 86400) { // One day of padding for good measure + isDiscordKotlin = detectDiscordKotlin; + delta += DISCORD_KT_DELAY; + } // Thanks dziurwa (I hate you) // This is when the user's clock is ahead @@ -87,15 +106,13 @@ export default definePlugin({ const abs = Math.abs(delta); const ahead = abs !== delta; - const [stringDelta, isSuspectedKotlinDiscord] = this.stringDelta(abs); - const isKotlinDiscord = ahead && isSuspectedKotlinDiscord; + const stringDelta = abs >= latency ? this.stringDelta(abs) : null; // Also thanks dziurwa // 2 minutes const TROLL_LIMIT = 2 * 60; - const { latency } = this.settings.store; - const fill: Fill = isKotlinDiscord + const fill: Fill = isDiscordKotlin ? ["status-positive", "status-positive", "text-muted"] : delta >= TROLL_LIMIT || ahead ? ["text-muted", "text-muted", "text-muted"] @@ -103,17 +120,24 @@ export default definePlugin({ ? ["status-danger", "text-muted", "text-muted"] : ["status-warning", "status-warning", "text-muted"]; - return abs >= latency ? { delta: stringDelta, ahead, fill, isKotlinDiscord } : null; + return (abs >= latency || isDiscordKotlin) ? { delta: stringDelta, ahead, fill, isDiscordKotlin } : null; }, + Tooltip() { return ErrorBoundary.wrap(({ message }: { message: Message; }) => { - const d = this.latencyTooltipData(message); if (!isNonNullish(d)) return null; + let text: string; + if (!d.delta) { + text = "User is suspected to be on an old Discord Android client"; + } else { + text = (d.ahead ? `This user's clock is ${d.delta} ahead.` : `This message was sent with a delay of ${d.delta}.`) + (d.isDiscordKotlin ? " User is suspected to be on an old Discord Android client." : ""); + } + return { @@ -126,8 +150,9 @@ export default definePlugin({ ; }); }, + Icon({ delta, fill, props }: { - delta: string; + delta: string | null; fill: Fill, props: { onClick(): void; @@ -147,7 +172,7 @@ export default definePlugin({ role="img" fill="none" style={{ marginRight: "8px", verticalAlign: -1 }} - aria-label={delta} + aria-label={delta ?? "Old Discord Android client"} aria-hidden="false" {...props} > From 902b6bcdf20c6e9b3170ace70c124834e6e4f8cd Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sun, 12 May 2024 20:58:26 -0300 Subject: [PATCH 093/134] PinDMs: ErrorBoundary renderChannel --- src/plugins/pinDms/index.tsx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/plugins/pinDms/index.tsx b/src/plugins/pinDms/index.tsx index 010b5506c..79503b9ad 100644 --- a/src/plugins/pinDms/index.tsx +++ b/src/plugins/pinDms/index.tsx @@ -320,25 +320,26 @@ export default definePlugin({ ); - }), + }, { noop: true }), renderChannel(sectionIndex: number, index: number, ChannelComponent: React.ComponentType) { - const { channel, category } = this.getChannel(sectionIndex, index, this.instance.props.channels); + return ErrorBoundary.wrap(() => { + const { channel, category } = this.getChannel(sectionIndex, index, this.instance.props.channels); - if (!channel || !category) return null; - if (this.isChannelHidden(sectionIndex, index)) return null; + if (!channel || !category) return null; + if (this.isChannelHidden(sectionIndex, index)) return null; - return ( - - {channel.id} - - ); + return ( + + {channel.id} + + ); + }, { noop: true }); }, - getChannel(sectionIndex: number, index: number, channels: Record) { const category = categories[sectionIndex - 1]; if (!category) return { channel: null, category: null }; From 1f1c80c5f3bf897cec82d08302a2d3f396436ed0 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Mon, 13 May 2024 03:30:10 +0200 Subject: [PATCH 094/134] ValidUser: fix crashing when viewing a valid-userd staff's profile --- src/plugins/validUser/index.tsx | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index 7a21ac86b..fd88ca9c9 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -18,6 +18,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; +import { isNonNullish } from "@utils/guards"; import { sleep } from "@utils/misc"; import { Queue } from "@utils/Queue"; import definePlugin from "@utils/types"; @@ -27,19 +28,20 @@ import type { ComponentType, ReactNode } from "react"; // LYING to the type checker here const UserFlags = Constants.UserFlags as Record; const badges: Record = { - "active_developer": { id: "active_developer", description: "Active Developer", icon: "6bdc42827a38498929a4920da12695d9", link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447" }, - "bug_hunter_level_1": { id: "bug_hunter_level_1", description: "Discord Bug Hunter", icon: "2717692c7dca7289b35297368a940dd0", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, - "bug_hunter_level_2": { id: "bug_hunter_level_2", description: "Discord Bug Hunter", icon: "848f79194d4be5ff5f81505cbd0ce1e6", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, - "certified_moderator": { id: "certified_moderator", description: "Moderator Programs Alumni", icon: "fee1624003e2fee35cb398e125dc479b", link: "https://discord.com/safety" }, - "discord_employee": { id: "staff", description: "Discord Staff", icon: "5e74e9b61934fc1f67c65515d1f7e60d", link: "https://discord.com/company" }, - "hypesquad": { id: "hypesquad", description: "HypeSquad Events", icon: "bf01d1073931f921909045f3a39fd264", link: "https://discord.com/hypesquad" }, - "hypesquad_online_house_1": { id: "hypesquad_house_1", description: "HypeSquad Bravery", icon: "8a88d63823d8a71cd5e390baa45efa02", link: "https://discord.com/settings/hypesquad-online" }, - "hypesquad_online_house_2": { id: "hypesquad_house_2", description: "HypeSquad Brilliance", icon: "011940fd013da3f7fb926e4a1cd2e618", link: "https://discord.com/settings/hypesquad-online" }, - "hypesquad_online_house_3": { id: "hypesquad_house_3", description: "HypeSquad Balance", icon: "3aa41de486fa12454c3761e8e223442e", link: "https://discord.com/settings/hypesquad-online" }, - "partner": { id: "partner", description: "Partnered Server Owner", icon: "3f9748e53446a137a052f3454e2de41e", link: "https://discord.com/partners" }, - "premium": { id: "premium", description: "Subscriber", icon: "2ba85e8026a8614b640c2837bcdfe21b", link: "https://discord.com/settings/premium" }, - "premium_early_supporter": { id: "early_supporter", description: "Early Supporter", icon: "7060786766c9c840eb3019e725d2b358", link: "https://discord.com/settings/premium" }, - "verified_developer": { id: "verified_developer", description: "Early Verified Bot Developer", icon: "6df5892e0f35b051f8b61eace34f4967" }, + active_developer: { id: "active_developer", description: "Active Developer", icon: "6bdc42827a38498929a4920da12695d9", link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447" }, + bug_hunter_level_1: { id: "bug_hunter_level_1", description: "Discord Bug Hunter", icon: "2717692c7dca7289b35297368a940dd0", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, + bug_hunter_level_2: { id: "bug_hunter_level_2", description: "Discord Bug Hunter", icon: "848f79194d4be5ff5f81505cbd0ce1e6", link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs" }, + certified_moderator: { id: "certified_moderator", description: "Moderator Programs Alumni", icon: "fee1624003e2fee35cb398e125dc479b", link: "https://discord.com/safety" }, + discord_employee: { id: "staff", description: "Discord Staff", icon: "5e74e9b61934fc1f67c65515d1f7e60d", link: "https://discord.com/company" }, + get staff() { return this.discord_employee; }, + hypesquad: { id: "hypesquad", description: "HypeSquad Events", icon: "bf01d1073931f921909045f3a39fd264", link: "https://discord.com/hypesquad" }, + hypesquad_online_house_1: { id: "hypesquad_house_1", description: "HypeSquad Bravery", icon: "8a88d63823d8a71cd5e390baa45efa02", link: "https://discord.com/settings/hypesquad-online" }, + hypesquad_online_house_2: { id: "hypesquad_house_2", description: "HypeSquad Brilliance", icon: "011940fd013da3f7fb926e4a1cd2e618", link: "https://discord.com/settings/hypesquad-online" }, + hypesquad_online_house_3: { id: "hypesquad_house_3", description: "HypeSquad Balance", icon: "3aa41de486fa12454c3761e8e223442e", link: "https://discord.com/settings/hypesquad-online" }, + partner: { id: "partner", description: "Partnered Server Owner", icon: "3f9748e53446a137a052f3454e2de41e", link: "https://discord.com/partners" }, + premium: { id: "premium", description: "Subscriber", icon: "2ba85e8026a8614b640c2837bcdfe21b", link: "https://discord.com/settings/premium" }, + premium_early_supporter: { id: "early_supporter", description: "Early Supporter", icon: "7060786766c9c840eb3019e725d2b358", link: "https://discord.com/settings/premium" }, + verified_developer: { id: "verified_developer", description: "Early Verified Bot Developer", icon: "6df5892e0f35b051f8b61eace34f4967" }, }; const fetching = new Set(); @@ -93,7 +95,8 @@ async function getUser(id: string) { userObj = UserStore.getUser(id); const fakeBadges: ProfileBadge[] = Object.entries(UserFlags) .filter(([_, flag]) => !isNaN(flag) && userObj.hasFlag(flag)) - .map(([key]) => badges[key.toLowerCase()]); + .map(([key]) => badges[key.toLowerCase()]) + .filter(isNonNullish); if (user.premium_type || !user.bot && (user.banner || user.avatar?.startsWith?.("a_"))) fakeBadges.push(badges.premium); From f6765818d2248292b4dacf74c3ae3e2eae5856d4 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Mon, 13 May 2024 03:34:01 +0200 Subject: [PATCH 095/134] ValidUser: fix rendering old mentions when message is edited Fixes https://github.com/Vendicated/Vencord/issues/2451 --- src/plugins/pinDms/index.tsx | 2 +- src/plugins/validUser/index.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/pinDms/index.tsx b/src/plugins/pinDms/index.tsx index 79503b9ad..60484561a 100644 --- a/src/plugins/pinDms/index.tsx +++ b/src/plugins/pinDms/index.tsx @@ -83,7 +83,7 @@ export default definePlugin({ // Rendering { match: /"renderRow",(\i)=>{(?<="renderDM",.+?(\i\.default),\{channel:.+?)/, - replace: "$&if($self.isChannelIndex($1.section, $1.row))return $self.renderChannel($1.section,$1.row,$2);" + replace: "$&if($self.isChannelIndex($1.section, $1.row))return $self.renderChannel($1.section,$1.row,$2)();" }, { match: /"renderSection",(\i)=>{/, diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index fd88ca9c9..64b734f53 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -23,7 +23,7 @@ import { sleep } from "@utils/misc"; import { Queue } from "@utils/Queue"; import definePlugin from "@utils/types"; import { Constants, FluxDispatcher, RestAPI, UserProfileStore, UserStore, useState } from "@webpack/common"; -import type { ComponentType, ReactNode } from "react"; +import { type ComponentType, type ReactNode } from "react"; // LYING to the type checker here const UserFlags = Constants.UserFlags as Record; @@ -205,6 +205,7 @@ export default definePlugin({ return ( Date: Mon, 13 May 2024 01:09:19 -0400 Subject: [PATCH 096/134] feat(ShowHiddenThings): Remove Discovery banned/NSFW filters (#2453) --- src/plugins/showHiddenThings/README.md | 4 +++- src/plugins/showHiddenThings/index.ts | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/plugins/showHiddenThings/README.md b/src/plugins/showHiddenThings/README.md index e969391e4..753e5c148 100644 --- a/src/plugins/showHiddenThings/README.md +++ b/src/plugins/showHiddenThings/README.md @@ -1,6 +1,6 @@ # ShowHiddenThings -Displays various moderator-only elements regardless of permissions. +Displays various hidden & moderator-only things regardless of permissions. ## Features @@ -15,3 +15,5 @@ Displays various moderator-only elements regardless of permissions. ![](https://github.com/Vendicated/Vencord/assets/47677887/3dac95dd-841c-4c15-ad87-2db7bd1e4dab) - Disable filters in Server Discovery search that hide servers that don't meet discovery criteria + +- Disable filters in Server Discovery search that hide NSFW & disallowed servers diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 1858582a8..8de70aca9 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -41,13 +41,18 @@ const settings = definePluginSettings({ description: "Disable filters in Server Discovery search that hide servers that don't meet discovery criteria.", default: true, }, + disableDisallowedDiscoveryFilters: { + type: OptionType.BOOLEAN, + description: "Disable filters in Server Discovery search that hide NSFW & disallowed servers.", + default: true, + }, }); migratePluginSettings("ShowHiddenThings", "ShowTimeouts"); export default definePlugin({ name: "ShowHiddenThings", tags: ["ShowTimeouts", "ShowInvitesPaused", "ShowModView", "DisableDiscoveryFilters"], - description: "Displays various moderator-only elements regardless of permissions.", + description: "Displays various hidden & moderator-only things regardless of permissions.", authors: [Devs.Dolfies], patches: [ { @@ -81,6 +86,23 @@ export default definePlugin({ match: /filters:\i\.join\(" AND "\),facets:\[/, replace: "facets:[" } + }, + { + find: "DiscoveryBannedSearchWords.includes", + predicate: () => settings.store.disableDisallowedDiscoveryFilters, + replacement: { + match: /(?<=function\(\){)(?=.{0,130}DiscoveryBannedSearchWords\.includes)/, + replace: "return false;" + } + }, + { + find: "Endpoints.GUILD_DISCOVERY_VALID_TERM", + predicate: () => settings.store.disableDisallowedDiscoveryFilters, + all: true, + replacement: { + match: /\i\.HTTP\.get\(\{url:\i\.Endpoints\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\);/g, + replace: "Promise.resolve({ body: { valid: true } });" + } } ], settings, From 9621dc7bb39087a752910eab170701fb6b4be585 Mon Sep 17 00:00:00 2001 From: axiand Date: Tue, 14 May 2024 03:16:49 +0200 Subject: [PATCH 097/134] EmoteCloner: allow cloning from reactions (#2458) --- src/plugins/emoteCloner/index.tsx | 5 +++-- src/utils/constants.ts | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index cd9890a80..8c3ded6a7 100644 --- a/src/plugins/emoteCloner/index.tsx +++ b/src/plugins/emoteCloner/index.tsx @@ -322,8 +322,9 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) = switch (favoriteableType) { case "emoji": const match = props.message.content.match(RegExp(`|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.`)); - if (!match) return; - const name = match[1] ?? "FakeNitroEmoji"; + const reaction = props.message.reactions.find(reaction => reaction.emoji.id === favoriteableId); + if (!match && !reaction) return; + const name = (match && match[1]) ?? reaction?.emoji.name ?? "FakeNitroEmoji"; return buildMenuItem("Emoji", () => ({ id: favoriteableId, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index c1e2cea2c..e446a27b6 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -473,6 +473,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ ImBanana: { name: "Im_Banana", id: 635250116688871425n + }, + xocherry: { + name: "xocherry", + id: 221288171013406720n } } satisfies Record); From bd6f9e6f32e5ad95f7e16f323746a5770b1208de Mon Sep 17 00:00:00 2001 From: Amia <9750071+aamiaa@users.noreply.github.com> Date: Tue, 14 May 2024 03:22:49 +0200 Subject: [PATCH 098/134] fix(MutualGroupDMs): properly pass props (#2457) Co-authored-by: vee --- src/plugins/mutualGroupDMs/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index e787fefb4..94998677b 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -56,12 +56,12 @@ export default definePlugin({ find: ".UserProfileSections.USER_INFO_CONNECTIONS:", replacement: { match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/, - replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs($1,$2);" + replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs({user: $1, onClose: $2});" } } ], - renderMutualGDMs: ErrorBoundary.wrap((user: User, onClose: () => void) => { + renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => { const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => ( Date: Tue, 14 May 2024 04:39:05 +0300 Subject: [PATCH 099/134] FakeNitro: allow using subscription-locked emojis (#2456) Co-authored-by: Vendicated --- src/plugins/fakeNitro/index.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 087928e9f..293183664 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -39,6 +39,7 @@ const StickerStore = findStoreLazy("StickersStore") as { const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore"); const ProtoUtils = findByPropsLazy("BINARY_READ_OPTIONS"); +const RoleSubscriptionEmojiUtils = findByPropsLazy("isUnusableRoleSubscriptionEmoji"); function searchProtoClassField(localName: string, protoClass: any) { const field = protoClass?.fields?.find((field: any) => field.localName === localName); @@ -408,6 +409,15 @@ export default definePlugin({ match: /canUseCustomNotificationSounds:function\(\i\){/, replace: "$&return true;" } + }, + // Allows the usage of subscription-locked emojis + { + find: "isUnusableRoleSubscriptionEmoji:function", + replacement: { + match: /isUnusableRoleSubscriptionEmoji:function/, + // replace the original export with a func that always returns false and alias the original + replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function" + } } ], @@ -804,6 +814,9 @@ export default definePlugin({ if (e.require_colons === false) return true; if (e.available === false) return false; + const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji; + if (isUnusableRoleSubEmoji(e, this.guildId)) return false; + if (this.canUseEmotes) return e.guildId === this.guildId || hasExternalEmojiPerms(channelId); else From 892167420aa2db6fc6563c7e6ace5e37a4c946ea Mon Sep 17 00:00:00 2001 From: Anubis <102488279+AnubisNekhet@users.noreply.github.com> Date: Tue, 14 May 2024 07:27:20 +0530 Subject: [PATCH 100/134] MessageLogger: use discord variables instead of hardcoded colors (#2428) --- src/plugins/messageLogger/deleteStyleOverlay.css | 2 +- src/plugins/messageLogger/deleteStyleText.css | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/messageLogger/deleteStyleOverlay.css b/src/plugins/messageLogger/deleteStyleOverlay.css index 3778e80b3..59e4ac666 100644 --- a/src/plugins/messageLogger/deleteStyleOverlay.css +++ b/src/plugins/messageLogger/deleteStyleOverlay.css @@ -1,3 +1,3 @@ .messagelogger-deleted { - background-color: rgba(240 71 71 / 15%) !important; + background-color: hsla(var(--red-430-hsl, 0 85% 61%) / 15%) !important; } diff --git a/src/plugins/messageLogger/deleteStyleText.css b/src/plugins/messageLogger/deleteStyleText.css index 8fb8bf129..3477ef229 100644 --- a/src/plugins/messageLogger/deleteStyleText.css +++ b/src/plugins/messageLogger/deleteStyleText.css @@ -1,19 +1,19 @@ /* Message content highlighting */ .messagelogger-deleted [class*="contents"] > :is(div, h1, h2, h3, p) { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } /* Bot "thinking" text highlighting */ .messagelogger-deleted [class*="colorStandard"] { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } /* Embed highlighting */ .messagelogger-deleted article :is(div, span, h1, h2, h3, p) { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } .messagelogger-deleted a { - color: #be3535 !important; + color: var(--red-460, #be3535) !important; text-decoration: underline; } From 9dc8e4e24493b0dd5bd4758eb419e5d1c4052029 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 13 May 2024 22:45:57 -0300 Subject: [PATCH 101/134] Properly ErrorBoundary recent changes --- src/plugins/betterNotes/index.tsx | 12 ++-- src/plugins/pauseInvitesForever/index.tsx | 71 ++++++++++++----------- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index 5ebca1f8b..cacdba5fd 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -61,7 +61,7 @@ export default definePlugin({ find: ".popularApplicationCommandIds,", replacement: { match: /lastSection:(!?\i)}\),/, - replace: "$&$self.patchPadding($1)," + replace: "$&$self.patchPadding({lastSection:$1})," } } ], @@ -81,12 +81,10 @@ export default definePlugin({ } }, - patchPadding(lastSection: any) { - if (!lastSection) return; + patchPadding: ErrorBoundary.wrap(({ lastSection }) => { + if (!lastSection) return null; return ( - -
-
+
); - } + }) }); diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 1e71a4ed1..e7abaa17d 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -24,6 +24,22 @@ import { GuildStore, i18n, RestAPI } from "@webpack/common"; const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); +function showDisableInvites(guildId: string) { + // Once the experiment is removed, this should keep working + const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true }; + // @ts-ignore + return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED"); +} + +function disableInvites(guildId: string) { + const guild = GuildStore.getGuild(guildId); + const features = [...guild.features, "INVITES_DISABLED"]; + RestAPI.patch({ + url: `/guilds/${guild.id}`, + body: { features }, + }); +} + export default definePlugin({ name: "PauseInvitesForever", tags: ["DisableInvitesForever"], @@ -33,44 +49,29 @@ export default definePlugin({ patches: [ { find: "Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION", - replacement: [{ - match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/, - replace: "children: $self.renderInvitesLabel(arguments[0].guildId, setChecked)", - }, - { - match: /(\i\.hasDMsDisabled\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/, - replace: "$1,setChecked=$2" - }] + group: true, + replacement: [ + { + match: /children:\i\.\i\.\i\.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION/, + replace: "children: $self.renderInvitesLabel({guildId:arguments[0].guildId,setChecked})", + }, + { + match: /(\i\.hasDMsDisabled\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/, + replace: "$1,setChecked=$2" + } + ] } ], - showDisableInvites(guildId: string) { - // Once the experiment is removed, this should keep working - const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true }; - // @ts-ignore - return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED"); - }, - - disableInvites(guildId: string) { - const guild = GuildStore.getGuild(guildId); - const features = [...guild.features, "INVITES_DISABLED"]; - RestAPI.patch({ - url: `/guilds/${guild.id}`, - body: { features }, - }); - }, - - renderInvitesLabel(guildId: string, setChecked: Function) { + renderInvitesLabel: ErrorBoundary.wrap(({ guildId, setChecked }) => { return ( - -
- {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} - {this.showDisableInvites(guildId) && { - setChecked(true); - this.disableInvites(guildId); - }}> Pause Indefinitely.} -
-
+
+ {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {showDisableInvites(guildId) && { + setChecked(true); + disableInvites(guildId); + }}> Pause Indefinitely.} +
); - } + }) }); From d4ebfc233fde9e54b76ca17cb2cac82fbb4d6aa9 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 13 May 2024 23:00:02 -0300 Subject: [PATCH 102/134] Make all RestAPI calls use Endpoints object --- src/plugins/betterSessions/index.tsx | 4 ++-- src/plugins/emoteCloner/index.tsx | 6 +++--- src/plugins/friendInvites/index.ts | 4 ++-- src/plugins/invisibleChat.desktop/index.tsx | 4 ++-- src/plugins/messageLinkEmbeds/index.tsx | 3 ++- src/plugins/pauseInvitesForever/index.tsx | 4 ++-- src/plugins/unsuppressEmbeds/index.tsx | 4 ++-- src/plugins/validUser/index.tsx | 2 +- src/plugins/voiceMessages/index.tsx | 4 ++-- src/plugins/whoReacted/index.tsx | 4 ++-- src/utils/discord.tsx | 4 ++-- 11 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 539508f80..9c93289c8 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -22,7 +22,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; -import { React, RestAPI, Tooltip } from "@webpack/common"; +import { Constants, React, RestAPI, Tooltip } from "@webpack/common"; import { RenameButton } from "./components/RenameButton"; import { Session, SessionInfo } from "./types"; @@ -168,7 +168,7 @@ export default definePlugin({ async checkNewSessions() { const data = await RestAPI.get({ - url: "/auth/sessions" + url: Constants.Endpoints.AUTH_SESSIONS }); for (const session of data.body.user_sessions) { diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index 8c3ded6a7..b456c351e 100644 --- a/src/plugins/emoteCloner/index.tsx +++ b/src/plugins/emoteCloner/index.tsx @@ -24,7 +24,7 @@ import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal"; import definePlugin from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common"; +import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common"; import { Promisable } from "type-fest"; const StickersStore = findStoreLazy("StickersStore"); @@ -64,7 +64,7 @@ async function fetchSticker(id: string) { if (cached) return cached; const { body } = await RestAPI.get({ - url: `/stickers/${id}` + url: Constants.Endpoints.STICKER(id) }); FluxDispatcher.dispatch({ @@ -83,7 +83,7 @@ async function cloneSticker(guildId: string, sticker: Sticker) { data.append("file", await fetchBlob(getUrl(sticker))); const { body } = await RestAPI.post({ - url: `/guilds/${guildId}/stickers`, + url: Constants.Endpoints.GUILD_STICKER_PACKS(guildId), body: data, }); diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index e5ff447ed..47e312c31 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -20,7 +20,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { RestAPI, UserStore } from "@webpack/common"; +import { Constants, RestAPI, UserStore } from "@webpack/common"; const FriendInvites = findByPropsLazy("createFriendInvite"); const { uuid4 } = findByPropsLazy("uuid4"); @@ -58,7 +58,7 @@ export default definePlugin({ if (uses === 1) { const random = uuid4(); const { body: { invite_suggestions } } = await RestAPI.post({ - url: "/friend-finder/find-friends", + url: Constants.Endpoints.FRIEND_FINDER, body: { modified_contacts: { [random]: [1, "", ""] diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx index fcb0af712..3dfe51e77 100644 --- a/src/plugins/invisibleChat.desktop/index.tsx +++ b/src/plugins/invisibleChat.desktop/index.tsx @@ -23,7 +23,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getStegCloak } from "@utils/dependencies"; import definePlugin, { OptionType } from "@utils/types"; -import { ChannelStore, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common"; +import { ChannelStore, Constants, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common"; import { Message } from "discord-types/general"; import { buildDecModal } from "./components/DecryptionModal"; @@ -153,7 +153,7 @@ export default definePlugin({ // Gets the Embed of a Link async getEmbed(url: URL): Promise { const { body } = await RestAPI.post({ - url: "/unfurler/embed-urls", + url: Constants.Endpoints.UNFURL_EMBED_URLS, body: { urls: [url] } diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 2a5f88282..5c3063628 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -27,6 +27,7 @@ import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { Button, ChannelStore, + Constants, FluxDispatcher, GuildStore, IconUtils, @@ -132,7 +133,7 @@ async function fetchMessage(channelID: string, messageID: string) { messageCache.set(messageID, { fetched: false }); const res = await RestAPI.get({ - url: `/channels/${channelID}/messages`, + url: Constants.Endpoints.MESSAGES(channelID), query: { limit: 1, around: messageID diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index e7abaa17d..6a70be1aa 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -20,7 +20,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { GuildStore, i18n, RestAPI } from "@webpack/common"; +import { Constants, GuildStore, i18n, RestAPI } from "@webpack/common"; const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); @@ -35,7 +35,7 @@ function disableInvites(guildId: string) { const guild = GuildStore.getGuild(guildId); const features = [...guild.features, "INVITES_DISABLED"]; RestAPI.patch({ - url: `/guilds/${guild.id}`, + url: Constants.Endpoints.GUILD(guildId), body: { features }, }); } diff --git a/src/plugins/unsuppressEmbeds/index.tsx b/src/plugins/unsuppressEmbeds/index.tsx index 0e87201c6..16debf711 100644 --- a/src/plugins/unsuppressEmbeds/index.tsx +++ b/src/plugins/unsuppressEmbeds/index.tsx @@ -20,7 +20,7 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co import { ImageInvisible, ImageVisible } from "@components/Icons"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common"; +import { Constants, Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common"; const EMBED_SUPPRESSED = 1 << 2; @@ -44,7 +44,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { channe icon={isEmbedSuppressed ? ImageVisible : ImageInvisible} action={() => RestAPI.patch({ - url: `/channels/${channel.id}/messages/${messageId}`, + url: Constants.Endpoints.MESSAGE(channel.id, messageId), body: { flags: isEmbedSuppressed ? flags & ~EMBED_SUPPRESSED : flags | EMBED_SUPPRESSED } }) } diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index 64b734f53..4825cdaa3 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -75,7 +75,7 @@ async function getUser(id: string) { if (userObj) return userObj; - const user: any = await RestAPI.get({ url: `/users/${id}` }).then(response => { + const user: any = await RestAPI.get({ url: Constants.Endpoints.USER(id) }).then(response => { FluxDispatcher.dispatch({ type: "USER_UPDATE", user: response.body, diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 2f232f341..40e877df9 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -28,7 +28,7 @@ import { useAwaiter } from "@utils/react"; import definePlugin from "@utils/types"; import { chooseFile } from "@utils/web"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { Button, Card, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; +import { Button, Card, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; import { VoiceRecorderDesktop } from "./DesktopRecorder"; @@ -98,7 +98,7 @@ function sendAudio(blob: Blob, meta: AudioMetadata) { upload.on("complete", () => { RestAPI.post({ - url: `/channels/${channelId}/messages`, + url: Constants.Endpoints.MESSAGES(channelId), body: { flags: 1 << 13, channel_id: channelId, diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index b3728c215..5721dc912 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -23,7 +23,7 @@ import { Queue } from "@utils/Queue"; import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; -import { ChannelStore, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common"; +import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common"; import { CustomEmoji } from "@webpack/types"; import { Message, ReactionEmoji, User } from "discord-types/general"; @@ -36,7 +36,7 @@ let reactions: Record; function fetchReactions(msg: Message, emoji: ReactionEmoji, type: number) { const key = emoji.name + (emoji.id ? `:${emoji.id}` : ""); return RestAPI.get({ - url: `/channels/${msg.channel_id}/messages/${msg.id}/reactions/${key}`, + url: Constants.Endpoints.REACTIONS(msg.channel_id, msg.id, key), query: { limit: 100, type diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 74e1aefe8..57202ba3c 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -17,7 +17,7 @@ */ import { MessageObject } from "@api/MessageEvents"; -import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Guild, Message, User } from "discord-types/general"; import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal"; @@ -162,7 +162,7 @@ export async function fetchUserProfile(id: string, options?: FetchUserProfileOpt FluxDispatcher.dispatch({ type: "USER_PROFILE_FETCH_START", userId: id }); const { body } = await RestAPI.get({ - url: `/users/${id}/profile`, + url: Constants.Endpoints.USER_PROFILE(id), query: { with_mutual_guilds: false, with_mutual_friends_count: false, From 12376c622ee1568d7c4633272362534ca7aea2df Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:52:35 +0200 Subject: [PATCH 103/134] fix settings ui on canary --- src/plugins/_core/settings.tsx | 112 ++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 772ee9b64..0a6aea8b9 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -26,7 +26,7 @@ import UpdaterTab from "@components/VencordSettings/UpdaterTab"; import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { React } from "@webpack/common"; +import { i18n, React } from "@webpack/common"; import gitHash from "~git-hash"; @@ -36,41 +36,55 @@ export default definePlugin({ authors: [Devs.Ven, Devs.Megu], required: true, - patches: [{ - find: ".versionHash", - replacement: [ - { - match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, - replace: (m, component, props) => { - props = props.replace(/children:\[.+\]/, ""); - return `${m},$self.makeInfoElements(${component}, ${props})`; + patches: [ + { + find: ".versionHash", + replacement: [ + { + match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + replace: (m, component, props) => { + props = props.replace(/children:\[.+\]/, ""); + return `${m},$self.makeInfoElements(${component}, ${props})`; + } } + ] + }, + // Discord Stable + // FIXME: remove once change merged to stable + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + get match() { + switch (Settings.plugins.Settings.settingsLocation) { + case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; + case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; + case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; + case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; + case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; + case "aboveActivity": + default: + return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; + } + }, + replace: "...$self.makeSettingsCategories($1),$&" + } + }, + // Discord Canary + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/, + replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` + } + }, + { + find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", + replacement: { + match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, + replace: "$2.default.open($1);return;" } - ] - }, { - find: "Messages.ACTIVITY_SETTINGS", - replacement: { - get match() { - switch (Settings.plugins.Settings.settingsLocation) { - case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; - case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; - case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; - case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; - case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; - case "aboveActivity": - default: - return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; - } - }, - replace: "...$self.makeSettingsCategories($1),$&" } - }, { - find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", - replacement: { - match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, - replace: "$2.default.open($1);return;" - } - }], + ], customSections: [] as ((SectionTypes: Record) => any)[], @@ -130,19 +144,43 @@ export default definePlugin({ ].filter(Boolean); }, + isRightSpot({ header, settings }: { header?: string; settings?: string[]; }) { + const firstChild = settings?.[0]; + // lowest two elements... sanity backup + if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true; + + const { settingsLocation } = Settings.plugins.Settings; + + if (settingsLocation === "bottom") return firstChild === "LOGOUT"; + if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + + const names = { + top: i18n.Messages.USER_SETTINGS, + aboveNitro: i18n.Messages.BILLING_SETTINGS, + belowNitro: i18n.Messages.APP_SETTINGS, + aboveActivity: i18n.Messages.ACTIVITY_SETTINGS + }; + return header === names[settingsLocation]; + }, + + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { + if (!this.isRightSpot(element)) return; + + elements.push(...this.makeSettingsCategories(sectionTypes)); + }, + options: { settingsLocation: { type: OptionType.SELECT, description: "Where to put the Vencord settings section", options: [ { label: "At the very top", value: "top" }, - { label: "Above the Nitro section", value: "aboveNitro" }, + { label: "Above the Nitro section", value: "aboveNitro", default: true }, { label: "Below the Nitro section", value: "belowNitro" }, - { label: "Above Activity Settings", value: "aboveActivity", default: true }, + { label: "Above Activity Settings", value: "aboveActivity" }, { label: "Below Activity Settings", value: "belowActivity" }, { label: "At the very bottom", value: "bottom" }, - ], - restartNeeded: true + ] }, }, From a54b55edad3e33c44ac1419d7d20c1724a528f7e Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:54:00 +0200 Subject: [PATCH 104/134] bump to v1.8.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e5845987..95f98a8ba 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.3", + "version": "1.8.4", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 719c6140f3fafb0ae04323268651f0b4f919af91 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 21:18:43 +0200 Subject: [PATCH 105/134] fix Vencord Settings section being added multiple times --- src/plugins/_core/settings.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 0a6aea8b9..b09af2c05 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -154,6 +154,8 @@ export default definePlugin({ if (settingsLocation === "bottom") return firstChild === "LOGOUT"; if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + if (!header) return; + const names = { top: i18n.Messages.USER_SETTINGS, aboveNitro: i18n.Messages.BILLING_SETTINGS, @@ -163,8 +165,12 @@ export default definePlugin({ return header === names[settingsLocation]; }, + patchedSettings: new WeakSet(), + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { - if (!this.isRightSpot(element)) return; + if (this.patchedSettings.has(elements) || !this.isRightSpot(element)) return; + + this.patchedSettings.add(elements); elements.push(...this.makeSettingsCategories(sectionTypes)); }, From d8b3869b8113f304a352677907c6ee9975ee0cd1 Mon Sep 17 00:00:00 2001 From: Board <26598490+BoardTM@users.noreply.github.com> Date: Wed, 15 May 2024 01:07:33 +0200 Subject: [PATCH 106/134] ThemeAttributes: add larger avatar url variables to avatars (#2449) Co-authored-by: vee --- src/plugins/themeAttributes/README.md | 10 ++++++++- src/plugins/themeAttributes/index.ts | 30 ++++++++++++++++++++++++++- src/utils/constants.ts | 4 ++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/plugins/themeAttributes/README.md b/src/plugins/themeAttributes/README.md index 87cb803c5..89001aae4 100644 --- a/src/plugins/themeAttributes/README.md +++ b/src/plugins/themeAttributes/README.md @@ -1,6 +1,6 @@ # ThemeAttributes -This plugin adds data attributes to various elements inside Discord +This plugin adds data attributes and CSS variables to various elements inside Discord This allows themes to more easily theme those elements or even do things that otherwise wouldn't be possible @@ -19,3 +19,11 @@ This allows themes to more easily theme those elements or even do things that ot - `data-is-self` is a boolean indicating whether this is the current user's message ![image](https://github.com/Vendicated/Vencord/assets/45497981/34bd5053-3381-402f-82b2-9c812cc7e122) + +## CSS Variables + +### Avatars + +`--avatar-url-` contains a URL for the users avatar with the size attribute adjusted for the resolutions `128, 256, 512, 1024, 2048, 4096`. + +![image](https://github.com/Vendicated/Vencord/assets/26598490/192ddac0-c827-472f-9933-fa99ff36f723) diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index b8ceac621..b80844546 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -9,10 +9,11 @@ import definePlugin from "@utils/types"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; + export default definePlugin({ name: "ThemeAttributes", description: "Adds data attributes to various elements for theming purposes", - authors: [Devs.Ven], + authors: [Devs.Ven, Devs.Board], patches: [ // Add data-tab-id to all tab bar items @@ -32,9 +33,36 @@ export default definePlugin({ match: /\.messageListItem(?=,"aria)/, replace: "$&,...$self.getMessageProps(arguments[0])" } + }, + + // add --avatar-url- css variable to avatar img elements + // popout profiles + { + find: ".LABEL_WITH_ONLINE_STATUS", + replacement: { + match: /src:null!=\i\?(\i).{1,50}"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } + }, + // chat avatars + { + find: "showCommunicationDisabledStyles", + replacement: { + match: /src:(\i),"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } } ], + getAvatarStyles(src: string) { + return Object.fromEntries( + [128, 256, 512, 1024, 2048, 4096].map(size => [ + `--avatar-url-${size}`, + `url(${src.replace(/\d+$/, String(size))})` + ]) + ); + }, + getMessageProps(props: { message: Message; }) { const author = props.message?.author; const authorId = author?.id; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e446a27b6..69c18cd56 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -382,6 +382,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ant0n", id: 145224646868860928n }, + Board: { + name: "BoardTM", + id: 285475344817848320n, + }, philipbry: { name: "philipbry", id: 554994003318276106n From 5232a85319d3db6fa30e6dd638f19582aae092c5 Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:18:30 -0700 Subject: [PATCH 107/134] new plugin NoServerEmoji ~ hides server emojis from autocomplete (#1787) Co-authored-by: vee --- src/plugins/noServerEmojis/index.ts | 50 +++++++++++++++++++++++++++++ src/utils/constants.ts | 4 +++ 2 files changed, 54 insertions(+) create mode 100644 src/plugins/noServerEmojis/index.ts diff --git a/src/plugins/noServerEmojis/index.ts b/src/plugins/noServerEmojis/index.ts new file mode 100644 index 000000000..ed843769c --- /dev/null +++ b/src/plugins/noServerEmojis/index.ts @@ -0,0 +1,50 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + shownEmojis: { + description: "The types of emojis to show in the autocomplete menu.", + type: OptionType.SELECT, + default: "onlyUnicode", + options: [ + { label: "Only unicode emojis", value: "onlyUnicode" }, + { label: "Unicode emojis and server emojis from current server", value: "currentServer" }, + { label: "Unicode emojis and all server emojis (Discord default)", value: "all" } + ] + } +}); + +export default definePlugin({ + name: "NoServerEmojis", + authors: [Devs.UlyssesZhan], + description: "Do not show server emojis in the autocomplete menu.", + settings, + patches: [ + { + find: "}searchWithoutFetchingLatest(", + replacement: { + match: /searchWithoutFetchingLatest.{20,300}get\((\i).{10,40}?reduce\(\((\i),(\i)\)=>\{/, + replace: "$& if ($self.shouldSkip($1, $3)) return $2;" + } + } + ], + shouldSkip(guildId: string, emoji: any) { + if (emoji.type !== "GUILD_EMOJI") { + return false; + } + if (settings.store.shownEmojis === "onlyUnicode") { + return true; + } + if (settings.store.shownEmojis === "currentServer") { + return emoji.guildId !== guildId; + } + return false; + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 69c18cd56..21d891900 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -378,6 +378,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ProffDea", id: 609329952180928513n }, + UlyssesZhan: { + name: "UlyssesZhan", + id: 586808226058862623n + }, ant0n: { name: "ant0n", id: 145224646868860928n From 81d3f5df1a5b0faee051a7b8cd74f4f45386e4c3 Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:21:00 -0700 Subject: [PATCH 108/134] new plugin CtrlEnterSend (#1794) Co-authored-by: vee --- src/plugins/ctrlEnterSend/index.ts | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/plugins/ctrlEnterSend/index.ts diff --git a/src/plugins/ctrlEnterSend/index.ts b/src/plugins/ctrlEnterSend/index.ts new file mode 100644 index 000000000..4b9dd8e06 --- /dev/null +++ b/src/plugins/ctrlEnterSend/index.ts @@ -0,0 +1,68 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +export default definePlugin({ + name: "CtrlEnterSend", + authors: [Devs.UlyssesZhan], + description: "Use Ctrl+Enter to send messages (customizable)", + settings: definePluginSettings({ + submitRule: { + description: "The way to send a message", + type: OptionType.SELECT, + options: [ + { + label: "Ctrl+Enter (Enter or Shift+Enter for new line)", + value: "ctrl+enter" + }, + { + label: "Shift+Enter (Enter for new line)", + value: "shift+enter" + }, + { + label: "Enter (Shift+Enter for new line; Discord default)", + value: "enter" + } + ], + default: "ctrl+enter" + }, + sendMessageInTheMiddleOfACodeBlock: { + description: "Whether to send a message in the middle of a code block", + type: OptionType.BOOLEAN, + default: true, + } + }), + patches: [ + { + find: "KeyboardKeys.ENTER&&(!", + replacement: { + match: /(?<=(\i)\.which===\i\.KeyboardKeys.ENTER&&).{0,100}(\(0,\i\.hasOpenPlainTextCodeBlock\)\(\i\)).{0,100}(?=&&\(\i\.preventDefault)/, + replace: "$self.shouldSubmit($1, $2)" + } + } + ], + shouldSubmit(event: KeyboardEvent, codeblock: boolean): boolean { + let result = false; + switch (this.settings.store.submitRule) { + case "shift+enter": + result = event.shiftKey; + break; + case "ctrl+enter": + result = event.ctrlKey; + break; + case "enter": + result = !event.shiftKey && !event.ctrlKey; + break; + } + if (!this.settings.store.sendMessageInTheMiddleOfACodeBlock) { + result &&= !codeblock; + } + return result; + } +}); From 97dd56ccdab091ba65b6e25efd172b0464b191d5 Mon Sep 17 00:00:00 2001 From: ! Sleepy <109904491+eepyfemboi@users.noreply.github.com> Date: Tue, 14 May 2024 17:17:19 -0700 Subject: [PATCH 109/134] MoreUserTags: Add chat moderator tag (#2424) Co-authored-by: Vendicated --- src/plugins/moreUserTags/index.tsx | 42 ++++++++++-------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index df47e5456..1257b4524 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -50,6 +50,7 @@ interface TagSettings { MODERATOR_STAFF: TagSetting, MODERATOR: TagSetting, VOICE_MODERATOR: TagSetting, + TRIAL_MODERATOR: TagSetting, [k: string]: TagSetting; } @@ -93,6 +94,11 @@ const tags: Tag[] = [ displayName: "VC Mod", description: "Can manage voice chats", permissions: ["MOVE_MEMBERS", "MUTE_MEMBERS", "DEAFEN_MEMBERS"] + }, { + name: "CHAT_MODERATOR", + displayName: "Chat Mod", + description: "Can timeout people", + permissions: ["MODERATE_MEMBERS"] } ]; const defaultSettings = Object.fromEntries( @@ -263,34 +269,14 @@ export default definePlugin({ ], start() { - if (settings.store.tagSettings) return; - // @ts-ignore - if (!settings.store.visibility_WEBHOOK) settings.store.tagSettings = defaultSettings; - else { - const newSettings = { ...defaultSettings }; - Object.entries(Vencord.PlainSettings.plugins.MoreUserTags).forEach(([name, value]) => { - const [setting, tag] = name.split("_"); - if (setting === "visibility") { - switch (value) { - case "always": - // its the default - break; - case "chat": - newSettings[tag].showInNotChat = false; - break; - case "not-chat": - newSettings[tag].showInChat = false; - break; - case "never": - newSettings[tag].showInChat = false; - newSettings[tag].showInNotChat = false; - break; - } - } - settings.store.tagSettings = newSettings; - delete Vencord.Settings.plugins.MoreUserTags[name]; - }); - } + settings.store.tagSettings ??= defaultSettings; + + // newly added field might be missing from old users + settings.store.tagSettings.CHAT_MODERATOR ??= { + text: "Chat Mod", + showInChat: true, + showInNotChat: true + }; }, getPermissions(user: User, channel: Channel): string[] { From 840d571ce2b756f2bde31296bec433930df14413 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 21:34:25 -0300 Subject: [PATCH 110/134] Fix BetterSettings & StartupTimings patch --- src/plugins/betterSettings/index.tsx | 2 +- src/plugins/startupTimings/index.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 5064bd538..e90e5c82a 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -119,7 +119,7 @@ export default definePlugin({ { // Settings cog context menu find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { - match: /\(0,\i.default\)\(\)(?=\.filter\(\i=>\{let\{section:\i\}=)/, + match: /\(0,\i.useDefaultUserSettingsSections\)\(\)(?=\.filter\(\i=>\{let\{section:\i\}=)/, replace: "$self.wrapMenu($&)" } } diff --git a/src/plugins/startupTimings/index.tsx b/src/plugins/startupTimings/index.tsx index 742d822ae..cf366df38 100644 --- a/src/plugins/startupTimings/index.tsx +++ b/src/plugins/startupTimings/index.tsx @@ -26,10 +26,12 @@ export default definePlugin({ description: "Adds Startup Timings to the Settings menu", authors: [Devs.Megu], patches: [{ - find: "UserSettingsSections.PAYMENT_FLOW_MODAL_TEST_PAGE,", + find: "Messages.ACTIVITY_SETTINGS", replacement: { - match: /{section:\i\.UserSettingsSections\.PAYMENT_FLOW_MODAL_TEST_PAGE/, - replace: '{section:"StartupTimings",label:"Startup Timings",element:$self.StartupTimingPage},$&' + match: /(?<=}\)([,;])(\i\.settings)\.forEach.+?(\i)\.push.+}\))/, + replace: (_, commaOrSemi, settings, elements) => "" + + `${commaOrSemi}${settings}?.[0]==="CHANGELOG"` + + `&&${elements}.push({section:"StartupTimings",label:"Startup Timings",element:$self.StartupTimingPage})` } }], StartupTimingPage From 0e4724ec0d2ee3c9bd15f81d29dcbd8fec1211ce Mon Sep 17 00:00:00 2001 From: Vendicated Date: Wed, 15 May 2024 03:14:02 +0200 Subject: [PATCH 111/134] Settings: remove obsolete patch; add redundancy & more useful dbg copy --- src/plugins/_core/settings.tsx | 79 +++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index b09af2c05..81d1d1797 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -30,6 +30,9 @@ import { i18n, React } from "@webpack/common"; import gitHash from "~git-hash"; +type SectionType = "HEADER" | "DIVIDER" | "CUSTOM"; +type SectionTypes = Record; + export default definePlugin({ name: "Settings", description: "Adds Settings UI and debug info", @@ -41,34 +44,18 @@ export default definePlugin({ find: ".versionHash", replacement: [ { - match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + match: /\[\(0,\i\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, replace: (m, component, props) => { props = props.replace(/children:\[.+\]/, ""); return `${m},$self.makeInfoElements(${component}, ${props})`; } + }, + { + match: /copyValue:\i\.join\(" "\)/, + replace: "$& + $self.getInfoString()" } ] }, - // Discord Stable - // FIXME: remove once change merged to stable - { - find: "Messages.ACTIVITY_SETTINGS", - replacement: { - get match() { - switch (Settings.plugins.Settings.settingsLocation) { - case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; - case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; - case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; - case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; - case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; - case "aboveActivity": - default: - return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; - } - }, - replace: "...$self.makeSettingsCategories($1),$&" - } - }, // Discord Canary { find: "Messages.ACTIVITY_SETTINGS", @@ -77,6 +64,13 @@ export default definePlugin({ replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` } }, + { + find: "useDefaultUserSettingsSections:function", + replacement: { + match: /(?<=useDefaultUserSettingsSections:function\(\){return )(\i)\}/, + replace: "$self.wrapSettingsHook($1)}" + } + }, { find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { @@ -86,9 +80,9 @@ export default definePlugin({ } ], - customSections: [] as ((SectionTypes: Record) => any)[], + customSections: [] as ((SectionTypes: SectionTypes) => any)[], - makeSettingsCategories(SectionTypes: Record) { + makeSettingsCategories(SectionTypes: SectionTypes) { return [ { section: SectionTypes.HEADER, @@ -167,7 +161,7 @@ export default definePlugin({ patchedSettings: new WeakSet(), - addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: SectionTypes) { if (this.patchedSettings.has(elements) || !this.isRightSpot(element)) return; this.patchedSettings.add(elements); @@ -175,6 +169,20 @@ export default definePlugin({ elements.push(...this.makeSettingsCategories(sectionTypes)); }, + wrapSettingsHook(originalHook: (...args: any[]) => Record[]) { + return (...args: any[]) => { + const elements = originalHook(...args); + if (!this.patchedSettings.has(elements)) + elements.unshift(...this.makeSettingsCategories({ + HEADER: "HEADER", + DIVIDER: "DIVIDER", + CUSTOM: "CUSTOM" + })); + + return elements; + }; + }, + options: { settingsLocation: { type: OptionType.SELECT, @@ -213,15 +221,24 @@ export default definePlugin({ return ""; }, - makeInfoElements(Component: React.ComponentType, props: React.PropsWithChildren) { + getInfoRows() { const { electronVersion, chromiumVersion, additionalInfo } = this; - return ( - <> - Vencord {gitHash}{additionalInfo} - {electronVersion && Electron {electronVersion}} - {chromiumVersion && Chromium {chromiumVersion}} - + const rows = [`Vencord ${gitHash}${additionalInfo}`]; + + if (electronVersion) rows.push(`Electron ${electronVersion}`); + if (chromiumVersion) rows.push(`Chromium ${chromiumVersion}`); + + return rows; + }, + + getInfoString() { + return "\n" + this.getInfoRows().join("\n"); + }, + + makeInfoElements(Component: React.ComponentType, props: React.PropsWithChildren) { + return this.getInfoRows().map((text, i) => + {text} ); } }); From 46801de21fc587118710873bee7e78f517932cf0 Mon Sep 17 00:00:00 2001 From: mcpower Date: Wed, 15 May 2024 11:42:09 +1000 Subject: [PATCH 112/134] chore: tidy up suggested vscode extensions list (#2221) Co-authored-by: Vendicated --- .vscode/extensions.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f16f1e273..e86effb19 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,11 +1,9 @@ { "recommendations": [ "dbaeumer.vscode-eslint", - "eamodio.gitlens", "EditorConfig.EditorConfig", - "ExodiusStudios.comment-anchors", - "formulahendry.auto-rename-tag", "GregorBiswanger.json2ts", - "stylelint.vscode-stylelint" + "stylelint.vscode-stylelint", + "Vendicated.vencord-companion" ] } From 1fea8420938a4dfd519881132d5782a30604112a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 22:47:19 -0300 Subject: [PATCH 113/134] BetterFolders: Fix scrolling --- src/plugins/betterFolders/index.tsx | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index d252682f8..795f19901 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { FluxDispatcher, i18n } from "@webpack/common"; +import { FluxDispatcher, i18n, useMemo } from "@webpack/common"; import FolderSideBar from "./FolderSideBar"; @@ -117,8 +117,8 @@ export default definePlugin({ }, // If we are rendering the Better Folders sidebar, we filter out guilds that are not in folders and unexpanded folders { - match: /(useStateFromStoresArray\).{0,25}let \i)=(\i\.\i.getGuildsTree\(\))/, - replace: (_, rest, guildsTree) => `${rest}=$self.getGuildTree(!!arguments[0].isBetterFolders,${guildsTree},arguments[0].betterFoldersExpandedIds)` + match: /\[(\i)\]=(\(0,\i\.useStateFromStoresArray\).{0,40}getGuildsTree\(\).+?}\))(?=,)/, + replace: (_, originalTreeVar, rest) => `[betterFoldersOriginalTree]=${rest},${originalTreeVar}=$self.getGuildTree(!!arguments[0].isBetterFolders,betterFoldersOriginalTree,arguments[0].betterFoldersExpandedIds)` }, // If we are rendering the Better Folders sidebar, we filter out everything but the servers and folders from the GuildsBar Guild List children { @@ -252,19 +252,21 @@ export default definePlugin({ } }, - getGuildTree(isBetterFolders: boolean, oldTree: any, expandedFolderIds?: Set) { - if (!isBetterFolders || expandedFolderIds == null) return oldTree; + getGuildTree(isBetterFolders: boolean, originalTree: any, expandedFolderIds?: Set) { + return useMemo(() => { + if (!isBetterFolders || expandedFolderIds == null) return originalTree; - const newTree = new GuildsTree(); - // Children is every folder and guild which is not in a folder, this filters out only the expanded folders - newTree.root.children = oldTree.root.children.filter(guildOrFolder => expandedFolderIds.has(guildOrFolder.id)); - // Nodes is every folder and guild, even if it's in a folder, this filters out only the expanded folders and guilds inside them - newTree.nodes = Object.fromEntries( - Object.entries(oldTree.nodes) - .filter(([_, guildOrFolder]: any[]) => expandedFolderIds.has(guildOrFolder.id) || expandedFolderIds.has(guildOrFolder.parentId)) - ); + const newTree = new GuildsTree(); + // Children is every folder and guild which is not in a folder, this filters out only the expanded folders + newTree.root.children = originalTree.root.children.filter(guildOrFolder => expandedFolderIds.has(guildOrFolder.id)); + // Nodes is every folder and guild, even if it's in a folder, this filters out only the expanded folders and guilds inside them + newTree.nodes = Object.fromEntries( + Object.entries(originalTree.nodes) + .filter(([_, guildOrFolder]: any[]) => expandedFolderIds.has(guildOrFolder.id) || expandedFolderIds.has(guildOrFolder.parentId)) + ); - return newTree; + return newTree; + }, [isBetterFolders, originalTree, expandedFolderIds]); }, makeGuildsBarGuildListFilter(isBetterFolders: boolean) { From 4d572670f15d1ce2ffde979eb70714e251d09443 Mon Sep 17 00:00:00 2001 From: Eric <45801973+waresnew@users.noreply.github.com> Date: Tue, 14 May 2024 22:10:29 -0400 Subject: [PATCH 114/134] new plugin ValidReply ~ fix "Message could not be loaded" (#2337) Co-authored-by: V --- src/plugins/validReply/README.md | 7 ++ src/plugins/validReply/index.ts | 106 +++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/plugins/validReply/README.md create mode 100644 src/plugins/validReply/index.ts diff --git a/src/plugins/validReply/README.md b/src/plugins/validReply/README.md new file mode 100644 index 000000000..49e313cf5 --- /dev/null +++ b/src/plugins/validReply/README.md @@ -0,0 +1,7 @@ +# ValidReply + +Fixes referenced (replied to) messages showing as "Message could not be loaded". + +Hover the text to load the message! + +![](https://github.com/Vendicated/Vencord/assets/45801973/d3286acf-e822-4b7f-a4e7-8ced18f581af) diff --git a/src/plugins/validReply/index.ts b/src/plugins/validReply/index.ts new file mode 100644 index 000000000..21a1bdd1f --- /dev/null +++ b/src/plugins/validReply/index.ts @@ -0,0 +1,106 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { FluxDispatcher, RestAPI } from "@webpack/common"; +import { Message, User } from "discord-types/general"; +import { Channel } from "discord-types/general/index.js"; + +const enum ReferencedMessageState { + Loaded, + NotLoaded, + Deleted +} + +interface Reply { + baseAuthor: User, + baseMessage: Message; + channel: Channel; + referencedMessage: { state: ReferencedMessageState; }; + compact: boolean; + isReplyAuthorBlocked: boolean; +} + +const fetching = new Map(); +let ReplyStore: any; + +const { createMessageRecord } = findByPropsLazy("createMessageRecord"); + +export default definePlugin({ + name: "ValidReply", + description: 'Fixes "Message could not be loaded" upon hovering over the reply', + authors: [Devs.newwares], + patches: [ + { + find: "Messages.REPLY_QUOTE_MESSAGE_NOT_LOADED", + replacement: { + match: /Messages\.REPLY_QUOTE_MESSAGE_NOT_LOADED/, + replace: "$&,onMouseEnter:()=>$self.fetchReply(arguments[0])" + } + }, + { + find: "ReferencedMessageStore", + replacement: { + match: /constructor\(\)\{\i\(this,"_channelCaches",new Map\)/, + replace: "$&;$self.setReplyStore(this);" + } + } + ], + + setReplyStore(store: any) { + ReplyStore = store; + }, + + async fetchReply(reply: Reply) { + const { channel_id: channelId, message_id: messageId } = reply.baseMessage.messageReference!; + + if (fetching.has(messageId)) { + return; + } + fetching.set(messageId, channelId); + + RestAPI.get({ + url: `/channels/${channelId}/messages`, + query: { + limit: 1, + around: messageId + }, + retries: 2 + }) + .then(res => { + const reply: Message | undefined = res?.body?.[0]; + if (!reply) return; + + if (reply.id !== messageId) { + ReplyStore.set(channelId, messageId, { + state: ReferencedMessageState.Deleted + }); + + FluxDispatcher.dispatch({ + type: "MESSAGE_DELETE", + channelId: channelId, + message: messageId + }); + } else { + ReplyStore.set(reply.channel_id, reply.id, { + state: ReferencedMessageState.Loaded, + message: createMessageRecord(reply) + }); + + FluxDispatcher.dispatch({ + type: "MESSAGE_UPDATE", + message: reply + }); + } + }) + .catch(() => { }) + .finally(() => { + fetching.delete(messageId); + }); + } +}); From f4d64616904dabc1b8bd4dd15fccc31c45c147d0 Mon Sep 17 00:00:00 2001 From: Aztup <55710232+Aztup@users.noreply.github.com> Date: Wed, 15 May 2024 04:35:00 +0200 Subject: [PATCH 115/134] feat(plugins/openInApp) Add tidal support (#2404) Co-authored-by: vee --- src/main/utils/constants.ts | 1 + src/plugins/openInApp/index.ts | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/utils/constants.ts b/src/main/utils/constants.ts index 6c076c328..9513da51c 100644 --- a/src/main/utils/constants.ts +++ b/src/main/utils/constants.ts @@ -35,6 +35,7 @@ export const ALLOWED_PROTOCOLS = [ "steam:", "spotify:", "com.epicgames.launcher:", + "tidal:" ]; export const IS_VANILLA = /* @__PURE__ */ process.argv.includes("--vanilla"); diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 0835c0612..83da5f3c3 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -26,6 +26,7 @@ const ShortUrlMatcher = /^https:\/\/(spotify\.link|s\.team)\/.+$/; const SpotifyMatcher = /^https:\/\/open\.spotify\.com\/(track|album|artist|playlist|user|episode)\/(.+)(?:\?.+?)?$/; const SteamMatcher = /^https:\/\/(steamcommunity\.com|(?:help|store)\.steampowered\.com)\/.+$/; const EpicMatcher = /^https:\/\/store\.epicgames\.com\/(.+)$/; +const TidalMatcher = /^https:\/\/tidal\.com\/browse\/(track|album|artist|playlist|user|video|mix)\/(.+)(?:\?.+?)?$/; const settings = definePluginSettings({ spotify: { @@ -42,6 +43,11 @@ const settings = definePluginSettings({ type: OptionType.BOOLEAN, description: "Open Epic Games links in the Epic Games Launcher", default: true, + }, + tidal: { + type: OptionType.BOOLEAN, + description: "Open Tidal links in the Tidal app", + default: true, } }); @@ -49,7 +55,7 @@ const Native = VencordNative.pluginHelpers.OpenInApp as PluginNative Date: Tue, 14 May 2024 22:44:47 -0400 Subject: [PATCH 116/134] PetPet: Fix Upload Image Option (#2461) --- src/plugins/crashHandler/index.ts | 25 +++++++++++++------------ src/plugins/fakeNitro/index.tsx | 5 ++--- src/plugins/petpet/index.ts | 17 ++++++++++++----- src/utils/constants.ts | 6 +++++- src/webpack/common/stores.ts | 7 +------ src/webpack/common/types/stores.d.ts | 9 +++++++++ src/webpack/common/utils.ts | 2 ++ src/webpack/webpack.ts | 2 +- 8 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index 10053021f..3297ca300 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -24,22 +24,20 @@ import { closeAllModals } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { maybePromptToUpdate } from "@utils/updater"; import { filters, findBulk, proxyLazyWebpack } from "@webpack"; -import { FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; +import { DraftType, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; const CrashHandlerLogger = new Logger("CrashHandler"); -const { ModalStack, DraftManager, DraftType, closeExpressionPicker } = proxyLazyWebpack(() => { - const modules = findBulk( + +const { ModalStack, DraftManager, closeExpressionPicker } = proxyLazyWebpack(() => { + const [ModalStack, DraftManager, ExpressionManager] = findBulk( filters.byProps("pushLazy", "popAll"), filters.byProps("clearDraft", "saveDraft"), - filters.byProps("DraftType"), - filters.byProps("closeExpressionPicker", "openExpressionPicker"), - ); + filters.byProps("closeExpressionPicker", "openExpressionPicker"),); return { - ModalStack: modules[0], - DraftManager: modules[1], - DraftType: modules[2]?.DraftType, - closeExpressionPicker: modules[3]?.closeExpressionPicker, + ModalStack, + DraftManager, + closeExpressionPicker: ExpressionManager?.closeExpressionPicker, }; }); @@ -137,8 +135,11 @@ export default definePlugin({ try { const channelId = SelectedChannelStore.getChannelId(); - DraftManager.clearDraft(channelId, DraftType.ChannelMessage); - DraftManager.clearDraft(channelId, DraftType.FirstThreadMessage); + for (const key in DraftType) { + if (!Number.isNaN(Number(key))) continue; + + DraftManager.clearDraft(channelId, DraftType[key]); + } } catch (err) { CrashHandlerLogger.debug("Failed to clear drafts.", err); } diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 293183664..a55a7771e 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -24,13 +24,12 @@ import { getCurrentGuild } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack"; -import { Alerts, ChannelStore, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; +import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; import type { CustomEmoji } from "@webpack/types"; import type { Message } from "discord-types/general"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; import type { ReactElement, ReactNode } from "react"; -const DRAFT_TYPE = 0; const StickerStore = findStoreLazy("StickersStore") as { getPremiumPacks(): StickerPack[]; getAllGuildStickers(): Map; @@ -807,7 +806,7 @@ export default definePlugin({ gif.finish(); const file = new File([gif.bytesView()], `${stickerId}.gif`, { type: "image/gif" }); - UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DRAFT_TYPE); + UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage); }, canUseEmote(e: CustomEmoji, channelId: string) { diff --git a/src/plugins/petpet/index.ts b/src/plugins/petpet/index.ts index 3f9743255..2e06d0b17 100644 --- a/src/plugins/petpet/index.ts +++ b/src/plugins/petpet/index.ts @@ -21,10 +21,9 @@ import { Devs } from "@utils/constants"; import { makeLazy } from "@utils/lazy"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { UploadHandler, UserUtils } from "@webpack/common"; +import { DraftType, UploadHandler, UploadManager, UserUtils } from "@webpack/common"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; -const DRAFT_TYPE = 0; const DEFAULT_DELAY = 20; const DEFAULT_RESOLUTION = 128; const FRAMES = 10; @@ -59,9 +58,12 @@ async function resolveImage(options: Argument[], ctx: CommandContext, noServerPf for (const opt of options) { switch (opt.name) { case "image": - const upload = UploadStore.getUploads(ctx.channel.id, DRAFT_TYPE)[0]; + const upload = UploadStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand); if (upload) { - if (!upload.isImage) throw "Upload is not an image"; + if (!upload.isImage) { + UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand); + throw "Upload is not an image"; + } return upload.item.file; } break; @@ -73,10 +75,12 @@ async function resolveImage(options: Argument[], ctx: CommandContext, noServerPf return user.getAvatarURL(noServerPfp ? void 0 : ctx.guild?.id, 2048).replace(/\?size=\d+$/, "?size=2048"); } catch (err) { console.error("[petpet] Failed to fetch user\n", err); + UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand); throw "Failed to fetch user. Check the console for more info."; } } } + UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand); return null; } @@ -130,6 +134,7 @@ export default definePlugin({ var url = await resolveImage(opts, cmdCtx, noServerPfp); if (!url) throw "No Image specified!"; } catch (err) { + UploadManager.clearAll(cmdCtx.channel.id, DraftType.SlashCommand); sendBotMessage(cmdCtx.channel.id, { content: String(err), }); @@ -147,6 +152,8 @@ export default definePlugin({ canvas.width = canvas.height = resolution; const ctx = canvas.getContext("2d")!; + UploadManager.clearAll(cmdCtx.channel.id, DraftType.SlashCommand); + for (let i = 0; i < FRAMES; i++) { ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -174,7 +181,7 @@ export default definePlugin({ const file = new File([gif.bytesView()], "petpet.gif", { type: "image/gif" }); // Immediately after the command finishes, Discord clears all input, including pending attachments. // Thus, setTimeout is needed to make this execute after Discord cleared the input - setTimeout(() => UploadHandler.promptToUpload([file], cmdCtx.channel, DRAFT_TYPE), 10); + setTimeout(() => UploadHandler.promptToUpload([file], cmdCtx.channel, DraftType.ChannelMessage), 10); }, }, ] diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 21d891900..a77edf7d5 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -485,7 +485,11 @@ export const Devs = /* #__PURE__*/ Object.freeze({ xocherry: { name: "xocherry", id: 221288171013406720n - } + }, + ScattrdBlade: { + name: "ScattrdBlade", + id: 678007540608532491n + }, } satisfies Record); // iife so #__PURE__ works correctly diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index be5721ff3..123c62b05 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -27,12 +27,7 @@ export const Flux: t.Flux = findByPropsLazy("connectStores"); export type GenericStore = t.FluxStore & Record; -export enum DraftType { - ChannelMessage = 0, - ThreadSettings = 1, - FirstThreadMessage = 2, - ApplicationLauncherCommand = 3 -} +export const { DraftType }: { DraftType: typeof t.DraftType; } = findByPropsLazy("DraftType"); export let MessageStore: Omit & { getMessages(chanId: string): any; diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index d6bf3aaf3..27715b5ee 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -173,6 +173,15 @@ export class DraftStore extends FluxStore { getThreadSettings(channelId: string): any | null; } +export enum DraftType { + ChannelMessage, + ThreadSettings, + FirstThreadMessage, + ApplicationLauncherCommand, + Poll, + SlashCommand, +} + export class GuildStore extends FluxStore { getGuild(guildId: string): Guild; getGuildCount(): number; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 6d74e9b25..2cd636d8e 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -119,6 +119,8 @@ export function showToast(message: string, type = ToastType.MESSAGE) { } export const UserUtils = findByPropsLazy("getUser", "fetchCurrentUser") as { getUser: (id: string) => Promise; }; + +export const UploadManager = findByPropsLazy("clearAll", "addFile"); export const UploadHandler = findByPropsLazy("showUploadFileSizeExceededError", "promptToUpload") as { promptToUpload: (files: File[], channel: Channel, draftType: Number) => void; }; diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index 34a9b69c9..8ea6713d0 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -432,7 +432,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def } const [, rawChunkIds, entryPointId] = match; - if (Number.isNaN(entryPointId)) { + if (Number.isNaN(Number(entryPointId))) { const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the chunk ids array, or the entry point id returned as the second group wasn't a number"); logger.warn(err, "Code:", code, "Matcher:", matcher); From f74da73086b2b361490e028c999c80b3ac2ba76a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 23:57:43 -0300 Subject: [PATCH 117/134] feat: Allow finds to use regex (#2452) --- .../VencordSettings/PatchHelperTab.tsx | 44 ++++++++++++++----- src/utils/types.ts | 8 +++- src/webpack/patchWebpack.ts | 7 ++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/components/VencordSettings/PatchHelperTab.tsx b/src/components/VencordSettings/PatchHelperTab.tsx index 064c872ab..9e2980e7e 100644 --- a/src/components/VencordSettings/PatchHelperTab.tsx +++ b/src/components/VencordSettings/PatchHelperTab.tsx @@ -180,7 +180,8 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { return ( <> - replacement + {/* FormTitle adds a class if className is not set, so we set it to an empty string to prevent that */} + replacement {!isFunc && (
- Cheat Sheet + Cheat Sheet {Object.entries({ "\\i": "Special regex escape sequence that matches identifiers (varnames, classnames, etc.)", "$$": "Insert a $", @@ -220,11 +221,12 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { interface FullPatchInputProps { setFind(v: string): void; + setParsedFind(v: string | RegExp): void; setMatch(v: string): void; setReplacement(v: string | ReplaceFn): void; } -function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputProps) { +function FullPatchInput({ setFind, setParsedFind, setMatch, setReplacement }: FullPatchInputProps) { const [fullPatch, setFullPatch] = React.useState(""); const [fullPatchError, setFullPatchError] = React.useState(""); @@ -233,6 +235,7 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro setFullPatchError(""); setFind(""); + setParsedFind(""); setMatch(""); setReplacement(""); return; @@ -256,7 +259,8 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro if (!parsed.replacement.match) throw new Error("No 'replacement.match' field"); if (!parsed.replacement.replace) throw new Error("No 'replacement.replace' field"); - setFind(parsed.find); + setFind(parsed.find instanceof RegExp ? parsed.find.toString() : parsed.find); + setParsedFind(parsed.find); setMatch(parsed.replacement.match instanceof RegExp ? parsed.replacement.match.source : parsed.replacement.match); setReplacement(parsed.replacement.replace); setFullPatchError(""); @@ -266,7 +270,7 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro } return <> - Paste your full JSON patch here to fill out the fields + Paste your full JSON patch here to fill out the fields