From 62e34f55b05f7ee88268cfc53370effffc2724c4 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 1 Jun 2024 12:23:56 +0100 Subject: [PATCH 01/28] feat: add support for additional proxy protocols --- .../handlers/onBeforeVideoWeaverRequest.ts | 2 +- src/background/handlers/onResponseStarted.ts | 2 +- src/common/ts/proxyInfo.ts | 33 ++++++++++++++----- src/common/ts/proxySettings.ts | 2 +- src/options/options.ts | 15 +++++---- src/types.ts | 14 +++++++- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/background/handlers/onBeforeVideoWeaverRequest.ts b/src/background/handlers/onBeforeVideoWeaverRequest.ts index 9eba3c74..deec2f29 100644 --- a/src/background/handlers/onBeforeVideoWeaverRequest.ts +++ b/src/background/handlers/onBeforeVideoWeaverRequest.ts @@ -38,7 +38,7 @@ export default function onBeforeVideoWeaverRequest( textLower.includes("https://example.com") && textLower.includes("https://help.twitch.tv/"); const proxy = - details.proxyInfo && details.proxyInfo.type !== "direct" + details.proxyInfo && details.proxyInfo.type !== "DIRECT" ? getUrlFromProxyInfo(details.proxyInfo) : null; diff --git a/src/background/handlers/onResponseStarted.ts b/src/background/handlers/onResponseStarted.ts index a02b4367..e1883869 100644 --- a/src/background/handlers/onResponseStarted.ts +++ b/src/background/handlers/onResponseStarted.ts @@ -171,7 +171,7 @@ function getProxyFromDetails( return getUrlFromProxyInfo(possibleProxies[0]); } else { const proxyInfo = details.proxyInfo; // Firefox only. - if (!proxyInfo || proxyInfo.type === "direct") return null; + if (!proxyInfo || proxyInfo.type === "DIRECT") return null; return getUrlFromProxyInfo(proxyInfo); } } diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index a053a229..9b06313f 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -1,18 +1,34 @@ import { Address6 } from "ip-address"; -import type { ProxyInfo } from "../../types"; +import type { ProxyInfo, ProxyScheme } from "../../types"; -export function getProxyInfoFromUrl( - url: string -): ProxyInfo & { type: "http"; host: string; port: number } { +export const proxySchemes: { [key: string]: ProxyScheme } = { + direct: "DIRECT", + http: "PROXY", + https: "HTTPS", + socks: "SOCKS", + socks4: "SOCKS4", + socks5: "SOCKS5", + quic: "QUIC", +}; + +export function getProxyInfoFromUrl(url: string) { + let protocol = ""; + if (url.includes("://")) { + let [proto, urlWithoutProtocol] = url.split("://"); + protocol = proto; + url = urlWithoutProtocol; + } const lastIndexOfAt = url.lastIndexOf("@"); - const hostname = url.substring(lastIndexOfAt + 1, url.length); + let hostname = url.substring(lastIndexOfAt + 1, url.length); const lastIndexOfColon = getLastIndexOfColon(hostname); - + hostname; let host: string | undefined = undefined; let port: number | undefined = undefined; if (lastIndexOfColon === -1) { host = hostname; - port = 3128; // Default port + if (!protocol) { + port = 3128; // Default port + } } else { host = hostname.substring(0, lastIndexOfColon); port = Number(hostname.substring(lastIndexOfColon + 1, hostname.length)); @@ -31,7 +47,8 @@ export function getProxyInfoFromUrl( } return { - type: "http", + type: proxySchemes[protocol] ?? "PROXY", + protocol, host, port, username, diff --git a/src/common/ts/proxySettings.ts b/src/common/ts/proxySettings.ts index 22697917..d493f5fd 100644 --- a/src/common/ts/proxySettings.ts +++ b/src/common/ts/proxySettings.ts @@ -92,7 +92,7 @@ function getProxyInfoStringFromUrls(urls: string[]): string { return [ ...urls.map(url => { const proxyInfo = getProxyInfoFromUrl(url); - return `PROXY ${getUrlFromProxyInfo({ + return `${proxyInfo.type} ${getUrlFromProxyInfo({ ...proxyInfo, // Don't include username/password in PAC script. username: undefined, diff --git a/src/options/options.ts b/src/options/options.ts index 078e0b4d..640a6483 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -16,10 +16,9 @@ import sendAdLog from "../common/ts/sendAdLog"; import store from "../store"; import getDefaultState from "../store/getDefaultState"; import type { State } from "../store/types"; -import { KeyOfType, ProxyRequestType } from "../types"; +import { AllowedResult, KeyOfType, ProxyRequestType } from "../types"; //#region Types -type AllowedResult = [boolean, string?]; type InsertMode = "append" | "prepend" | "both"; type StoreStringArrayKey = KeyOfType; type ListOptions = { @@ -323,12 +322,16 @@ function isOptimizedProxyUrlAllowed(url: string): AllowedResult { return [false, "TTV LOL PRO v1 proxies are not compatible"]; } - if (/^https?:\/\//i.test(url)) { - return [false, "Proxy URLs must not contain a protocol (e.g. 'http://')"]; + const proxyInfo = getProxyInfoFromUrl(url); + if (proxyInfo.host.includes("/")) { + return [false, "Proxy URLs must not contain a path (e.g. '/path')"]; } - if (url.includes("/")) { - return [false, "Proxy URLs must not contain a path (e.g. '/path')"]; + try { + const host = url.substring(url.lastIndexOf("@") + 1, url.length); + new URL(`http://${host}`); // Throws if the host is invalid. + } catch { + return [false, `'${url}' is not a valid proxy URL`]; } try { diff --git a/src/types.ts b/src/types.ts index ca7d7a43..ce657e37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,9 +3,21 @@ export type KeyOfType = keyof { [P in keyof T as T[P] extends V ? P : never]: any; }; +export type AllowedResult = [boolean, string?]; + +// From https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md#proxy-server-schemes +export type ProxyScheme = + | "DIRECT" + | "PROXY" + | "HTTPS" + | "SOCKS" + | "SOCKS4" + | "SOCKS5" + | "QUIC"; + // From https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/proxy/ProxyInfo export interface ProxyInfo { - type: "direct" | "http" | "https" | "socks" | "socks4"; + type: ProxyScheme; host?: string; port?: number; username?: string; From a7e7aa0e9312e8d975a8d36c2be128bac84747b3 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 1 Jun 2024 12:23:56 +0100 Subject: [PATCH 02/28] fix: fallback to protocols default port for onAuthRequired --- src/common/ts/proxyInfo.ts | 27 +++++++++++++++++++++------ src/options/options.ts | 3 ++- src/types.ts | 2 -- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index 9b06313f..4e8b482e 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -1,7 +1,7 @@ import { Address6 } from "ip-address"; -import type { ProxyInfo, ProxyScheme } from "../../types"; +import type { ProxyInfo } from "../../types"; -export const proxySchemes: { [key: string]: ProxyScheme } = { +export const proxySchemes = { direct: "DIRECT", http: "PROXY", https: "HTTPS", @@ -9,19 +9,32 @@ export const proxySchemes: { [key: string]: ProxyScheme } = { socks4: "SOCKS4", socks5: "SOCKS5", quic: "QUIC", +} as const; + +type Protocol = keyof typeof proxySchemes; + +const defaultPorts: Partial<{ + [key in keyof typeof proxySchemes]: number; +}> = { + http: 80, + https: 443, + socks: 1080, + socks4: 1080, + socks5: 1080, + quic: 443, }; export function getProxyInfoFromUrl(url: string) { let protocol = ""; if (url.includes("://")) { - let [proto, urlWithoutProtocol] = url.split("://"); - protocol = proto; + let [_protocol, urlWithoutProtocol] = url.split("://"); + protocol = _protocol; url = urlWithoutProtocol; } const lastIndexOfAt = url.lastIndexOf("@"); let hostname = url.substring(lastIndexOfAt + 1, url.length); const lastIndexOfColon = getLastIndexOfColon(hostname); - hostname; + let host: string | undefined = undefined; let port: number | undefined = undefined; if (lastIndexOfColon === -1) { @@ -46,8 +59,10 @@ export function getProxyInfoFromUrl(url: string) { password = credentials.substring(indexOfColon + 1, credentials.length); } + port = port ? port : defaultPorts[protocol as Protocol]; + return { - type: proxySchemes[protocol] ?? "PROXY", + type: proxySchemes[protocol as Protocol] ?? "PROXY", protocol, host, port, diff --git a/src/options/options.ts b/src/options/options.ts index 640a6483..07379535 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -16,9 +16,10 @@ import sendAdLog from "../common/ts/sendAdLog"; import store from "../store"; import getDefaultState from "../store/getDefaultState"; import type { State } from "../store/types"; -import { AllowedResult, KeyOfType, ProxyRequestType } from "../types"; +import { KeyOfType, ProxyRequestType } from "../types"; //#region Types +type AllowedResult = [boolean, string?]; type InsertMode = "append" | "prepend" | "both"; type StoreStringArrayKey = KeyOfType; type ListOptions = { diff --git a/src/types.ts b/src/types.ts index ce657e37..25029349 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,8 +3,6 @@ export type KeyOfType = keyof { [P in keyof T as T[P] extends V ? P : never]: any; }; -export type AllowedResult = [boolean, string?]; - // From https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md#proxy-server-schemes export type ProxyScheme = | "DIRECT" From f2aee154ba68558344df40ff9604f6ee4500f225 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 1 Jun 2024 20:14:56 +0100 Subject: [PATCH 03/28] fix: types --- src/background/handlers/onProxyRequest.ts | 14 +++++++------- src/common/ts/proxyInfo.ts | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/background/handlers/onProxyRequest.ts b/src/background/handlers/onProxyRequest.ts index 5dbaf5fa..a27e60d4 100644 --- a/src/background/handlers/onProxyRequest.ts +++ b/src/background/handlers/onProxyRequest.ts @@ -32,7 +32,7 @@ export default async function onProxyRequest( } const host = getHostFromUrl(details.url); - if (!host) return { type: "direct" }; + if (!host) return { type: "DIRECT" }; const documentHost = details.documentUrl ? getHostFromUrl(details.documentUrl) @@ -43,7 +43,7 @@ export default async function onProxyRequest( !passportHostRegex.test(documentHost) && // Passport requests have a `passport.twitch.tv` document URL. !twitchTvHostRegex.test(documentHost) ) { - return { type: "direct" }; + return { type: "DIRECT" }; } const proxies = store.state.optimizedProxiesEnabled @@ -92,12 +92,12 @@ export default async function onProxyRequest( if (proxyUsherRequest && usherHostRegex.test(host)) { if (details.url.includes("/vod/")) { console.log(`✋ '${details.url}' is a VOD manifest.`); - return { type: "direct" }; + return { type: "DIRECT" }; } const channelName = findChannelFromUsherUrl(details.url); if (isChannelWhitelisted(channelName)) { console.log(`✋ Channel '${channelName}' is whitelisted.`); - return { type: "direct" }; + return { type: "DIRECT" }; } console.log( `⌛ Proxying ${details.url} (${ @@ -119,7 +119,7 @@ export default async function onProxyRequest( findChannelFromTwitchTvUrl(tabUrl); if (isChannelWhitelisted(channelName)) { console.log(`✋ Channel '${channelName}' is whitelisted.`); - return { type: "direct" }; + return { type: "DIRECT" }; } console.log( `⌛ Proxying ${details.url} (${ @@ -149,12 +149,12 @@ export default async function onProxyRequest( return proxyInfoArray; } - return { type: "direct" }; + return { type: "DIRECT" }; } function getProxyInfoArrayFromUrls(urls: string[]): ProxyInfo[] { return [ ...urls.map(getProxyInfoFromUrl), - { type: "direct" } as ProxyInfo, // Fallback to direct connection if all proxies fail. + { type: "DIRECT" } as ProxyInfo, // Fallback to direct connection if all proxies fail. ]; } diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index 4e8b482e..7f42552a 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -27,12 +27,12 @@ const defaultPorts: Partial<{ export function getProxyInfoFromUrl(url: string) { let protocol = ""; if (url.includes("://")) { - let [_protocol, urlWithoutProtocol] = url.split("://"); + const [_protocol, urlWithoutProtocol] = url.split("://"); protocol = _protocol; url = urlWithoutProtocol; } const lastIndexOfAt = url.lastIndexOf("@"); - let hostname = url.substring(lastIndexOfAt + 1, url.length); + const hostname = url.substring(lastIndexOfAt + 1, url.length); const lastIndexOfColon = getLastIndexOfColon(hostname); let host: string | undefined = undefined; From 3536898e23d3609ad86395c27eb84b9bdc86a72a Mon Sep 17 00:00:00 2001 From: younesaassila <47226184+younesaassila@users.noreply.github.com> Date: Fri, 31 Jan 2025 23:07:37 +0100 Subject: [PATCH 04/28] Add WIP implementation of #177 --- src/common/ts/wasChannelSubscriber.ts | 12 ++ src/content/content.ts | 167 +++++++++++++++++--------- src/options/options.ts | 10 ++ src/options/page.html | 17 +++ src/page/getFetch.ts | 49 +++++++- src/store/getDefaultState.ts | 2 + src/store/types.ts | 2 + src/types.ts | 2 + 8 files changed, 206 insertions(+), 55 deletions(-) create mode 100644 src/common/ts/wasChannelSubscriber.ts diff --git a/src/common/ts/wasChannelSubscriber.ts b/src/common/ts/wasChannelSubscriber.ts new file mode 100644 index 00000000..0a372439 --- /dev/null +++ b/src/common/ts/wasChannelSubscriber.ts @@ -0,0 +1,12 @@ +import store from "../../store"; + +export default function wasChannelSubscriber( + channelName: string | null +): boolean { + if (!channelName) return false; + const activeChannelSubscriptionsLower = + store.state.activeChannelSubscriptions.map(channel => + channel.toLowerCase() + ); + return activeChannelSubscriptionsLower.includes(channelName.toLowerCase()); +} diff --git a/src/content/content.ts b/src/content/content.ts index 7477d6f4..120bc2aa 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -2,8 +2,10 @@ import pageScriptURL from "url:../page/page.ts"; import workerScriptURL from "url:../page/worker.ts"; import browser, { Storage } from "webextension-polyfill"; import findChannelFromTwitchTvUrl from "../common/ts/findChannelFromTwitchTvUrl"; +import isChannelWhitelisted from "../common/ts/isChannelWhitelisted"; import isChromium from "../common/ts/isChromium"; import { getStreamStatus, setStreamStatus } from "../common/ts/streamStatus"; +import wasChannelSubscriber from "../common/ts/wasChannelSubscriber"; import store from "../store"; import type { State } from "../store/types"; import { MessageType } from "../types"; @@ -64,6 +66,7 @@ function onStoreChange(changes: Record) { // This is mainly to reduce the amount of messages sent to the page script. // (Also to reduce the number of console logs.) const ignoredKeys: (keyof State)[] = [ + "activeChannelSubscriptions", "adLog", "dnsResponses", "openedTwitchTabs", @@ -102,61 +105,117 @@ function onPageMessage(event: MessageEvent) { const message = event.data?.message; if (!message) return; - switch (message.type) { - case MessageType.GetStoreState: - const sendStoreState = () => { - window.postMessage({ - type: MessageType.PageScriptMessage, - message: { - type: MessageType.GetStoreStateResponse, - state: JSON.parse(JSON.stringify(store.state)), - }, - }); - }; - if (store.readyState === "complete") sendStoreState(); - else store.addEventListener("load", sendStoreState); - break; - case MessageType.EnableFullMode: - try { - browser.runtime.sendMessage(message); - } catch (error) { - console.error( - "[TTV LOL PRO] Failed to send EnableFullMode message", - error - ); - } - break; - case MessageType.DisableFullMode: - try { - browser.runtime.sendMessage(message); - } catch (error) { - console.error( - "[TTV LOL PRO] Failed to send DisableFullMode message", - error - ); + // GetStoreState + if (message.type === MessageType.GetStoreState) { + const sendStoreState = () => { + window.postMessage({ + type: MessageType.PageScriptMessage, + message: { + type: MessageType.GetStoreStateResponse, + state: JSON.parse(JSON.stringify(store.state)), + }, + }); + }; + if (store.readyState === "complete") sendStoreState(); + else store.addEventListener("load", sendStoreState); + } + // EnableFullMode + else if (message.type === MessageType.EnableFullMode) { + try { + browser.runtime.sendMessage(message); + } catch (error) { + console.error( + "[TTV LOL PRO] Failed to send EnableFullMode message", + error + ); + } + } + // DisableFullMode + else if (message.type === MessageType.DisableFullMode) { + try { + browser.runtime.sendMessage(message); + } catch (error) { + console.error( + "[TTV LOL PRO] Failed to send DisableFullMode message", + error + ); + } + } + // ChannelSubscriptionStatus + else if (message.type === MessageType.ChannelSubscriptionStatus) { + const { channelName, isSubscribed, scope } = message; + const wasSubscribed = wasChannelSubscriber(channelName); + let isWhitelisted = isChannelWhitelisted(channelName); + console.log( + "[TTV LOL PRO] Received channel subscription status message. Current state:", + { + wasSubscribed, + isSubscribed, + isWhitelisted, } - break; - case MessageType.UsherResponse: - try { - browser.runtime.sendMessage(message); - } catch (error) { - console.error( - "[TTV LOL PRO] Failed to send UsherResponse message", - error - ); + ); + if (store.state.whitelistChannelSubscriptions && channelName != null) { + if (!wasSubscribed && isSubscribed) { + store.state.activeChannelSubscriptions.push(channelName); + // Add to whitelist. + if (!isWhitelisted) { + console.log(`[TTV LOL PRO] Adding '${channelName}' to whitelist.`); + store.state.whitelistedChannels.push(channelName); + isWhitelisted = true; + } + } else if (wasSubscribed && !isSubscribed) { + store.state.activeChannelSubscriptions = + store.state.activeChannelSubscriptions.filter( + c => c.toLowerCase() !== channelName.toLowerCase() + ); + // Remove from whitelist. + if (isWhitelisted) { + console.log( + `[TTV LOL PRO] Removing '${channelName}' from whitelist.` + ); + store.state.whitelistedChannels = + store.state.whitelistedChannels.filter( + c => c.toLowerCase() !== channelName.toLowerCase() + ); + isWhitelisted = false; + } } - break; - case MessageType.MultipleAdBlockersInUse: - const channelName = findChannelFromTwitchTvUrl(location.href); - if (!channelName) break; - const streamStatus = getStreamStatus(channelName); - setStreamStatus(channelName, { - ...(streamStatus ?? { proxied: false }), - reason: "Another Twitch ad blocker is in use", - }); - break; - case MessageType.ClearStats: - clearStats(message.channelName); - break; + } + console.log("[TTV LOL PRO] Sending channel subscription status response."); + window.postMessage({ + type: + scope === "page" // TODO: Is this necessary? Isn't the scope always "worker"? + ? MessageType.PageScriptMessage + : MessageType.WorkerScriptMessage, + message: { + type: MessageType.ChannelSubscriptionStatusResponse, + isWhitelisted: isWhitelisted, + }, + }); + } + // UsherResponse + else if (message.type === MessageType.UsherResponse) { + try { + browser.runtime.sendMessage(message); + } catch (error) { + console.error( + "[TTV LOL PRO] Failed to send UsherResponse message", + error + ); + } + } + // MultipleAdBlockersInUse + else if (message.type === MessageType.MultipleAdBlockersInUse) { + const channelName = findChannelFromTwitchTvUrl(location.href); + if (!channelName) return; + const streamStatus = getStreamStatus(channelName); + setStreamStatus(channelName, { + ...(streamStatus ?? { proxied: false }), + reason: "Another Twitch ad blocker is in use", + }); + } + // ClearStats + else if (message.type === MessageType.ClearStats) { + clearStats(message.channelName); } } diff --git a/src/options/options.ts b/src/options/options.ts index 078e0b4d..97c0c099 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -75,6 +75,9 @@ const passportLevelProxyUsageWwwElement = $( const whitelistedChannelsListElement = $( "#whitelisted-channels-list" ) as HTMLUListElement; +const whitelistSubscriptionsCheckboxElement = $( + "#whitelist-subscriptions-checkbox" +) as HTMLInputElement; // Proxies const optimizedProxiesInputElement = $("#optimized") as HTMLInputElement; const optimizedProxiesListElement = $( @@ -163,6 +166,12 @@ function main() { return [true]; }, }); + whitelistSubscriptionsCheckboxElement.checked = + store.state.whitelistChannelSubscriptions; + whitelistSubscriptionsCheckboxElement.addEventListener("change", () => { + store.state.whitelistChannelSubscriptions = + whitelistSubscriptionsCheckboxElement.checked; + }); // Proxies if (store.state.optimizedProxiesEnabled) optimizedProxiesInputElement.checked = true; @@ -548,6 +557,7 @@ exportButtonElement.addEventListener("click", () => { optimizedProxies: store.state.optimizedProxies, optimizedProxiesEnabled: store.state.optimizedProxiesEnabled, passportLevel: store.state.passportLevel, + whitelistChannelSubscriptions: store.state.whitelistChannelSubscriptions, whitelistedChannels: store.state.whitelistedChannels, }; saveFile( diff --git a/src/options/page.html b/src/options/page.html index ad6e9d2d..d11724ce 100644 --- a/src/options/page.html +++ b/src/options/page.html @@ -138,6 +138,23 @@

Whitelisted channels

Twitch tabs are whitelisted channels.
    +
      +
    • + + +
      + + This option will automatically add or remove channels from the + whitelist based on your subscriptions. + +
    • +
    diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 32b507c4..b65dca19 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -265,7 +265,42 @@ export function getFetch(pageState: PageState): typeof fetch { encodeURIComponent('"player_type":"frontpage"') ); const channelName = findChannelFromUsherUrl(url); - const isWhitelisted = isChannelWhitelisted(channelName, pageState); + let isWhitelisted = isChannelWhitelisted(channelName, pageState); + if ( + pageState.state?.whitelistChannelSubscriptions && + channelName != null + ) { + const wasSubscribed = wasChannelSubscriber(channelName, pageState); + const isSubscribed = url.includes( + encodeURIComponent('"subscriber":true') + ); + // const isSubscribed = url.includes( + // encodeURIComponent("aminematue") + // ); + const hasSubStatusChanged = + (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); + if (hasSubStatusChanged) { + console.log( + "[TTV LOL PRO] Channel subscription status changed. Sending message…" + ); + try { + const response = + await pageState.sendMessageToContentScriptAndWaitForResponse( + pageState.scope, + { + type: MessageType.ChannelSubscriptionStatus, + scope: pageState.scope, + channelName, + isSubscribed, + }, + MessageType.ChannelSubscriptionStatusResponse + ); + if (typeof response.isWhitelisted === "boolean") { + isWhitelisted = response.isWhitelisted; + } + } catch {} + } + } if (!isLivestream || isFrontpage || isWhitelisted) { console.log( "[TTV LOL PRO] Not flagging Usher request: not a livestream, is frontpage, or is whitelisted." @@ -623,6 +658,18 @@ function isChannelWhitelisted( return whitelistedChannelsLower.includes(channelName.toLowerCase()); } +function wasChannelSubscriber( + channelName: string | null | undefined, + pageState: PageState +): boolean { + if (!channelName) return false; + const activeChannelSubscriptionsLower = + pageState.state?.activeChannelSubscriptions.map(channel => + channel.toLowerCase() + ) ?? []; + return activeChannelSubscriptionsLower.includes(channelName.toLowerCase()); +} + async function flagRequest( request: Request, requestType: ProxyRequestType, diff --git a/src/store/getDefaultState.ts b/src/store/getDefaultState.ts index 4b37bfa9..ea99dc2f 100644 --- a/src/store/getDefaultState.ts +++ b/src/store/getDefaultState.ts @@ -3,6 +3,7 @@ import type { State } from "./types"; export default function getDefaultState() { const state: State = { + activeChannelSubscriptions: [], adLog: [], adLogEnabled: true, adLogLastSent: 0, @@ -18,6 +19,7 @@ export default function getDefaultState() { passportLevel: 0, streamStatuses: {}, videoWeaverUrlsByChannel: {}, + whitelistChannelSubscriptions: true, whitelistedChannels: [], }; return state; diff --git a/src/store/types.ts b/src/store/types.ts index b8e9f331..f244c2d2 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -6,6 +6,7 @@ export type ReadyState = "loading" | "complete"; export type StorageAreaName = "local" | "managed" | "sync"; export interface State { + activeChannelSubscriptions: string[]; adLog: AdLogEntry[]; adLogEnabled: boolean; adLogLastSent: number; @@ -19,6 +20,7 @@ export interface State { passportLevel: number; streamStatuses: Record; videoWeaverUrlsByChannel: Record; + whitelistChannelSubscriptions: boolean; whitelistedChannels: string[]; } diff --git a/src/types.ts b/src/types.ts index ca7d7a43..aea52675 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,6 +79,8 @@ export const enum MessageType { EnableFullMode = "TLP_EnableFullMode", EnableFullModeResponse = "TLP_EnableFullModeResponse", DisableFullMode = "TLP_DisableFullMode", + ChannelSubscriptionStatus = "TLP_ChannelSubscriptionStatus", + ChannelSubscriptionStatusResponse = "TLP_ChannelSubscriptionStatusResponse", UsherResponse = "TLP_UsherResponse", NewPlaybackAccessToken = "TLP_NewPlaybackAccessToken", NewPlaybackAccessTokenResponse = "TLP_NewPlaybackAccessTokenResponse", From 2ce563b271f80c1147d2d0497023cdced69f8816 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 13:34:52 +0100 Subject: [PATCH 05/28] Fix #360 --- src/common/ts/isChannelWhitelisted.ts | 5 ++--- src/common/ts/wasChannelSubscriber.ts | 8 +++----- src/page/getFetch.ts | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/common/ts/isChannelWhitelisted.ts b/src/common/ts/isChannelWhitelisted.ts index 1f8b4262..88364f07 100644 --- a/src/common/ts/isChannelWhitelisted.ts +++ b/src/common/ts/isChannelWhitelisted.ts @@ -4,8 +4,7 @@ export default function isChannelWhitelisted( channelName: string | null ): boolean { if (!channelName) return false; - const whitelistedChannelsLower = store.state.whitelistedChannels.map( - channel => channel.toLowerCase() + return store.state.whitelistedChannels.some( + c => c.toLowerCase() === channelName.toLowerCase() ); - return whitelistedChannelsLower.includes(channelName.toLowerCase()); } diff --git a/src/common/ts/wasChannelSubscriber.ts b/src/common/ts/wasChannelSubscriber.ts index 0a372439..be45e79b 100644 --- a/src/common/ts/wasChannelSubscriber.ts +++ b/src/common/ts/wasChannelSubscriber.ts @@ -4,9 +4,7 @@ export default function wasChannelSubscriber( channelName: string | null ): boolean { if (!channelName) return false; - const activeChannelSubscriptionsLower = - store.state.activeChannelSubscriptions.map(channel => - channel.toLowerCase() - ); - return activeChannelSubscriptionsLower.includes(channelName.toLowerCase()); + return store.state.activeChannelSubscriptions.some( + c => c.toLowerCase() === channelName.toLowerCase() + ); } diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index b65dca19..dc2e42da 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -651,11 +651,11 @@ function isChannelWhitelisted( pageState: PageState ): boolean { if (!channelName) return false; - const whitelistedChannelsLower = - pageState.state?.whitelistedChannels.map(channel => - channel.toLowerCase() - ) ?? []; - return whitelistedChannelsLower.includes(channelName.toLowerCase()); + return ( + pageState.state?.whitelistedChannels.some( + c => c.toLowerCase() === channelName.toLowerCase() + ) ?? false + ); } function wasChannelSubscriber( @@ -663,11 +663,11 @@ function wasChannelSubscriber( pageState: PageState ): boolean { if (!channelName) return false; - const activeChannelSubscriptionsLower = - pageState.state?.activeChannelSubscriptions.map(channel => - channel.toLowerCase() - ) ?? []; - return activeChannelSubscriptionsLower.includes(channelName.toLowerCase()); + return ( + pageState.state?.activeChannelSubscriptions.some( + c => c.toLowerCase() === channelName.toLowerCase() + ) ?? false + ); } async function flagRequest( From e96e509bc77038ac22794ae479ce0fae7b4f0c5d Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:30:07 +0100 Subject: [PATCH 06/28] Clean up auto whitelist option code --- src/content/content.ts | 54 ++++++++++++++++++----------------------- src/page/getFetch.ts | 19 ++++++--------- src/page/sendMessage.ts | 13 +++++++--- src/types.ts | 4 +-- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/content/content.ts b/src/content/content.ts index 120bc2aa..78d1b040 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -5,7 +5,6 @@ import findChannelFromTwitchTvUrl from "../common/ts/findChannelFromTwitchTvUrl" import isChannelWhitelisted from "../common/ts/isChannelWhitelisted"; import isChromium from "../common/ts/isChromium"; import { getStreamStatus, setStreamStatus } from "../common/ts/streamStatus"; -import wasChannelSubscriber from "../common/ts/wasChannelSubscriber"; import store from "../store"; import type { State } from "../store/types"; import { MessageType } from "../types"; @@ -100,12 +99,12 @@ function onBackgroundMessage(message: any): undefined { } function onPageMessage(event: MessageEvent) { - if (event.data?.type !== MessageType.ContentScriptMessage) return; + if (!event.data) return; + if (event.data.type !== MessageType.ContentScriptMessage) return; - const message = event.data?.message; + const { message, responseType, responseMessageType } = event.data; if (!message) return; - // GetStoreState if (message.type === MessageType.GetStoreState) { const sendStoreState = () => { window.postMessage({ @@ -119,7 +118,7 @@ function onPageMessage(event: MessageEvent) { if (store.readyState === "complete") sendStoreState(); else store.addEventListener("load", sendStoreState); } - // EnableFullMode + // --- else if (message.type === MessageType.EnableFullMode) { try { browser.runtime.sendMessage(message); @@ -130,7 +129,7 @@ function onPageMessage(event: MessageEvent) { ); } } - // DisableFullMode + // --- else if (message.type === MessageType.DisableFullMode) { try { browser.runtime.sendMessage(message); @@ -141,19 +140,16 @@ function onPageMessage(event: MessageEvent) { ); } } - // ChannelSubscriptionStatus - else if (message.type === MessageType.ChannelSubscriptionStatus) { - const { channelName, isSubscribed, scope } = message; - const wasSubscribed = wasChannelSubscriber(channelName); - let isWhitelisted = isChannelWhitelisted(channelName); - console.log( - "[TTV LOL PRO] Received channel subscription status message. Current state:", - { - wasSubscribed, - isSubscribed, - isWhitelisted, - } - ); + // --- + else if (message.type === MessageType.ChannelSubStatusChange) { + const { channelName, wasSubscribed, isSubscribed } = message; + const isWhitelisted = isChannelWhitelisted(channelName); + console.log("[TTV LOL PRO] ChannelSubStatusChange", { + channelName, + wasSubscribed, + isSubscribed, + isWhitelisted, + }); if (store.state.whitelistChannelSubscriptions && channelName != null) { if (!wasSubscribed && isSubscribed) { store.state.activeChannelSubscriptions.push(channelName); @@ -161,7 +157,6 @@ function onPageMessage(event: MessageEvent) { if (!isWhitelisted) { console.log(`[TTV LOL PRO] Adding '${channelName}' to whitelist.`); store.state.whitelistedChannels.push(channelName); - isWhitelisted = true; } } else if (wasSubscribed && !isSubscribed) { store.state.activeChannelSubscriptions = @@ -177,23 +172,20 @@ function onPageMessage(event: MessageEvent) { store.state.whitelistedChannels.filter( c => c.toLowerCase() !== channelName.toLowerCase() ); - isWhitelisted = false; } } } - console.log("[TTV LOL PRO] Sending channel subscription status response."); window.postMessage({ - type: - scope === "page" // TODO: Is this necessary? Isn't the scope always "worker"? - ? MessageType.PageScriptMessage - : MessageType.WorkerScriptMessage, + type: responseType, message: { - type: MessageType.ChannelSubscriptionStatusResponse, - isWhitelisted: isWhitelisted, + type: responseMessageType, + whitelistedChannels: JSON.parse( + JSON.stringify(store.state.whitelistedChannels) + ), }, }); } - // UsherResponse + // --- else if (message.type === MessageType.UsherResponse) { try { browser.runtime.sendMessage(message); @@ -204,7 +196,7 @@ function onPageMessage(event: MessageEvent) { ); } } - // MultipleAdBlockersInUse + // --- else if (message.type === MessageType.MultipleAdBlockersInUse) { const channelName = findChannelFromTwitchTvUrl(location.href); if (!channelName) return; @@ -214,7 +206,7 @@ function onPageMessage(event: MessageEvent) { reason: "Another Twitch ad blocker is in use", }); } - // ClearStats + // --- else if (message.type === MessageType.ClearStats) { clearStats(message.channelName); } diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index dc2e42da..976dedfe 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -265,7 +265,6 @@ export function getFetch(pageState: PageState): typeof fetch { encodeURIComponent('"player_type":"frontpage"') ); const channelName = findChannelFromUsherUrl(url); - let isWhitelisted = isChannelWhitelisted(channelName, pageState); if ( pageState.state?.whitelistChannelSubscriptions && channelName != null @@ -274,33 +273,29 @@ export function getFetch(pageState: PageState): typeof fetch { const isSubscribed = url.includes( encodeURIComponent('"subscriber":true') ); - // const isSubscribed = url.includes( - // encodeURIComponent("aminematue") - // ); const hasSubStatusChanged = (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); if (hasSubStatusChanged) { - console.log( - "[TTV LOL PRO] Channel subscription status changed. Sending message…" - ); try { const response = await pageState.sendMessageToContentScriptAndWaitForResponse( pageState.scope, { - type: MessageType.ChannelSubscriptionStatus, - scope: pageState.scope, + type: MessageType.ChannelSubStatusChange, channelName, + wasSubscribed, isSubscribed, }, - MessageType.ChannelSubscriptionStatusResponse + MessageType.ChannelSubStatusChangeResponse ); - if (typeof response.isWhitelisted === "boolean") { - isWhitelisted = response.isWhitelisted; + if (typeof response.whitelistedChannels === "object") { + pageState.state.whitelistedChannels = + response.whitelistedChannels; } } catch {} } } + const isWhitelisted = isChannelWhitelisted(channelName, pageState); if (!isLivestream || isFrontpage || isWhitelisted) { console.log( "[TTV LOL PRO] Not flagging Usher request: not a livestream, is frontpage, or is whitelisted." diff --git a/src/page/sendMessage.ts b/src/page/sendMessage.ts index 91b1f988..0865cb1b 100644 --- a/src/page/sendMessage.ts +++ b/src/page/sendMessage.ts @@ -13,7 +13,9 @@ function sendMessage( type: MessageType, message: any ): void { - if (!recipient) return; + if (!recipient) { + return console.warn("[TTV LOL PRO] Message recipient is undefined."); + } recipient.postMessage({ type, message, @@ -30,7 +32,7 @@ async function sendMessageAndWaitForResponse( ): Promise { return new Promise((resolve, reject) => { if (!recipient) { - console.warn("[TTV LOL PRO] Recipient is undefined."); + console.warn("[TTV LOL PRO] Message recipient is undefined."); resolve(undefined); return; } @@ -46,7 +48,12 @@ async function sendMessageAndWaitForResponse( }; self.addEventListener("message", listener); - sendMessage(recipient, type, message); + recipient.postMessage({ + type, + message, + responseType, + responseMessageType, + }); setTimeout(() => { self.removeEventListener("message", listener); reject(new Error("Timed out waiting for message response.")); diff --git a/src/types.ts b/src/types.ts index aea52675..2d924e80 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,8 +79,8 @@ export const enum MessageType { EnableFullMode = "TLP_EnableFullMode", EnableFullModeResponse = "TLP_EnableFullModeResponse", DisableFullMode = "TLP_DisableFullMode", - ChannelSubscriptionStatus = "TLP_ChannelSubscriptionStatus", - ChannelSubscriptionStatusResponse = "TLP_ChannelSubscriptionStatusResponse", + ChannelSubStatusChange = "TLP_ChannelSubStatusChange", + ChannelSubStatusChangeResponse = "TLP_ChannelSubStatusChangeResponse", UsherResponse = "TLP_UsherResponse", NewPlaybackAccessToken = "TLP_NewPlaybackAccessToken", NewPlaybackAccessTokenResponse = "TLP_NewPlaybackAccessTokenResponse", From 09750b6b1f8554896e2299213c9550a3f3a1b6f8 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:13:21 +0100 Subject: [PATCH 07/28] Fix some errors, improve code for message handlers --- src/content/content.ts | 6 +++--- src/options/options.ts | 8 ++++++-- src/page/getFetch.ts | 13 ++++++++----- src/page/page.ts | 4 ++-- src/page/sendMessage.ts | 8 ++++---- src/page/worker.ts | 6 ++++-- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/content/content.ts b/src/content/content.ts index 78d1b040..9445e204 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -65,7 +65,6 @@ function onStoreChange(changes: Record) { // This is mainly to reduce the amount of messages sent to the page script. // (Also to reduce the number of console logs.) const ignoredKeys: (keyof State)[] = [ - "activeChannelSubscriptions", "adLog", "dnsResponses", "openedTwitchTabs", @@ -99,8 +98,9 @@ function onBackgroundMessage(message: any): undefined { } function onPageMessage(event: MessageEvent) { - if (!event.data) return; - if (event.data.type !== MessageType.ContentScriptMessage) return; + if (!event.data || event.data.type !== MessageType.ContentScriptMessage) { + return; + } const { message, responseType, responseMessageType } = event.data; if (!message) return; diff --git a/src/options/options.ts b/src/options/options.ts index 97c0c099..bd18c9e6 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -169,8 +169,12 @@ function main() { whitelistSubscriptionsCheckboxElement.checked = store.state.whitelistChannelSubscriptions; whitelistSubscriptionsCheckboxElement.addEventListener("change", () => { - store.state.whitelistChannelSubscriptions = - whitelistSubscriptionsCheckboxElement.checked; + const { checked } = whitelistSubscriptionsCheckboxElement; + store.state.whitelistChannelSubscriptions = checked; + if (!checked) { + // Clear active channel subscriptions to free up storage space. + store.state.activeChannelSubscriptions = []; + } }); // Proxies if (store.state.optimizedProxiesEnabled) diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 976dedfe..72a32cf1 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -28,9 +28,11 @@ export function getFetch(pageState: PageState): typeof fetch { // Listen for NewPlaybackAccessToken messages from the worker script. if (pageState.scope === "page") { self.addEventListener("message", async event => { - if (event.data?.type !== MessageType.PageScriptMessage) return; + if (!event.data || event.data.type !== MessageType.PageScriptMessage) { + return; + } - const message = event.data?.message; + const { message } = event.data; if (!message) return; switch (message.type) { @@ -58,13 +60,14 @@ export function getFetch(pageState: PageState): typeof fetch { // Listen for ClearStats messages from the page script. self.addEventListener("message", event => { if ( - event.data?.type !== MessageType.PageScriptMessage && - event.data?.type !== MessageType.WorkerScriptMessage + !event.data || + (event.data.type !== MessageType.PageScriptMessage && + event.data.type !== MessageType.WorkerScriptMessage) ) { return; } - const message = event.data?.message; + const { message } = event.data; if (!message) return; switch (message.type) { diff --git a/src/page/page.ts b/src/page/page.ts index 60f7e337..b7619ace 100644 --- a/src/page/page.ts +++ b/src/page/page.ts @@ -130,9 +130,9 @@ window.addEventListener("message", event => { return; } - if (event.data?.type !== MessageType.PageScriptMessage) return; + if (!event.data || event.data.type !== MessageType.PageScriptMessage) return; - const message = event.data?.message; + const { message } = event.data; if (!message) return; switch (message.type) { diff --git a/src/page/sendMessage.ts b/src/page/sendMessage.ts index 0865cb1b..b25b33b4 100644 --- a/src/page/sendMessage.ts +++ b/src/page/sendMessage.ts @@ -14,7 +14,7 @@ function sendMessage( message: any ): void { if (!recipient) { - return console.warn("[TTV LOL PRO] Message recipient is undefined."); + return console.error("[TTV LOL PRO] Message recipient is undefined."); } recipient.postMessage({ type, @@ -32,14 +32,14 @@ async function sendMessageAndWaitForResponse( ): Promise { return new Promise((resolve, reject) => { if (!recipient) { - console.warn("[TTV LOL PRO] Message recipient is undefined."); + console.error("[TTV LOL PRO] Message recipient is undefined."); resolve(undefined); return; } const listener = (event: MessageEvent) => { - if (event.data?.type !== responseType) return; - const message = event.data?.message; + if (!event.data || event.data.type !== responseType) return; + const { message } = event.data; if (!message) return; if (message.type === responseMessageType) { self.removeEventListener("message", listener); diff --git a/src/page/worker.ts b/src/page/worker.ts index eed7ec96..57fb2bf2 100644 --- a/src/page/worker.ts +++ b/src/page/worker.ts @@ -47,9 +47,11 @@ const pageState: PageState = { self.fetch = getFetch(pageState); self.addEventListener("message", event => { - if (event.data?.type !== MessageType.WorkerScriptMessage) return; + if (!event.data || event.data.type !== MessageType.WorkerScriptMessage) { + return; + } - const message = event.data?.message; + const { message } = event.data; if (!message) return; switch (message.type) { From 4ef7449b42abaf10cc68b81459531244dde2390d Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:23:58 +0100 Subject: [PATCH 08/28] Upgrade dependencies --- package-lock.json | 2248 +++++++++++++++++++-------------------------- package.json | 15 +- 2 files changed, 943 insertions(+), 1320 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c85a193..0f320c5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,35 +10,35 @@ "license": "GPL-3.0", "dependencies": { "bowser": "^2.11.0", - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "m3u8-parser": "^7.2.0" }, "devDependencies": { - "@parcel/config-webextension": "^2.12.0", - "@types/chrome": "^0.0.271", - "@types/jsbn": "^1.2.33", - "@types/node": "^20.16.5", + "@parcel/config-webextension": "^2.13.3", + "@types/chrome": "^0.0.300", + "@types/node": "^22.13.0", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "os-browserify": "^0.3.0", - "parcel": "^2.12.0", - "postcss": "^8.4.47", + "parcel": "^2.13.3", + "postcss": "^8.5.1", "prettier": "2.8.8", "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", "shx": "^0.3.4", - "typescript": "^5.6.2", + "typescript": "^5.7.3", "webextension-polyfill": "^0.12.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -46,103 +46,19 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -151,16 +67,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, "node_modules/@lezer/common": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", - "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", + "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", "dev": true, "license": "MIT" }, @@ -358,22 +268,22 @@ ] }, "node_modules/@parcel/bundler-default": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz", - "integrity": "sha512-3ybN74oYNMKyjD6V20c9Gerdbh7teeNvVMwIoHIQMzuIFT6IGX53PyOLlOKRLbjxMc0TMimQQxIt2eQqxR5LsA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.13.3.tgz", + "integrity": "sha512-mOuWeth0bZzRv1b9Lrvydis/hAzJyePy0gwa0tix3/zyYBvw0JY+xkXVR4qKyD/blc1Ra2qOlfI2uD3ucnsdXA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/graph": "3.2.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/graph": "3.3.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -381,39 +291,39 @@ } }, "node_modules/@parcel/cache": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.12.0.tgz", - "integrity": "sha512-FX5ZpTEkxvq/yvWklRHDESVRz+c7sLTXgFuzz6uEnBcXV38j6dMSikflNpHA6q/L4GKkCqRywm9R6XQwhwIMyw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.13.3.tgz", + "integrity": "sha512-Vz5+K5uCt9mcuQAMDo0JdbPYDmVdB8Nvu/A2vTEK2rqZPxvoOTczKeMBA4JqzKqGURHPRLaJCvuR8nDG+jhK9A==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/fs": "2.12.0", - "@parcel/logger": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/fs": "2.13.3", + "@parcel/logger": "2.13.3", + "@parcel/utils": "2.13.3", "lmdb": "2.8.5" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/codeframe": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.12.0.tgz", - "integrity": "sha512-v2VmneILFiHZJTxPiR7GEF1wey1/IXPdZMcUlNXBiPZyWDfcuNgGGVQkx/xW561rULLIvDPharOMdxz5oHOKQg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.13.3.tgz", + "integrity": "sha512-L/PQf+PT0xM8k9nc0B+PxxOYO2phQYnbuifu9o4pFRiqVmCtHztP+XMIvRJ2gOEXy3pgAImSPFVJ3xGxMFky4g==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0" + "chalk": "^4.1.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -421,17 +331,17 @@ } }, "node_modules/@parcel/compressor-raw": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.12.0.tgz", - "integrity": "sha512-h41Q3X7ZAQ9wbQ2csP8QGrwepasLZdXiuEdpUryDce6rF9ZiHoJ97MRpdLxOhOPyASTw/xDgE1xyaPQr0Q3f5A==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.13.3.tgz", + "integrity": "sha512-C6vjDlgTLjYc358i7LA/dqcL0XDQZ1IHXFw6hBaHHOfxPKW2T4bzUI6RURyToEK9Q1X7+ggDKqgdLxwp4veCFg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0" + "@parcel/plugin": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -439,108 +349,108 @@ } }, "node_modules/@parcel/config-default": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.12.0.tgz", - "integrity": "sha512-dPNe2n9eEsKRc1soWIY0yToMUPirPIa2QhxcCB3Z5RjpDGIXm0pds+BaiqY6uGLEEzsjhRO0ujd4v2Rmm0vuFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@parcel/bundler-default": "2.12.0", - "@parcel/compressor-raw": "2.12.0", - "@parcel/namer-default": "2.12.0", - "@parcel/optimizer-css": "2.12.0", - "@parcel/optimizer-htmlnano": "2.12.0", - "@parcel/optimizer-image": "2.12.0", - "@parcel/optimizer-svgo": "2.12.0", - "@parcel/optimizer-swc": "2.12.0", - "@parcel/packager-css": "2.12.0", - "@parcel/packager-html": "2.12.0", - "@parcel/packager-js": "2.12.0", - "@parcel/packager-raw": "2.12.0", - "@parcel/packager-svg": "2.12.0", - "@parcel/packager-wasm": "2.12.0", - "@parcel/reporter-dev-server": "2.12.0", - "@parcel/resolver-default": "2.12.0", - "@parcel/runtime-browser-hmr": "2.12.0", - "@parcel/runtime-js": "2.12.0", - "@parcel/runtime-react-refresh": "2.12.0", - "@parcel/runtime-service-worker": "2.12.0", - "@parcel/transformer-babel": "2.12.0", - "@parcel/transformer-css": "2.12.0", - "@parcel/transformer-html": "2.12.0", - "@parcel/transformer-image": "2.12.0", - "@parcel/transformer-js": "2.12.0", - "@parcel/transformer-json": "2.12.0", - "@parcel/transformer-postcss": "2.12.0", - "@parcel/transformer-posthtml": "2.12.0", - "@parcel/transformer-raw": "2.12.0", - "@parcel/transformer-react-refresh-wrap": "2.12.0", - "@parcel/transformer-svg": "2.12.0" + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.13.3.tgz", + "integrity": "sha512-WUsx83ic8DgLwwnL1Bua4lRgQqYjxiTT+DBxESGk1paNm1juWzyfPXEQDLXwiCTcWMQGiXQFQ8OuSISauVQ8dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@parcel/bundler-default": "2.13.3", + "@parcel/compressor-raw": "2.13.3", + "@parcel/namer-default": "2.13.3", + "@parcel/optimizer-css": "2.13.3", + "@parcel/optimizer-htmlnano": "2.13.3", + "@parcel/optimizer-image": "2.13.3", + "@parcel/optimizer-svgo": "2.13.3", + "@parcel/optimizer-swc": "2.13.3", + "@parcel/packager-css": "2.13.3", + "@parcel/packager-html": "2.13.3", + "@parcel/packager-js": "2.13.3", + "@parcel/packager-raw": "2.13.3", + "@parcel/packager-svg": "2.13.3", + "@parcel/packager-wasm": "2.13.3", + "@parcel/reporter-dev-server": "2.13.3", + "@parcel/resolver-default": "2.13.3", + "@parcel/runtime-browser-hmr": "2.13.3", + "@parcel/runtime-js": "2.13.3", + "@parcel/runtime-react-refresh": "2.13.3", + "@parcel/runtime-service-worker": "2.13.3", + "@parcel/transformer-babel": "2.13.3", + "@parcel/transformer-css": "2.13.3", + "@parcel/transformer-html": "2.13.3", + "@parcel/transformer-image": "2.13.3", + "@parcel/transformer-js": "2.13.3", + "@parcel/transformer-json": "2.13.3", + "@parcel/transformer-postcss": "2.13.3", + "@parcel/transformer-posthtml": "2.13.3", + "@parcel/transformer-raw": "2.13.3", + "@parcel/transformer-react-refresh-wrap": "2.13.3", + "@parcel/transformer-svg": "2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/config-webextension": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/config-webextension/-/config-webextension-2.12.0.tgz", - "integrity": "sha512-BcRrRzSJjGKMxL7L59gkU0JQPN1pmfQms9+pNaqi8d42WqrBOQrVeU7cs62zWG1UZUv7o+uCgPGgOxPggtYnkQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/config-webextension/-/config-webextension-2.13.3.tgz", + "integrity": "sha512-NxnLq3Lk2btiD7YTgsDd47w1XEhMWFxH73GhTTc5ES09McbPCz8E9wm5VHBoLSq4eH/EAnEZ8ni0bKSKHAin4A==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/config-default": "2.12.0", - "@parcel/packager-webextension": "2.12.0", - "@parcel/runtime-webextension": "2.12.0", - "@parcel/transformer-raw": "2.12.0", - "@parcel/transformer-webextension": "2.12.0" + "@parcel/config-default": "2.13.3", + "@parcel/packager-webextension": "2.13.3", + "@parcel/runtime-webextension": "2.13.3", + "@parcel/transformer-raw": "2.13.3", + "@parcel/transformer-webextension": "2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/core": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz", - "integrity": "sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.13.3.tgz", + "integrity": "sha512-SRZFtqGiaKHlZ2YAvf+NHvBFWS3GnkBvJMfOJM7kxJRK3M1bhbwJa/GgSdzqro5UVf9Bfj6E+pkdrRQIOZ7jMQ==", "dev": true, "license": "MIT", "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/cache": "2.12.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/events": "2.12.0", - "@parcel/fs": "2.12.0", - "@parcel/graph": "3.2.0", - "@parcel/logger": "2.12.0", - "@parcel/package-manager": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/profiler": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/cache": "2.13.3", + "@parcel/diagnostic": "2.13.3", + "@parcel/events": "2.13.3", + "@parcel/feature-flags": "2.13.3", + "@parcel/fs": "2.13.3", + "@parcel/graph": "3.3.3", + "@parcel/logger": "2.13.3", + "@parcel/package-manager": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/profiler": "2.13.3", + "@parcel/rust": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", - "@parcel/workers": "2.12.0", - "abortcontroller-polyfill": "^1.1.9", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", + "@parcel/workers": "2.13.3", "base-x": "^3.0.8", "browserslist": "^4.6.6", "clone": "^2.1.1", - "dotenv": "^7.0.0", - "dotenv-expand": "^5.1.0", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", "json5": "^2.2.0", "msgpackr": "^1.9.9", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -548,9 +458,9 @@ } }, "node_modules/@parcel/diagnostic": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.12.0.tgz", - "integrity": "sha512-8f1NOsSFK+F4AwFCKynyIu9Kr/uWHC+SywAv4oS6Bv3Acig0gtwUjugk0C9UaB8ztBZiW5TQZhw+uPZn9T/lJA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.13.3.tgz", + "integrity": "sha512-C70KXLBaXLJvr7XCEVu8m6TqNdw1gQLxqg5BQ8roR62R4vWWDnOq8PEksxDi4Y8Z/FF4i3Sapv6tRx9iBNxDEg==", "dev": true, "license": "MIT", "dependencies": { @@ -558,7 +468,7 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -566,13 +476,27 @@ } }, "node_modules/@parcel/events": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.12.0.tgz", - "integrity": "sha512-nmAAEIKLjW1kB2cUbCYSmZOGbnGj8wCzhqnK727zCCWaA25ogzAtt657GPOeFyqW77KyosU728Tl63Fc8hphIA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.13.3.tgz", + "integrity": "sha512-ZkSHTTbD/E+53AjUzhAWTnMLnxLEU5yRw0H614CaruGh+GjgOIKyukGeToF5Gf/lvZ159VrJCGE0Z5EpgHVkuQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/feature-flags": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/feature-flags/-/feature-flags-2.13.3.tgz", + "integrity": "sha512-UZm14QpamDFoUut9YtCZSpG1HxPs07lUwUCpsAYL0PpxASD3oWJQxIJGfDZPa2272DarXDG9adTKrNXvkHZblw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -580,40 +504,42 @@ } }, "node_modules/@parcel/fs": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.12.0.tgz", - "integrity": "sha512-NnFkuvou1YBtPOhTdZr44WN7I60cGyly2wpHzqRl62yhObyi1KvW0SjwOMa0QGNcBOIzp4G0CapoZ93hD0RG5Q==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.13.3.tgz", + "integrity": "sha512-+MPWAt0zr+TCDSlj1LvkORTjfB/BSffsE99A9AvScKytDSYYpY2s0t4vtV9unSh0FHMS2aBCZNJ4t7KL+DcPIg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/rust": "2.12.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/feature-flags": "2.13.3", + "@parcel/rust": "2.13.3", + "@parcel/types-internal": "2.13.3", + "@parcel/utils": "2.13.3", "@parcel/watcher": "^2.0.7", - "@parcel/workers": "2.12.0" + "@parcel/workers": "2.13.3" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/graph": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-3.2.0.tgz", - "integrity": "sha512-xlrmCPqy58D4Fg5umV7bpwDx5Vyt7MlnQPxW68vae5+BA4GSWetfZt+Cs5dtotMG2oCHzZxhIPt7YZ7NRyQzLA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-3.3.3.tgz", + "integrity": "sha512-pxs4GauEdvCN8nRd6wG3st6LvpHske3GfqGwUSR0P0X0pBPI1/NicvXz6xzp3rgb9gPWfbKXeI/2IOTfIxxVfg==", "dev": true, "license": "MIT", "dependencies": { + "@parcel/feature-flags": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -621,17 +547,17 @@ } }, "node_modules/@parcel/logger": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.12.0.tgz", - "integrity": "sha512-cJ7Paqa7/9VJ7C+KwgJlwMqTQBOjjn71FbKk0G07hydUEBISU2aDfmc/52o60ErL9l+vXB26zTrIBanbxS8rVg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.13.3.tgz", + "integrity": "sha512-8YF/ZhsQgd7ohQ2vEqcMD1Ag9JlJULROWRPGgGYLGD+twuxAiSdiFBpN3f+j4gQN4PYaLaIS/SwUFx11J243fQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/events": "2.12.0" + "@parcel/diagnostic": "2.13.3", + "@parcel/events": "2.13.3" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -639,16 +565,16 @@ } }, "node_modules/@parcel/markdown-ansi": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.12.0.tgz", - "integrity": "sha512-WZz3rzL8k0H3WR4qTHX6Ic8DlEs17keO9gtD4MNGyMNQbqQEvQ61lWJaIH0nAtgEetu0SOITiVqdZrb8zx/M7w==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.13.3.tgz", + "integrity": "sha512-B4rUdlNUulJs2xOQuDbN7Hq5a9roq8IZUcJ1vQ8PAv+zMGb7KCfqIIr/BSCDYGhayfAGBVWW8x55Kvrl1zrDYw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0" + "chalk": "^4.1.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -656,19 +582,19 @@ } }, "node_modules/@parcel/namer-default": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.12.0.tgz", - "integrity": "sha512-9DNKPDHWgMnMtqqZIMiEj/R9PNWW16lpnlHjwK3ciRlMPgjPJ8+UNc255teZODhX0T17GOzPdGbU/O/xbxVPzA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.13.3.tgz", + "integrity": "sha512-A2a5A5fuyNcjSGOS0hPcdQmOE2kszZnLIXof7UMGNkNkeC62KAG8WcFZH5RNOY3LT5H773hq51zmc2Y2gE5Rnw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -676,22 +602,22 @@ } }, "node_modules/@parcel/node-resolver-core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.3.0.tgz", - "integrity": "sha512-rhPW9DYPEIqQBSlYzz3S0AjXxjN6Ub2yS6tzzsW/4S3Gpsgk/uEq4ZfxPvoPf/6TgZndVxmKwpmxaKtGMmf3cA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-3.4.3.tgz", + "integrity": "sha512-IEnMks49egEic1ITBp59VQyHzkSQUXqpU9hOHwqN3KoSTdZ6rEgrXcS3pa6tdXay4NYGlcZ88kFCE8i/xYoVCg==", "dev": true, "license": "MIT", "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/fs": "2.12.0", - "@parcel/rust": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/fs": "2.13.3", + "@parcel/rust": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -699,23 +625,23 @@ } }, "node_modules/@parcel/optimizer-css": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.12.0.tgz", - "integrity": "sha512-ifbcC97fRzpruTjaa8axIFeX4MjjSIlQfem3EJug3L2AVqQUXnM1XO8L0NaXGNLTW2qnh1ZjIJ7vXT/QhsphsA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.13.3.tgz", + "integrity": "sha512-A8o9IVCv919vhv69SkLmyW2WjJR5WZgcMqV6L1uiGF8i8z18myrMhrp2JuSHx29PRT9uNyzNC4Xrd4StYjIhJg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", + "@parcel/utils": "2.13.3", "browserslist": "^4.6.6", "lightningcss": "^1.22.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -723,236 +649,90 @@ } }, "node_modules/@parcel/optimizer-htmlnano": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.12.0.tgz", - "integrity": "sha512-MfPMeCrT8FYiOrpFHVR+NcZQlXAptK2r4nGJjfT+ndPBhEEZp4yyL7n1y7HfX9geg5altc4WTb4Gug7rCoW8VQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.13.3.tgz", + "integrity": "sha512-K4Uvg0Sy2pECP7pdvvbud++F0pfcbNkq+IxTrgqBX5HJnLEmRZwgdvZEKF43oMEolclMnURMQRGjRplRaPdbXg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "htmlnano": "^2.0.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "svgo": "^2.4.0" + "posthtml": "^0.16.5" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/optimizer-htmlnano/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/@parcel/optimizer-htmlnano/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@parcel/optimizer-htmlnano/node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@parcel/optimizer-htmlnano/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/@parcel/optimizer-htmlnano/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@parcel/optimizer-image": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.12.0.tgz", - "integrity": "sha512-bo1O7raeAIbRU5nmNVtx8divLW9Xqn0c57GVNGeAK4mygnQoqHqRZ0mR9uboh64pxv6ijXZHPhKvU9HEpjPjBQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.13.3.tgz", + "integrity": "sha512-wlDUICA29J4UnqkKrWiyt68g1e85qfYhp4zJFcFJL0LX1qqh1QwsLUz3YJ+KlruoqPxJSFEC8ncBEKiVCsqhEQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", - "@parcel/utils": "2.12.0", - "@parcel/workers": "2.12.0" + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", + "@parcel/utils": "2.13.3", + "@parcel/workers": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/optimizer-svgo": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.12.0.tgz", - "integrity": "sha512-Kyli+ZZXnoonnbeRQdoWwee9Bk2jm/49xvnfb+2OO8NN0d41lblBoRhOyFiScRnJrw7eVl1Xrz7NTkXCIO7XFQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.13.3.tgz", + "integrity": "sha512-piIKxQKzhZK54dJR6yqIcq+urZmpsfgUpLCZT3cnWlX4ux5+S2iN66qqZBs0zVn+a58LcWcoP4Z9ieiJmpiu2w==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", - "svgo": "^2.4.0" + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/optimizer-svgo/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/@parcel/optimizer-svgo/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@parcel/optimizer-svgo/node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@parcel/optimizer-svgo/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/@parcel/optimizer-svgo/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@parcel/optimizer-swc": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.12.0.tgz", - "integrity": "sha512-iBi6LZB3lm6WmbXfzi8J3DCVPmn4FN2lw7DGXxUXu7MouDPVWfTsM6U/5TkSHJRNRogZ2gqy5q9g34NPxHbJcw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-swc/-/optimizer-swc-2.13.3.tgz", + "integrity": "sha512-zNSq6oWqLlW8ksPIDjM0VgrK6ZAJbPQCDvs1V+p0oX3CzEe85lT5VkRpnfrN1+/vvEJNGL8e60efHKpI+rXGTA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", - "@swc/core": "^1.3.36", + "@parcel/utils": "2.13.3", + "@swc/core": "^1.7.26", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -960,50 +740,50 @@ } }, "node_modules/@parcel/package-manager": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.12.0.tgz", - "integrity": "sha512-0nvAezcjPx9FT+hIL+LS1jb0aohwLZXct7jAh7i0MLMtehOi0z1Sau+QpgMlA9rfEZZ1LIeFdnZZwqSy7Ccspw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.13.3.tgz", + "integrity": "sha512-FLNI5OrZxymGf/Yln0E/kjnGn5sdkQAxW7pQVdtuM+5VeN75yibJRjsSGv88PvJ+KvpD2ANgiIJo1RufmoPcww==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/fs": "2.12.0", - "@parcel/logger": "2.12.0", - "@parcel/node-resolver-core": "3.3.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", - "@parcel/workers": "2.12.0", - "@swc/core": "^1.3.36", + "@parcel/diagnostic": "2.13.3", + "@parcel/fs": "2.13.3", + "@parcel/logger": "2.13.3", + "@parcel/node-resolver-core": "3.4.3", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", + "@parcel/workers": "2.13.3", + "@swc/core": "^1.7.26", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/packager-css": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.12.0.tgz", - "integrity": "sha512-j3a/ODciaNKD19IYdWJT+TP+tnhhn5koBGBWWtrKSu0UxWpnezIGZetit3eE+Y9+NTePalMkvpIlit2eDhvfJA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.13.3.tgz", + "integrity": "sha512-ghDqRMtrUwaDERzFm9le0uz2PTeqqsjsW0ihQSZPSAptElRl9o5BR+XtMPv3r7Ui0evo+w35gD55oQCJ28vCig==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", + "@parcel/utils": "2.13.3", "lightningcss": "^1.22.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1011,21 +791,21 @@ } }, "node_modules/@parcel/packager-html": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.12.0.tgz", - "integrity": "sha512-PpvGB9hFFe+19NXGz2ApvPrkA9GwEqaDAninT+3pJD57OVBaxB8U+HN4a5LICKxjUppPPqmrLb6YPbD65IX4RA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.13.3.tgz", + "integrity": "sha512-jDLnKSA/EzVEZ3/aegXO3QJ/Ij732AgBBkIQfeC8tUoxwVz5b3HiPBAjVjcUSfZs7mdBSHO+ELWC3UD+HbsIrQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1", "posthtml": "^0.16.5" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1033,24 +813,24 @@ } }, "node_modules/@parcel/packager-js": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.12.0.tgz", - "integrity": "sha512-viMF+FszITRRr8+2iJyk+4ruGiL27Y6AF7hQ3xbJfzqnmbOhGFtLTQwuwhOLqN/mWR2VKdgbLpZSarWaO3yAMg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.13.3.tgz", + "integrity": "sha512-0pMHHf2zOn7EOJe88QJw5h/wcV1bFfj6cXVcE55Wa8GX3V+SdCgolnlvNuBcRQ1Tlx0Xkpo+9hMFVIQbNQY6zw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", "globals": "^13.2.0", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1058,17 +838,17 @@ } }, "node_modules/@parcel/packager-raw": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.12.0.tgz", - "integrity": "sha512-tJZqFbHqP24aq1F+OojFbQIc09P/u8HAW5xfndCrFnXpW4wTgM3p03P0xfw3gnNq+TtxHJ8c3UFE5LnXNNKhYA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.13.3.tgz", + "integrity": "sha512-AWu4UB+akBdskzvT3KGVHIdacU9f7cI678DQQ1jKQuc9yZz5D0VFt3ocFBOmvDfEQDF0uH3jjtJR7fnuvX7Biw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0" + "@parcel/plugin": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1076,20 +856,20 @@ } }, "node_modules/@parcel/packager-svg": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.12.0.tgz", - "integrity": "sha512-ldaGiacGb2lLqcXas97k8JiZRbAnNREmcvoY2W2dvW4loVuDT9B9fU777mbV6zODpcgcHWsLL3lYbJ5Lt3y9cg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.13.3.tgz", + "integrity": "sha512-tKGRiFq/4jh5u2xpTstNQ7gu+RuZWzlWqpw5NaFmcKe6VQe5CMcS499xTFoREAGnRvevSeIgC38X1a+VOo+/AA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", "posthtml": "^0.16.4" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1097,17 +877,17 @@ } }, "node_modules/@parcel/packager-wasm": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz", - "integrity": "sha512-fYqZzIqO9fGYveeImzF8ll6KRo2LrOXfD+2Y5U3BiX/wp9wv17dz50QLDQm9hmTcKGWxK4yWqKQh+Evp/fae7A==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.13.3.tgz", + "integrity": "sha512-SZB56/b230vFrSehVXaUAWjJmWYc89gzb8OTLkBm7uvtFtov2J1R8Ig9TTJwinyXE3h84MCFP/YpQElSfoLkJw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0" + "@parcel/plugin": "2.13.3" }, "engines": { - "node": ">=12.0.0", - "parcel": "^2.12.0" + "node": ">=16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1115,19 +895,19 @@ } }, "node_modules/@parcel/packager-webextension": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/packager-webextension/-/packager-webextension-2.12.0.tgz", - "integrity": "sha512-IcdioNuxh1d5fwG5n7izA6CKQgnrBMjN65E5NznvOgr/RXGjegnmDcEgq7qBsQHRPBP/iJQG+En4AfCxEfPjUA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-webextension/-/packager-webextension-2.13.3.tgz", + "integrity": "sha512-wmC4jbeYNsPO7XSnPFK08qjy47HzRKemt8NJX1uog3vPI4osuo9vrCMDPywNkD8fVj6KNZepa70j6B0iqyLM3g==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=12.0.0", - "parcel": "^2.12.0" + "node": ">=16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1135,16 +915,16 @@ } }, "node_modules/@parcel/plugin": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.12.0.tgz", - "integrity": "sha512-nc/uRA8DiMoe4neBbzV6kDndh/58a4wQuGKw5oEoIwBCHUvE2W8ZFSu7ollSXUGRzfacTt4NdY8TwS73ScWZ+g==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.13.3.tgz", + "integrity": "sha512-cterKHHcwg6q11Gpif/aqvHo056TR+yDVJ3fSdiG2xr5KD1VZ2B3hmofWERNNwjMcnR1h9Xq40B7jCKUhOyNFA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/types": "2.12.0" + "@parcel/types": "2.13.3" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -1152,18 +932,19 @@ } }, "node_modules/@parcel/profiler": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/profiler/-/profiler-2.12.0.tgz", - "integrity": "sha512-q53fvl5LDcFYzMUtSusUBZSjQrKjMlLEBgKeQHFwkimwR1mgoseaDBDuNz0XvmzDzF1UelJ02TUKCGacU8W2qA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/profiler/-/profiler-2.13.3.tgz", + "integrity": "sha512-ok6BwWSLvyHe5TuSXjSacYnDStFgP5Y30tA9mbtWSm0INDsYf+m5DqzpYPx8U54OaywWMK8w3MXUClosJX3aPA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/events": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/events": "2.13.3", + "@parcel/types-internal": "2.13.3", "chrome-trace-event": "^1.0.2" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -1171,21 +952,21 @@ } }, "node_modules/@parcel/reporter-cli": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.12.0.tgz", - "integrity": "sha512-TqKsH4GVOLPSCanZ6tcTPj+rdVHERnt5y4bwTM82cajM21bCX1Ruwp8xOKU+03091oV2pv5ieB18pJyRF7IpIw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.13.3.tgz", + "integrity": "sha512-EA5tKt/6bXYNMEavSs35qHlFdx6cZmRazlZxPBgxPePQYoouNAPMNLUOEQozaPhz9f5fvNDN7EHOFaAWcdO2LA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", - "chalk": "^4.1.0", + "@parcel/plugin": "2.13.3", + "@parcel/types": "2.13.3", + "@parcel/utils": "2.13.3", + "chalk": "^4.1.2", "term-size": "^2.2.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1193,18 +974,18 @@ } }, "node_modules/@parcel/reporter-dev-server": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.12.0.tgz", - "integrity": "sha512-tIcDqRvAPAttRlTV28dHcbWT5K2r/MBFks7nM4nrEDHWtnrCwimkDmZTc1kD8QOCCjGVwRHcQybpHvxfwol6GA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.13.3.tgz", + "integrity": "sha512-ZNeFp6AOIQFv7mZIv2P5O188dnZHNg0ymeDVcakfZomwhpSva2dFNS3AnvWo4eyWBlUxkmQO8BtaxeWTs7jAuA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0" + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1212,20 +993,20 @@ } }, "node_modules/@parcel/reporter-tracer": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.12.0.tgz", - "integrity": "sha512-g8rlu9GxB8Ut/F8WGx4zidIPQ4pcYFjU9bZO+fyRIPrSUFH2bKijCnbZcr4ntqzDGx74hwD6cCG4DBoleq2UlQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-tracer/-/reporter-tracer-2.13.3.tgz", + "integrity": "sha512-aBsVPI8jLZTDkFYrI69GxnsdvZKEYerkPsu935LcX9rfUYssOnmmUP+3oI+8fbg+qNjJuk9BgoQ4hCp9FOphMQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "chrome-trace-event": "^1.0.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1233,18 +1014,18 @@ } }, "node_modules/@parcel/resolver-default": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.12.0.tgz", - "integrity": "sha512-uuhbajTax37TwCxu7V98JtRLiT6hzE4VYSu5B7Qkauy14/WFt2dz6GOUXPgVsED569/hkxebPx3KCMtZW6cHHA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.13.3.tgz", + "integrity": "sha512-urBZuRALWT9pFMeWQ8JirchLmsQEyI9lrJptiwLbJWrwvmlwSUGkcstmPwoNRf/aAQjICB7ser/247Vny0pFxA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/node-resolver-core": "3.3.0", - "@parcel/plugin": "2.12.0" + "@parcel/node-resolver-core": "3.4.3", + "@parcel/plugin": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1252,18 +1033,18 @@ } }, "node_modules/@parcel/runtime-browser-hmr": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.12.0.tgz", - "integrity": "sha512-4ZLp2FWyD32r0GlTulO3+jxgsA3oO1P1b5oO2IWuWilfhcJH5LTiazpL5YdusUjtNn9PGN6QLAWfxmzRIfM+Ow==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.13.3.tgz", + "integrity": "sha512-EAcPojQFUNUGUrDk66cu3ySPO0NXRVS5CKPd4QrxPCVVbGzde4koKu8krC/TaGsoyUqhie8HMnS70qBP0GFfcQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0" + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1271,20 +1052,20 @@ } }, "node_modules/@parcel/runtime-js": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.12.0.tgz", - "integrity": "sha512-sBerP32Z1crX5PfLNGDSXSdqzlllM++GVnVQVeM7DgMKS8JIFG3VLi28YkX+dYYGtPypm01JoIHCkvwiZEcQJg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.13.3.tgz", + "integrity": "sha512-62OucNAnxb2Q0uyTFWW/0Hvv2DJ4b5H6neh/YFu2/wmxaZ37xTpEuEcG2do7KW54xE5DeLP+RliHLwi4NvR3ww==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1292,20 +1073,20 @@ } }, "node_modules/@parcel/runtime-react-refresh": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.12.0.tgz", - "integrity": "sha512-SCHkcczJIDFTFdLTzrHTkQ0aTrX3xH6jrA4UsCBL6ji61+w+ohy4jEEe9qCgJVXhnJfGLE43HNXek+0MStX+Mw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.13.3.tgz", + "integrity": "sha512-PYZ1klpJVwqE3WuifILjtF1dugtesHEuJcXYZI85T6UoRSD5ctS1nAIpZzT14Ga1lRt/jd+eAmhWL1l3m/Vk1Q==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "react-error-overlay": "6.0.9", - "react-refresh": "^0.9.0" + "react-refresh": ">=0.9 <=0.14" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1313,19 +1094,19 @@ } }, "node_modules/@parcel/runtime-service-worker": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.12.0.tgz", - "integrity": "sha512-BXuMBsfiwpIEnssn+jqfC3jkgbS8oxeo3C7xhSQsuSv+AF2FwY3O3AO1c1RBskEW3XrBLNINOJujroNw80VTKA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.13.3.tgz", + "integrity": "sha512-BjMhPuT7Us1+YIo31exPRwomPiL+jrZZS5UUAwlEW2XGHDceEotzRM94LwxeFliCScT4IOokGoxixm19qRuzWg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1333,19 +1114,19 @@ } }, "node_modules/@parcel/runtime-webextension": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/runtime-webextension/-/runtime-webextension-2.12.0.tgz", - "integrity": "sha512-dqHTPv3w8e0sFLCwk/3DH40FWnI72dnfcUSWpbJCwGnhtUQ4/TkpCCEB6OT9crNnOpX+LrWPIOa5Ucd9c2nRjA==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-webextension/-/runtime-webextension-2.13.3.tgz", + "integrity": "sha512-z/iXfMHmfeSkKHdFaGVya/HtGiXMsHAdZmuYqmRiKJAFduVaBYP5DFkFzO/khZovz6U7LU0JPI2XYeZEBk7UKw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1353,13 +1134,13 @@ } }, "node_modules/@parcel/rust": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/rust/-/rust-2.12.0.tgz", - "integrity": "sha512-005cldMdFZFDPOjbDVEXcINQ3wT4vrxvSavRWI3Az0e3E18exO/x/mW9f648KtXugOXMAqCEqhFHcXECL9nmMw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/rust/-/rust-2.13.3.tgz", + "integrity": "sha512-dLq85xDAtzr3P5200cvxk+8WXSWauYbxuev9LCPdwfhlaWo/JEj6cu9seVdWlkagjGwkoV1kXC+GGntgUXOLAQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -1380,24 +1161,24 @@ } }, "node_modules/@parcel/transformer-babel": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.12.0.tgz", - "integrity": "sha512-zQaBfOnf/l8rPxYGnsk/ufh/0EuqvmnxafjBIpKZ//j6rGylw5JCqXSb1QvvAqRYruKeccxGv7+HrxpqKU6V4A==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.13.3.tgz", + "integrity": "sha512-ikzK9f5WTFrdQsPitQgjCPH6HmVU8AQPRemIJ2BndYhtodn5PQut5cnSvTrqax8RjYvheEKCQk/Zb/uR7qgS3g==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", + "@parcel/utils": "2.13.3", "browserslist": "^4.6.6", "json5": "^2.2.0", "nullthrows": "^1.1.1", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1405,23 +1186,23 @@ } }, "node_modules/@parcel/transformer-css": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.12.0.tgz", - "integrity": "sha512-vXhOqoAlQGATYyQ433Z1DXKmiKmzOAUmKysbYH3FD+LKEKLMEl/pA14goqp00TW+A/EjtSKKyeMyHlMIIUqj4Q==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.13.3.tgz", + "integrity": "sha512-zbrNURGph6JeVADbGydyZ7lcu/izj41kDxQ9xw4RPRW/3rofQiTU0OTREi+uBWiMENQySXVivEdzHA9cA+aLAA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", + "@parcel/utils": "2.13.3", "browserslist": "^4.6.6", "lightningcss": "^1.22.1", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1429,25 +1210,25 @@ } }, "node_modules/@parcel/transformer-html": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.12.0.tgz", - "integrity": "sha512-5jW4dFFBlYBvIQk4nrH62rfA/G/KzVzEDa6S+Nne0xXhglLjkm64Ci9b/d4tKZfuGWUbpm2ASAq8skti/nfpXw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.13.3.tgz", + "integrity": "sha512-Yf74FkL9RCCB4+hxQRVMNQThH9+fZ5w0NLiQPpWUOcgDEEyxTi4FWPQgEBsKl/XK2ehdydbQB9fBgPQLuQxwPg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", + "posthtml-parser": "^0.12.1", "posthtml-render": "^3.0.0", "semver": "^7.5.2", "srcset": "4" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1468,69 +1249,69 @@ } }, "node_modules/@parcel/transformer-image": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.12.0.tgz", - "integrity": "sha512-8hXrGm2IRII49R7lZ0RpmNk27EhcsH+uNKsvxuMpXPuEnWgC/ha/IrjaI29xCng1uGur74bJF43NUSQhR4aTdw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.13.3.tgz", + "integrity": "sha512-wL1CXyeFAqbp2wcEq/JD3a/tbAyVIDMTC6laQxlIwnVV7dsENhK1qRuJZuoBdixESeUpFQSmmQvDIhcfT/cUUg==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", - "@parcel/workers": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", + "@parcel/workers": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/transformer-js": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.12.0.tgz", - "integrity": "sha512-OSZpOu+FGDbC/xivu24v092D9w6EGytB3vidwbdiJ2FaPgfV7rxS0WIUjH4I0OcvHAcitArRXL0a3+HrNTdQQw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.13.3.tgz", + "integrity": "sha512-KqfNGn1IHzDoN2aPqt4nDksgb50Xzcny777C7A7hjlQ3cmkjyJrixYjzzsPaPSGJ+kJpknh3KE8unkQ9mhFvRQ==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.12.0", - "@parcel/workers": "2.12.0", + "@parcel/utils": "2.13.3", + "@parcel/workers": "2.13.3", "@swc/helpers": "^0.5.0", "browserslist": "^4.6.6", "nullthrows": "^1.1.1", - "regenerator-runtime": "^0.13.7", + "regenerator-runtime": "^0.14.1", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@parcel/transformer-json": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.12.0.tgz", - "integrity": "sha512-Utv64GLRCQILK5r0KFs4o7I41ixMPllwOLOhkdjJKvf1hZmN6WqfOmB1YLbWS/y5Zb/iB52DU2pWZm96vLFQZQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.13.3.tgz", + "integrity": "sha512-rrq0ab6J0w9ePtsxi0kAvpCmrUYXXAx1Z5PATZakv89rSYbHBKEdXxyCoKFui/UPVCUEGVs5r0iOFepdHpIyeA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", + "@parcel/plugin": "2.13.3", "json5": "^2.2.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1538,24 +1319,24 @@ } }, "node_modules/@parcel/transformer-postcss": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.12.0.tgz", - "integrity": "sha512-FZqn+oUtiLfPOn67EZxPpBkfdFiTnF4iwiXPqvst3XI8H+iC+yNgzmtJkunOOuylpYY6NOU5jT8d7saqWSDv2Q==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.13.3.tgz", + "integrity": "sha512-AIiWpU0QSFBrPcYIqAnhqB8RGE6yHFznnxztfg1t2zMSOnK3xoU6xqYKv8H/MduShGGrC3qVOeDfM8MUwzL3cw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", + "@parcel/utils": "2.13.3", "clone": "^2.1.1", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1563,23 +1344,23 @@ } }, "node_modules/@parcel/transformer-posthtml": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.12.0.tgz", - "integrity": "sha512-z6Z7rav/pcaWdeD+2sDUcd0mmNZRUvtHaUGa50Y2mr+poxrKilpsnFMSiWBT+oOqPt7j71jzDvrdnAF4XkCljg==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.13.3.tgz", + "integrity": "sha512-5GSLyccpHASwFAu3uJ83gDIBSvfsGdVmhJvy0Vxe+K1Fklk2ibhvvtUHMhB7mg6SPHC+R9jsNc3ZqY04ZLeGjw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", + "posthtml-parser": "^0.12.1", "posthtml-render": "^3.0.0", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1587,17 +1368,17 @@ } }, "node_modules/@parcel/transformer-raw": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.12.0.tgz", - "integrity": "sha512-Ht1fQvXxix0NncdnmnXZsa6hra20RXYh1VqhBYZLsDfkvGGFnXIgO03Jqn4Z8MkKoa0tiNbDhpKIeTjyclbBxQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.13.3.tgz", + "integrity": "sha512-BFsAbdQF0l8/Pdb7dSLJeYcd8jgwvAUbHgMink2MNXJuRUvDl19Gns8jVokU+uraFHulJMBj40+K/RTd33in4g==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0" + "@parcel/plugin": "2.13.3" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1605,19 +1386,19 @@ } }, "node_modules/@parcel/transformer-react-refresh-wrap": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.12.0.tgz", - "integrity": "sha512-GE8gmP2AZtkpBIV5vSCVhewgOFRhqwdM5Q9jNPOY5PKcM3/Ff0qCqDiTzzGLhk0/VMBrdjssrfZkVx6S/lHdJw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.13.3.tgz", + "integrity": "sha512-mOof4cRyxsZRdg8kkWaFtaX98mHpxUhcGPU+nF9RQVa9q737ItxrorsPNR9hpZAyE2TtFNflNW7RoYsgvlLw8w==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", - "react-refresh": "^0.9.0" + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", + "react-refresh": ">=0.9 <=0.14" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1625,24 +1406,24 @@ } }, "node_modules/@parcel/transformer-svg": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.12.0.tgz", - "integrity": "sha512-cZJqGRJ4JNdYcb+vj94J7PdOuTnwyy45dM9xqbIMH+HSiiIkfrMsdEwYft0GTyFTdsnf+hdHn3tau7Qa5hhX+A==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.13.3.tgz", + "integrity": "sha512-9jm7ZF4KHIrGLWlw/SFUz5KKJ20nxHvjFAmzde34R9Wu+F1BOjLZxae7w4ZRwvIc+UVOUcBBQFmhSVwVDZg6Dw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/rust": "2.13.3", "nullthrows": "^1.1.1", "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", + "posthtml-parser": "^0.12.1", "posthtml-render": "^3.0.0", "semver": "^7.5.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.12.0" + "node": ">= 16.0.0", + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1650,20 +1431,20 @@ } }, "node_modules/@parcel/transformer-webextension": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/transformer-webextension/-/transformer-webextension-2.12.0.tgz", - "integrity": "sha512-LvZAVcqVV3bV6TDFUTYLpOG92lJbEiULdgyVojP8zEMp716RU2QPJ8tQPbaUFDrXsT4UFnlEjM3N82k9Z/4xJw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-webextension/-/transformer-webextension-2.13.3.tgz", + "integrity": "sha512-P1AM32yo0blRfRbxijcumANPnNzROuPf2wbo8cYtKs7m9/G/UquOy3J+C3EW8AGbhJfeAY1mqUUtvVaAhgs8UQ==", "dev": true, "license": "MIT", "dependencies": { "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/plugin": "2.12.0", - "@parcel/utils": "2.12.0", - "content-security-policy-parser": "^0.3.0" + "@parcel/diagnostic": "2.13.3", + "@parcel/plugin": "2.13.3", + "@parcel/utils": "2.13.3", + "content-security-policy-parser": "^0.6.0" }, "engines": { - "parcel": "^2.12.0" + "parcel": "^2.13.3" }, "funding": { "type": "opencollective", @@ -1671,39 +1452,47 @@ } }, "node_modules/@parcel/types": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz", - "integrity": "sha512-8zAFiYNCwNTQcglIObyNwKfRYQK5ELlL13GuBOrSMxueUiI5ylgsGbTS1N7J3dAGZixHO8KhHGv5a71FILn9rQ==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.13.3.tgz", + "integrity": "sha512-+RpFHxx8fy8/dpuehHUw/ja9PRExC3wJoIlIIF42E7SLu2SvlTHtKm6EfICZzxCXNEBzjoDbamCRcN0nmTPlhw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/cache": "2.12.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/fs": "2.12.0", - "@parcel/package-manager": "2.12.0", + "@parcel/types-internal": "2.13.3", + "@parcel/workers": "2.13.3" + } + }, + "node_modules/@parcel/types-internal": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/types-internal/-/types-internal-2.13.3.tgz", + "integrity": "sha512-Lhx0n+9RCp+Ipktf/I+CLm3zE9Iq9NtDd8b2Vr5lVWyoT8AbzBKIHIpTbhLS4kjZ80L3I6o93OYjqAaIjsqoZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@parcel/diagnostic": "2.13.3", + "@parcel/feature-flags": "2.13.3", "@parcel/source-map": "^2.1.1", - "@parcel/workers": "2.12.0", "utility-types": "^3.10.0" } }, "node_modules/@parcel/utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.12.0.tgz", - "integrity": "sha512-z1JhLuZ8QmDaYoEIuUCVZlhcFrS7LMfHrb2OCRui5SQFntRWBH2fNM6H/fXXUkT9SkxcuFP2DUA6/m4+Gkz72g==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.13.3.tgz", + "integrity": "sha512-yxY9xw2wOUlJaScOXYZmMGoZ4Ck4Kqj+p6Koe5kLkkWM1j98Q0Dj2tf/mNvZi4yrdnlm+dclCwNRnuE8Q9D+pw==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/codeframe": "2.12.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/logger": "2.12.0", - "@parcel/markdown-ansi": "2.12.0", - "@parcel/rust": "2.12.0", + "@parcel/codeframe": "2.13.3", + "@parcel/diagnostic": "2.13.3", + "@parcel/logger": "2.13.3", + "@parcel/markdown-ansi": "2.13.3", + "@parcel/rust": "2.13.3", "@parcel/source-map": "^2.1.1", - "chalk": "^4.1.0", + "chalk": "^4.1.2", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -1711,10 +1500,11 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", - "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { "detect-libc": "^1.0.3", @@ -1730,24 +1520,25 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.4.1", - "@parcel/watcher-darwin-arm64": "2.4.1", - "@parcel/watcher-darwin-x64": "2.4.1", - "@parcel/watcher-freebsd-x64": "2.4.1", - "@parcel/watcher-linux-arm-glibc": "2.4.1", - "@parcel/watcher-linux-arm64-glibc": "2.4.1", - "@parcel/watcher-linux-arm64-musl": "2.4.1", - "@parcel/watcher-linux-x64-glibc": "2.4.1", - "@parcel/watcher-linux-x64-musl": "2.4.1", - "@parcel/watcher-win32-arm64": "2.4.1", - "@parcel/watcher-win32-ia32": "2.4.1", - "@parcel/watcher-win32-x64": "2.4.1" + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", - "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", "cpu": [ "arm64" ], @@ -1766,9 +1557,9 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", - "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", "cpu": [ "arm64" ], @@ -1787,9 +1578,9 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", - "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", "cpu": [ "x64" ], @@ -1808,9 +1599,9 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", - "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", "cpu": [ "x64" ], @@ -1829,9 +1620,30 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", - "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", "cpu": [ "arm" ], @@ -1850,9 +1662,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", - "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", "cpu": [ "arm64" ], @@ -1871,9 +1683,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", - "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", "cpu": [ "arm64" ], @@ -1892,9 +1704,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", - "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", "cpu": [ "x64" ], @@ -1913,9 +1725,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", - "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", "cpu": [ "x64" ], @@ -1934,9 +1746,9 @@ } }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", - "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", "cpu": [ "arm64" ], @@ -1955,9 +1767,9 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", - "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", "cpu": [ "ia32" ], @@ -1976,9 +1788,9 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", - "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", "cpu": [ "x64" ], @@ -1997,40 +1809,40 @@ } }, "node_modules/@parcel/workers": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.12.0.tgz", - "integrity": "sha512-zv5We5Jmb+ZWXlU6A+AufyjY4oZckkxsZ8J4dvyWL0W8IQvGO1JB4FGeryyttzQv3RM3OxcN/BpTGPiDG6keBw==", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.13.3.tgz", + "integrity": "sha512-oAHmdniWTRwwwsKbcF4t3VjOtKN+/W17Wj5laiYB+HLkfsjGTfIQPj3sdXmrlBAGpI4omIcvR70PHHXnfdTfwA==", "dev": true, "license": "MIT", "dependencies": { - "@parcel/diagnostic": "2.12.0", - "@parcel/logger": "2.12.0", - "@parcel/profiler": "2.12.0", - "@parcel/types": "2.12.0", - "@parcel/utils": "2.12.0", + "@parcel/diagnostic": "2.13.3", + "@parcel/logger": "2.13.3", + "@parcel/profiler": "2.13.3", + "@parcel/types-internal": "2.13.3", + "@parcel/utils": "2.13.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "peerDependencies": { - "@parcel/core": "^2.12.0" + "@parcel/core": "^2.13.3" } }, "node_modules/@swc/core": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.26.tgz", - "integrity": "sha512-f5uYFf+TmMQyYIoxkn/evWhNGuUzC730dFwAKGwBVHHVoPyak1/GvJUm6i1SKl+2Hrj9oN0i3WSoWWZ4pgI8lw==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.12.tgz", + "integrity": "sha512-+iUL0PYpPm6N9AdV1wvafakvCqFegQus1aoEDxgFsv3/uNVNIyRaupf/v/Zkp5hbep2EzhtoJR0aiJIzDbXWHg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" + "@swc/types": "^0.1.17" }, "engines": { "node": ">=10" @@ -2040,16 +1852,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.26", - "@swc/core-darwin-x64": "1.7.26", - "@swc/core-linux-arm-gnueabihf": "1.7.26", - "@swc/core-linux-arm64-gnu": "1.7.26", - "@swc/core-linux-arm64-musl": "1.7.26", - "@swc/core-linux-x64-gnu": "1.7.26", - "@swc/core-linux-x64-musl": "1.7.26", - "@swc/core-win32-arm64-msvc": "1.7.26", - "@swc/core-win32-ia32-msvc": "1.7.26", - "@swc/core-win32-x64-msvc": "1.7.26" + "@swc/core-darwin-arm64": "1.10.12", + "@swc/core-darwin-x64": "1.10.12", + "@swc/core-linux-arm-gnueabihf": "1.10.12", + "@swc/core-linux-arm64-gnu": "1.10.12", + "@swc/core-linux-arm64-musl": "1.10.12", + "@swc/core-linux-x64-gnu": "1.10.12", + "@swc/core-linux-x64-musl": "1.10.12", + "@swc/core-win32-arm64-msvc": "1.10.12", + "@swc/core-win32-ia32-msvc": "1.10.12", + "@swc/core-win32-x64-msvc": "1.10.12" }, "peerDependencies": { "@swc/helpers": "*" @@ -2061,9 +1873,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.26.tgz", - "integrity": "sha512-FF3CRYTg6a7ZVW4yT9mesxoVVZTrcSWtmZhxKCYJX9brH4CS/7PRPjAKNk6kzWgWuRoglP7hkjQcd6EpMcZEAw==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.12.tgz", + "integrity": "sha512-pOANQegUTAriW7jq3SSMZGM5l89yLVMs48R0F2UG6UZsH04SiViCnDctOGlA/Sa++25C+rL9MGMYM1jDLylBbg==", "cpu": [ "arm64" ], @@ -2078,9 +1890,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.26.tgz", - "integrity": "sha512-az3cibZdsay2HNKmc4bjf62QVukuiMRh5sfM5kHR/JMTrLyS6vSw7Ihs3UTkZjUxkLTT8ro54LI6sV6sUQUbLQ==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.12.tgz", + "integrity": "sha512-m4kbpIDDsN1FrwfNQMU+FTrss356xsXvatLbearwR+V0lqOkjLBP0VmRvQfHEg+uy13VPyrT9gj4HLoztlci7w==", "cpu": [ "x64" ], @@ -2095,9 +1907,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.26.tgz", - "integrity": "sha512-VYPFVJDO5zT5U3RpCdHE5v1gz4mmR8BfHecUZTmD2v1JeFY6fv9KArJUpjrHEEsjK/ucXkQFmJ0jaiWXmpOV9Q==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.12.tgz", + "integrity": "sha512-OY9LcupgqEu8zVK+rJPes6LDJJwPDmwaShU96beTaxX2K6VrXbpwm5WbPS/8FfQTsmpnuA7dCcMPUKhNgmzTrQ==", "cpu": [ "arm" ], @@ -2112,9 +1924,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.26.tgz", - "integrity": "sha512-YKevOV7abpjcAzXrhsl+W48Z9mZvgoVs2eP5nY+uoMAdP2b3GxC0Df1Co0I90o2lkzO4jYBpTMcZlmUXLdXn+Q==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.12.tgz", + "integrity": "sha512-nJD587rO0N4y4VZszz3xzVr7JIiCzSMhEMWnPjuh+xmPxDBz0Qccpr8xCr1cSxpl1uY7ERkqAGlKr6CwoV5kVg==", "cpu": [ "arm64" ], @@ -2129,9 +1941,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.26.tgz", - "integrity": "sha512-3w8iZICMkQQON0uIcvz7+Q1MPOW6hJ4O5ETjA0LSP/tuKqx30hIniCGOgPDnv3UTMruLUnQbtBwVCZTBKR3Rkg==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.12.tgz", + "integrity": "sha512-oqhSmV+XauSf0C//MoQnVErNUB/5OzmSiUzuazyLsD5pwqKNN+leC3JtRQ/QVzaCpr65jv9bKexT9+I2Tt3xDw==", "cpu": [ "arm64" ], @@ -2146,9 +1958,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.26.tgz", - "integrity": "sha512-c+pp9Zkk2lqb06bNGkR2Looxrs7FtGDMA4/aHjZcCqATgp348hOKH5WPvNLBl+yPrISuWjbKDVn3NgAvfvpH4w==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.12.tgz", + "integrity": "sha512-XldSIHyjD7m1Gh+/8rxV3Ok711ENLI420CU2EGEqSe3VSGZ7pHJvJn9ZFbYpWhsLxPqBYMFjp3Qw+J6OXCPXCA==", "cpu": [ "x64" ], @@ -2163,9 +1975,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.26.tgz", - "integrity": "sha512-PgtyfHBF6xG87dUSSdTJHwZ3/8vWZfNIXQV2GlwEpslrOkGqy+WaiiyE7Of7z9AvDILfBBBcJvJ/r8u980wAfQ==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.12.tgz", + "integrity": "sha512-wvPXzJxzPgTqhyp1UskOx1hRTtdWxlyFD1cGWOxgLsMik0V9xKRgqKnMPv16Nk7L9xl6quQ6DuUHj9ID7L3oVw==", "cpu": [ "x64" ], @@ -2180,9 +1992,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.26.tgz", - "integrity": "sha512-9TNXPIJqFynlAOrRD6tUQjMq7KApSklK3R/tXgIxc7Qx+lWu8hlDQ/kVPLpU7PWvMMwC/3hKBW+p5f+Tms1hmA==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.12.tgz", + "integrity": "sha512-TUYzWuu1O7uyIcRfxdm6Wh1u+gNnrW5M1DUgDOGZLsyQzgc2Zjwfh2llLhuAIilvCVg5QiGbJlpibRYJ/8QGsg==", "cpu": [ "arm64" ], @@ -2197,9 +2009,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.26.tgz", - "integrity": "sha512-9YngxNcG3177GYdsTum4V98Re+TlCeJEP4kEwEg9EagT5s3YejYdKwVAkAsJszzkXuyRDdnHUpYbTrPG6FiXrQ==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.12.tgz", + "integrity": "sha512-4Qrw+0Xt+Fe2rz4OJ/dEPMeUf/rtuFWWAj/e0vL7J5laUHirzxawLRE5DCJLQTarOiYR6mWnmadt9o3EKzV6Xg==", "cpu": [ "ia32" ], @@ -2214,9 +2026,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.26", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.26.tgz", - "integrity": "sha512-VR+hzg9XqucgLjXxA13MtV5O3C0bK0ywtLIBw/+a+O+Oc6mxFWHtdUeXDbIi5AiPbn0fjgVJMqYnyjGyyX8u0w==", + "version": "1.10.12", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.12.tgz", + "integrity": "sha512-YiloZXLW7rUxJpALwHXaGjVaAEn+ChoblG7/3esque+Y7QCyheoBUJp2DVM1EeVA43jBfZ8tvYF0liWd9Tpz1A==", "cpu": [ "x64" ], @@ -2238,39 +2050,29 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", - "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "tslib": "^2.4.0" + "tslib": "^2.8.0" } }, "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", + "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@types/chrome": { - "version": "0.0.271", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.271.tgz", - "integrity": "sha512-K0qgXvkwA5ic+/eygF1xiypHEvCoBgH5lwrhg3yva2mqJuCWyYm0vpZQ22GksAxgGfo0PWev9Zx3plp2clMlwg==", + "version": "0.0.300", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.300.tgz", + "integrity": "sha512-vS5bUmNjMrbPut43Q8plS8GTAiJE+pBOxw1ovGC4LcwiGNKTithAH7TxhzHeX4wNq/FsaLj5KaW7riI0CgYjIg==", "dev": true, "license": "MIT", "dependencies": { @@ -2296,27 +2098,20 @@ "license": "MIT" }, "node_modules/@types/har-format": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.15.tgz", - "integrity": "sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsbn": { - "version": "1.2.33", - "resolved": "https://registry.npmjs.org/@types/jsbn/-/jsbn-1.2.33.tgz", - "integrity": "sha512-ZlLkHfu8xqqVFSbCe1FSPtAMUs7LKxk7TPskMb+sI5IbuzqyVqIEt9SVaQfFD2vrFcQunqKAmEBOuBEkoNLw4g==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", + "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { - "version": "20.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", - "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", + "version": "22.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", + "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.20.0" } }, "node_modules/@types/webextension-polyfill": { @@ -2340,13 +2135,6 @@ "npm": ">=5" } }, - "node_modules/abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2408,13 +2196,6 @@ ], "license": "MIT" }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -2446,9 +2227,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -2466,10 +2247,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2514,9 +2295,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001662", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz", - "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", + "version": "1.0.30001696", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", + "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", "dev": true, "funding": [ { @@ -2592,13 +2373,13 @@ "license": "MIT" }, "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=18" } }, "node_modules/concat-map": { @@ -2609,13 +2390,13 @@ "license": "MIT" }, "node_modules/content-security-policy-parser": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/content-security-policy-parser/-/content-security-policy-parser-0.3.0.tgz", - "integrity": "sha512-ub90B4t9EfDPv3DCH7vEwGe4tVMkSm4Ow1HsmvmEQwinDfpTEDmkuJVa5WpzHDTt2bUirNRZuzL6S0msASlJhg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/content-security-policy-parser/-/content-security-policy-parser-0.6.0.tgz", + "integrity": "sha512-wejtC/p+HLNQ7uaWgg1o3CKHhE8QXC9fJ2GCY0X82L5HUNtZSq1dmUvNSHHEb6R7LS02fpmRBq/vP8i4/+9KCg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=18.0.0" } }, "node_modules/cosmiconfig": { @@ -2658,33 +2439,25 @@ "postcss": "^8.0.9" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": ">=0.10" } }, - "node_modules/css-select/node_modules/dom-serializer": { + "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -2694,14 +2467,30 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/css-select/node_modules/domhandler": { + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "license": "BSD-2-Clause", - "optional": true, - "peer": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -2712,14 +2501,12 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/css-select/node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", - "optional": true, - "peer": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -2729,207 +2516,46 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/css-select/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "dev": true, "license": "BSD-2-Clause", - "optional": true, - "peer": true, "engines": { - "node": ">=0.12" + "node": ">=12" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://dotenvx.com" } }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true, - "license": "CC0-1.0", - "optional": true, - "peer": true - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "domelementtype": "^2.2.0" + "dotenv": "^16.4.5" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "url": "https://dotenvx.com" } }, - "node_modules/dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=6" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/electron-to-chromium": { - "version": "1.5.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", - "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==", + "version": "1.5.90", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", + "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", "dev": true, "license": "ISC" }, "node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -2969,16 +2595,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3139,9 +2755,9 @@ } }, "node_modules/htmlparser2": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", - "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", @@ -3152,10 +2768,10 @@ ], "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, "node_modules/ieee754": { @@ -3226,14 +2842,10 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -3246,9 +2858,9 @@ "license": "MIT" }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { @@ -3321,12 +2933,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "license": "MIT" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -3348,9 +2954,9 @@ } }, "node_modules/lightningcss": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.27.0.tgz", - "integrity": "sha512-8f7aNmS1+etYSLHht0fQApPc2kNO8qGRutifN5rVIc6Xo6ABsEbqOr758UwI7ALVbTt4x1fllKt0PYgzD9S3yQ==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.1.tgz", + "integrity": "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -3364,22 +2970,22 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.27.0", - "lightningcss-darwin-x64": "1.27.0", - "lightningcss-freebsd-x64": "1.27.0", - "lightningcss-linux-arm-gnueabihf": "1.27.0", - "lightningcss-linux-arm64-gnu": "1.27.0", - "lightningcss-linux-arm64-musl": "1.27.0", - "lightningcss-linux-x64-gnu": "1.27.0", - "lightningcss-linux-x64-musl": "1.27.0", - "lightningcss-win32-arm64-msvc": "1.27.0", - "lightningcss-win32-x64-msvc": "1.27.0" + "lightningcss-darwin-arm64": "1.29.1", + "lightningcss-darwin-x64": "1.29.1", + "lightningcss-freebsd-x64": "1.29.1", + "lightningcss-linux-arm-gnueabihf": "1.29.1", + "lightningcss-linux-arm64-gnu": "1.29.1", + "lightningcss-linux-arm64-musl": "1.29.1", + "lightningcss-linux-x64-gnu": "1.29.1", + "lightningcss-linux-x64-musl": "1.29.1", + "lightningcss-win32-arm64-msvc": "1.29.1", + "lightningcss-win32-x64-msvc": "1.29.1" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.27.0.tgz", - "integrity": "sha512-Gl/lqIXY+d+ySmMbgDf0pgaWSqrWYxVHoc88q+Vhf2YNzZ8DwoRzGt5NZDVqqIW5ScpSnmmjcgXP87Dn2ylSSQ==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.1.tgz", + "integrity": "sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==", "cpu": [ "arm64" ], @@ -3398,9 +3004,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.27.0.tgz", - "integrity": "sha512-0+mZa54IlcNAoQS9E0+niovhyjjQWEMrwW0p2sSdLRhLDc8LMQ/b67z7+B5q4VmjYCMSfnFi3djAAQFIDuj/Tg==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.1.tgz", + "integrity": "sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==", "cpu": [ "x64" ], @@ -3419,9 +3025,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.27.0.tgz", - "integrity": "sha512-n1sEf85fePoU2aDN2PzYjoI8gbBqnmLGEhKq7q0DKLj0UTVmOTwDC7PtLcy/zFxzASTSBlVQYJUhwIStQMIpRA==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.1.tgz", + "integrity": "sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==", "cpu": [ "x64" ], @@ -3440,9 +3046,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.27.0.tgz", - "integrity": "sha512-MUMRmtdRkOkd5z3h986HOuNBD1c2lq2BSQA1Jg88d9I7bmPGx08bwGcnB75dvr17CwxjxD6XPi3Qh8ArmKFqCA==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.1.tgz", + "integrity": "sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==", "cpu": [ "arm" ], @@ -3461,9 +3067,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.27.0.tgz", - "integrity": "sha512-cPsxo1QEWq2sfKkSq2Bq5feQDHdUEwgtA9KaB27J5AX22+l4l0ptgjMZZtYtUnteBofjee+0oW1wQ1guv04a7A==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.1.tgz", + "integrity": "sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==", "cpu": [ "arm64" ], @@ -3482,9 +3088,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.27.0.tgz", - "integrity": "sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.1.tgz", + "integrity": "sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==", "cpu": [ "arm64" ], @@ -3503,9 +3109,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.27.0.tgz", - "integrity": "sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.1.tgz", + "integrity": "sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==", "cpu": [ "x64" ], @@ -3524,9 +3130,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.27.0.tgz", - "integrity": "sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.1.tgz", + "integrity": "sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==", "cpu": [ "x64" ], @@ -3545,9 +3151,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.27.0.tgz", - "integrity": "sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.1.tgz", + "integrity": "sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==", "cpu": [ "arm64" ], @@ -3566,9 +3172,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.27.0.tgz", - "integrity": "sha512-/OJLj94Zm/waZShL8nB5jsNj3CfNATLCTyFxZyouilfTmSoLDX7VlVAmhPHoZWVFp4vdmoiEbPEYC8HID3m6yw==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.1.tgz", + "integrity": "sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==", "cpu": [ "x64" ], @@ -3637,15 +3243,6 @@ "global": "^4.4.0" } }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true, - "license": "CC0-1.0", - "optional": true, - "peer": true - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3692,9 +3289,9 @@ } }, "node_modules/msgpackr": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz", - "integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", + "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", "dev": true, "license": "MIT", "optionalDependencies": { @@ -3752,9 +3349,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -3803,25 +3400,12 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -3840,9 +3424,9 @@ } }, "node_modules/ordered-binary": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.1.tgz", - "integrity": "sha512-5VyHfHY3cd0iza71JepYG50My+YUbrFtGoUz2ooEydPyPM7Aai/JW098juLr+RG6+rDJuzNNTsEQu2DZa1A41A==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", + "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", "dev": true, "license": "MIT" }, @@ -3854,32 +3438,33 @@ "license": "MIT" }, "node_modules/parcel": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.12.0.tgz", - "integrity": "sha512-W+gxAq7aQ9dJIg/XLKGcRT0cvnStFAQHPaI0pvD0U2l6IVLueUAm3nwN7lkY62zZNmlvNx6jNtE4wlbS+CyqSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@parcel/config-default": "2.12.0", - "@parcel/core": "2.12.0", - "@parcel/diagnostic": "2.12.0", - "@parcel/events": "2.12.0", - "@parcel/fs": "2.12.0", - "@parcel/logger": "2.12.0", - "@parcel/package-manager": "2.12.0", - "@parcel/reporter-cli": "2.12.0", - "@parcel/reporter-dev-server": "2.12.0", - "@parcel/reporter-tracer": "2.12.0", - "@parcel/utils": "2.12.0", - "chalk": "^4.1.0", - "commander": "^7.0.0", + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.13.3.tgz", + "integrity": "sha512-8GrC8C7J8mwRpAlk7EJ7lwdFTbCN+dcXH2gy5AsEs9pLfzo9wvxOTx6W0fzSlvCOvZOita+8GdfYlGfEt0tRgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@parcel/config-default": "2.13.3", + "@parcel/core": "2.13.3", + "@parcel/diagnostic": "2.13.3", + "@parcel/events": "2.13.3", + "@parcel/feature-flags": "2.13.3", + "@parcel/fs": "2.13.3", + "@parcel/logger": "2.13.3", + "@parcel/package-manager": "2.13.3", + "@parcel/reporter-cli": "2.13.3", + "@parcel/reporter-dev-server": "2.13.3", + "@parcel/reporter-tracer": "2.13.3", + "@parcel/utils": "2.13.3", + "chalk": "^4.1.2", + "commander": "^12.1.0", "get-port": "^4.2.0" }, "bin": { "parcel": "lib/bin.js" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 16.0.0" }, "funding": { "type": "opencollective", @@ -3936,9 +3521,9 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -3956,9 +3541,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "dev": true, "funding": [ { @@ -3976,8 +3561,8 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -4046,16 +3631,16 @@ } }, "node_modules/posthtml-parser": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", - "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.12.1.tgz", + "integrity": "sha512-rYFmsDLfYm+4Ts2Oh4DCDSZPtdC1BLnRXAobypVzX9alj28KGl65dIFtgDY9zB57D0TC4Qxqrawuq/2et1P0GA==", "dev": true, "license": "MIT", "dependencies": { - "htmlparser2": "^7.1.1" + "htmlparser2": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=16" } }, "node_modules/posthtml-render": { @@ -4071,6 +3656,95 @@ "node": ">=12" } }, + "node_modules/posthtml/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/posthtml/node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/posthtml/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/posthtml/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/posthtml/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/posthtml/node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, "node_modules/posthtml/node_modules/posthtml-parser": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", @@ -4157,9 +3831,9 @@ "license": "MIT" }, "node_modules/react-refresh": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", - "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "dev": true, "license": "MIT", "engines": { @@ -4179,26 +3853,28 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true, + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4235,9 +3911,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", "dev": true, "license": "ISC", "bin": { @@ -4282,16 +3958,6 @@ "node": ">=6" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4302,12 +3968,6 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "license": "BSD-3-Clause" - }, "node_modules/srcset": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/srcset/-/srcset-5.0.1.tgz", @@ -4323,14 +3983,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true, - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4357,34 +4009,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, "node_modules/sync-threads": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sync-threads/-/sync-threads-1.0.1.tgz", @@ -4426,9 +4050,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, @@ -4446,9 +4070,9 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4460,16 +4084,16 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -4487,8 +4111,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/package.json b/package.json index d1e577ec..b06d2e9b 100644 --- a/package.json +++ b/package.json @@ -43,24 +43,23 @@ "license": "GPL-3.0", "dependencies": { "bowser": "^2.11.0", - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "m3u8-parser": "^7.2.0" }, "devDependencies": { - "@parcel/config-webextension": "^2.12.0", - "@types/chrome": "^0.0.271", - "@types/jsbn": "^1.2.33", - "@types/node": "^20.16.5", + "@parcel/config-webextension": "^2.13.3", + "@types/chrome": "^0.0.300", + "@types/node": "^22.13.0", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "os-browserify": "^0.3.0", - "parcel": "^2.12.0", - "postcss": "^8.4.47", + "parcel": "^2.13.3", + "postcss": "^8.5.1", "prettier": "2.8.8", "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", "shx": "^0.3.4", - "typescript": "^5.6.2", + "typescript": "^5.7.3", "webextension-polyfill": "^0.12.0" }, "private": true From fc0cb7e1b50b2a1b48d343bad63b722c953dc5f2 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:24:46 +0100 Subject: [PATCH 09/28] Bump version number to 2.4.0 --- package-lock.json | 4 ++-- package.json | 2 +- src/manifest.chromium.json | 2 +- src/manifest.firefox.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f320c5d..dfd47a44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ttv-lol-pro", - "version": "2.3.10", + "version": "2.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ttv-lol-pro", - "version": "2.3.10", + "version": "2.4.0", "license": "GPL-3.0", "dependencies": { "bowser": "^2.11.0", diff --git a/package.json b/package.json index b06d2e9b..af802eaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ttv-lol-pro", - "version": "2.3.10", + "version": "2.4.0", "description": "TTV LOL PRO removes most livestream ads from Twitch.", "@parcel/bundler-default": { "minBundles": 10000000, diff --git a/src/manifest.chromium.json b/src/manifest.chromium.json index 9093e0cd..a8ed01eb 100644 --- a/src/manifest.chromium.json +++ b/src/manifest.chromium.json @@ -3,7 +3,7 @@ "name": "TTV LOL PRO", "description": "TTV LOL PRO removes most livestream ads from Twitch.", "homepage_url": "https://github.com/younesaassila/ttv-lol-pro", - "version": "2.3.10", + "version": "2.4.0", "background": { "service_worker": "background/background.ts", "type": "module" diff --git a/src/manifest.firefox.json b/src/manifest.firefox.json index 0db9fffc..743aac4e 100644 --- a/src/manifest.firefox.json +++ b/src/manifest.firefox.json @@ -3,7 +3,7 @@ "name": "TTV LOL PRO", "description": "TTV LOL PRO removes most livestream ads from Twitch.", "homepage_url": "https://github.com/younesaassila/ttv-lol-pro", - "version": "2.3.10", + "version": "2.4.0", "background": { "scripts": ["background/background.ts"], "persistent": false From 3b9103c331429e510ca436688210f3a9e4fb64e0 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:27:06 +0100 Subject: [PATCH 10/28] Fix build error --- package-lock.json | 154 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 155 insertions(+) diff --git a/package-lock.json b/package-lock.json index dfd47a44..410e877b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", "shx": "^0.3.4", + "svgo": "^3.3.2", "typescript": "^5.7.3", "webextension-polyfill": "^0.12.0" } @@ -2069,6 +2070,16 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@types/chrome": { "version": "0.0.300", "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.300.tgz", @@ -2196,6 +2207,13 @@ ], "license": "MIT" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -2439,6 +2457,86 @@ "postcss": "^8.0.9" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -3243,6 +3341,13 @@ "global": "^4.4.0" } }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3406,6 +3511,19 @@ "dev": true, "license": "MIT" }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -4009,6 +4127,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/sync-threads": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sync-threads/-/sync-threads-1.0.1.tgz", diff --git a/package.json b/package.json index af802eaf..13339154 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", "shx": "^0.3.4", + "svgo": "^3.3.2", "typescript": "^5.7.3", "webextension-polyfill": "^0.12.0" }, From 125cecec16e3bf5b6720ff9bb17fb4a7834fa395 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:44:50 +0100 Subject: [PATCH 11/28] Remove unused deps --- package-lock.json | 11 ++--------- package.json | 2 -- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 410e877b..4343bbf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,7 @@ "@types/node": "^22.13.0", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", - "os-browserify": "^0.3.0", "parcel": "^2.13.3", - "postcss": "^8.5.1", "prettier": "2.8.8", "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", @@ -3465,6 +3463,7 @@ } ], "license": "MIT", + "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3548,13 +3547,6 @@ "dev": true, "license": "MIT" }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", - "dev": true, - "license": "MIT" - }, "node_modules/parcel": { "version": "2.13.3", "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.13.3.tgz", @@ -3678,6 +3670,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", diff --git a/package.json b/package.json index 13339154..78411854 100644 --- a/package.json +++ b/package.json @@ -52,9 +52,7 @@ "@types/node": "^22.13.0", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", - "os-browserify": "^0.3.0", "parcel": "^2.13.3", - "postcss": "^8.5.1", "prettier": "2.8.8", "prettier-plugin-css-order": "^1.3.1", "prettier-plugin-organize-imports": "^3.2.4", From ebe2f76794c3b81077df7aa347fc300a20d59b11 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 16:08:29 +0100 Subject: [PATCH 12/28] Upgrade workflow dependencies --- .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f69afdac..2ae23db9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: concurrency: build-${{ github.ref }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: npm install - name: Run linter diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9ab9dc9e..d55392c7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -42,11 +42,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -59,7 +59,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -72,6 +72,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" From 66d3ef30b1c0a81487470edc1148bd2f4853c22d Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 18:52:29 +0100 Subject: [PATCH 13/28] Add VOD check for auto whitelist sub channel feature --- src/page/getFetch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 72a32cf1..82a918a4 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -270,6 +270,7 @@ export function getFetch(pageState: PageState): typeof fetch { const channelName = findChannelFromUsherUrl(url); if ( pageState.state?.whitelistChannelSubscriptions && + isLivestream && channelName != null ) { const wasSubscribed = wasChannelSubscriber(channelName, pageState); From 7ab206e3d822daa6d1e8ceb29355f2698b92670d Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sat, 1 Feb 2025 19:21:59 +0100 Subject: [PATCH 14/28] Reduce log level for "no manifest for weaver" because of frequency due to ClearStats --- src/page/getFetch.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 82a918a4..122e008a 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -329,9 +329,9 @@ export function getFetch(pageState: PageState): typeof fetch { [...manifest.assignedMap.values()].includes(url) ); if (manifest == null) { - console.warn( + console.log( "[TTV LOL PRO] No associated Usher manifest found for Video Weaver request." - ); + ); // This can happen just after a ClearStats message if Twitch decides to send another Video Weaver request. } if (videoWeaverUrlsToNotProxy.has(url)) { if (IS_DEVELOPMENT) { From 2a79647fae4d28805f40b0cab6660d70bdb1757f Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 2 Feb 2025 14:24:14 +0100 Subject: [PATCH 15/28] Implement review changes --- src/common/ts/isChannelWhitelisted.ts | 3 ++- src/common/ts/wasChannelSubscriber.ts | 3 ++- src/page/getFetch.ts | 6 ++++-- src/page/sendMessage.ts | 4 +--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/common/ts/isChannelWhitelisted.ts b/src/common/ts/isChannelWhitelisted.ts index 88364f07..be72ed16 100644 --- a/src/common/ts/isChannelWhitelisted.ts +++ b/src/common/ts/isChannelWhitelisted.ts @@ -4,7 +4,8 @@ export default function isChannelWhitelisted( channelName: string | null ): boolean { if (!channelName) return false; + const channelNameLower = channelName.toLowerCase(); return store.state.whitelistedChannels.some( - c => c.toLowerCase() === channelName.toLowerCase() + c => c.toLowerCase() === channelNameLower ); } diff --git a/src/common/ts/wasChannelSubscriber.ts b/src/common/ts/wasChannelSubscriber.ts index be45e79b..672bf2cd 100644 --- a/src/common/ts/wasChannelSubscriber.ts +++ b/src/common/ts/wasChannelSubscriber.ts @@ -4,7 +4,8 @@ export default function wasChannelSubscriber( channelName: string | null ): boolean { if (!channelName) return false; + const channelNameLower = channelName.toLowerCase(); return store.state.activeChannelSubscriptions.some( - c => c.toLowerCase() === channelName.toLowerCase() + c => c.toLowerCase() === channelNameLower ); } diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 122e008a..1e76f87d 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -650,9 +650,10 @@ function isChannelWhitelisted( pageState: PageState ): boolean { if (!channelName) return false; + const channelNameLower = channelName.toLowerCase(); return ( pageState.state?.whitelistedChannels.some( - c => c.toLowerCase() === channelName.toLowerCase() + c => c.toLowerCase() === channelNameLower ) ?? false ); } @@ -662,9 +663,10 @@ function wasChannelSubscriber( pageState: PageState ): boolean { if (!channelName) return false; + const channelNameLower = channelName.toLowerCase(); return ( pageState.state?.activeChannelSubscriptions.some( - c => c.toLowerCase() === channelName.toLowerCase() + c => c.toLowerCase() === channelNameLower ) ?? false ); } diff --git a/src/page/sendMessage.ts b/src/page/sendMessage.ts index b25b33b4..b8f3f266 100644 --- a/src/page/sendMessage.ts +++ b/src/page/sendMessage.ts @@ -32,9 +32,7 @@ async function sendMessageAndWaitForResponse( ): Promise { return new Promise((resolve, reject) => { if (!recipient) { - console.error("[TTV LOL PRO] Message recipient is undefined."); - resolve(undefined); - return; + return reject(new Error("Message recipient is undefined.")); } const listener = (event: MessageEvent) => { From be39a5344f1c8305de29618c6af410f21e76fcac Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 2 Feb 2025 17:22:48 +0100 Subject: [PATCH 16/28] Fix auto whitelist subs feature - The token in the Usher req lies about the sub status (always false) --- src/page/getFetch.ts | 144 ++++++++++++++++++++++++++++++++----------- src/types.ts | 2 + 2 files changed, 111 insertions(+), 35 deletions(-) diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 1e76f87d..437953ca 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -44,14 +44,28 @@ export function getFetch(pageState: PageState): typeof fetch { cachedPlaybackTokenRequestHeaders, cachedPlaybackTokenRequestBody ); - const message = { + pageState.sendMessageToWorkerScripts(pageState.twitchWorkers, { type: MessageType.NewPlaybackAccessTokenResponse, newPlaybackAccessToken, - }; - pageState.sendMessageToWorkerScripts( - pageState.twitchWorkers, - message - ); + }); + break; + case MessageType.ChannelSubStatusQuery: + try { + const req = getSubStatusRequest(message.channelName); + const res = await NATIVE_FETCH(req); + const body = await res.json(); + const isSubscribed = + body.data.user.self.subscriptionBenefit != null; + pageState.sendMessageToWorkerScripts(pageState.twitchWorkers, { + type: MessageType.ChannelSubStatusQueryResponse, + isSubscribed, + }); + } catch (error) { + pageState.sendMessageToWorkerScripts(pageState.twitchWorkers, { + type: MessageType.ChannelSubStatusQueryResponse, + error: `${error}`, + }); + } break; } }); @@ -199,7 +213,7 @@ export function getFetch(pageState: PageState): typeof fetch { pageState.state?.anonymousMode === true || (shouldFlagRequest && willFailIntegrityCheckIfProxied); if (shouldOverrideRequest) { - const newRequest = await getDefaultPlaybackAccessTokenRequest( + const newRequest = getDefaultPlaybackAccessTokenRequest( channelName, pageState.state?.anonymousMode === true ); @@ -273,31 +287,8 @@ export function getFetch(pageState: PageState): typeof fetch { isLivestream && channelName != null ) { - const wasSubscribed = wasChannelSubscriber(channelName, pageState); - const isSubscribed = url.includes( - encodeURIComponent('"subscriber":true') - ); - const hasSubStatusChanged = - (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); - if (hasSubStatusChanged) { - try { - const response = - await pageState.sendMessageToContentScriptAndWaitForResponse( - pageState.scope, - { - type: MessageType.ChannelSubStatusChange, - channelName, - wasSubscribed, - isSubscribed, - }, - MessageType.ChannelSubStatusChangeResponse - ); - if (typeof response.whitelistedChannels === "object") { - pageState.state.whitelistedChannels = - response.whitelistedChannels; - } - } catch {} - } + // TODO: Maybe also check before PlaybackAccessToken requests? (But then that's a LOT of overhead.) + await checkChannelSubStatus(channelName, pageState); } const isWhitelisted = isChannelWhitelisted(channelName, pageState); if (!isLivestream || isFrontpage || isWhitelisted) { @@ -726,6 +717,89 @@ async function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } +function getSubStatusRequest(channelName: string): Request { + const cookieMap = new Map( + document.cookie + .split(";") + .map(cookie => cookie.trim().split("=")) + .map(([name, value]) => [name, decodeURIComponent(value)]) + ); + const headersMap = new Map([ + [ + "Authorization", + cookieMap.has("auth-token") + ? `OAuth ${cookieMap.get("auth-token")}` + : "undefined", + ], + ["Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"], + ["Device-ID", generateRandomString(32)], + ]); + + return new Request("https://gql.twitch.tv/gql", { + method: "POST", + headers: Object.fromEntries(headersMap), + body: JSON.stringify({ + operationName: "ChannelPage_SubscribeButton_User", + variables: { + login: channelName, + }, + extensions: { + persistedQuery: { + version: 1, + sha256Hash: + "a1da17caf3041632c3f9b4069dfc8d93ff10b5b5023307ec0a694a9d8eae991e", + }, + }, + }), + }); +} + +async function checkChannelSubStatus( + channelName: string, + pageState: PageState +) { + try { + const channelSubStatus = + await pageState.sendMessageToPageScriptAndWaitForResponse( + pageState.scope, + { + type: MessageType.ChannelSubStatusQuery, + channelName, + }, + MessageType.ChannelSubStatusQueryResponse + ); + if (!channelSubStatus || channelSubStatus.error) { + throw new Error( + `Error querying channel sub status: ${channelSubStatus.error}` + ); + } + const wasSubscribed = wasChannelSubscriber(channelName, pageState); + const isSubscribed = channelSubStatus.isSubscribed; + const hasSubStatusChanged = + (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); + if (hasSubStatusChanged) { + try { + const response = + await pageState.sendMessageToContentScriptAndWaitForResponse( + pageState.scope, + { + type: MessageType.ChannelSubStatusChange, + channelName, + wasSubscribed, + isSubscribed, + }, + MessageType.ChannelSubStatusChangeResponse + ); + if (typeof response.whitelistedChannels === "object") { + pageState.state!.whitelistedChannels = response.whitelistedChannels; + } + } catch {} + } + } catch (error) { + console.error("[TTV LOL PRO] Failed to check channel sub status:", error); + } +} + //#region Video Weaver URL replacement /** @@ -734,10 +808,10 @@ async function sleep(ms: number): Promise { * @param anonymousMode * @returns */ -async function getDefaultPlaybackAccessTokenRequest( +function getDefaultPlaybackAccessTokenRequest( channel: string | null = null, anonymousMode: boolean = false -): Promise { +): Request | null { // We can use `location.href` because we're in the page script. const channelName = channel ?? findChannelFromTwitchTvUrl(location.href); if (!channelName) return null; @@ -793,7 +867,7 @@ async function fetchReplacementPlaybackAccessToken( ): Promise { // Not using the cached request because we'd need to check if integrity requests are proxied. try { - let request = await getDefaultPlaybackAccessTokenRequest( + let request = getDefaultPlaybackAccessTokenRequest( null, pageState.state?.anonymousMode === true ); diff --git a/src/types.ts b/src/types.ts index 2d924e80..43b0aa85 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,6 +79,8 @@ export const enum MessageType { EnableFullMode = "TLP_EnableFullMode", EnableFullModeResponse = "TLP_EnableFullModeResponse", DisableFullMode = "TLP_DisableFullMode", + ChannelSubStatusQuery = "TLP_ChannelSubStatusQuery", + ChannelSubStatusQueryResponse = "TLP_ChannelSubStatusQueryResponse", ChannelSubStatusChange = "TLP_ChannelSubStatusChange", ChannelSubStatusChangeResponse = "TLP_ChannelSubStatusChangeResponse", UsherResponse = "TLP_UsherResponse", From ac50e0c8b27b5a79aeae9f946467d4093c2a2aaf Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:52:18 +0100 Subject: [PATCH 17/28] Improve implementation of auto whitelist feature --- src/common/ts/regexes.ts | 2 +- src/common/ts/wasChannelSubscriber.ts | 11 -- src/content/content.ts | 11 +- src/page/getFetch.ts | 168 +++++++++----------------- src/page/page.ts | 1 + 5 files changed, 63 insertions(+), 130 deletions(-) delete mode 100644 src/common/ts/wasChannelSubscriber.ts diff --git a/src/common/ts/regexes.ts b/src/common/ts/regexes.ts index 53cbc155..f9fbef74 100644 --- a/src/common/ts/regexes.ts +++ b/src/common/ts/regexes.ts @@ -1,7 +1,7 @@ export const passportHostRegex = /^passport\.twitch\.tv$/i; export const twitchApiChannelNameRegex = /\/hls\/(.+)\.m3u8/i; export const twitchChannelNameRegex = - /^https?:\/\/(?:www|m)\.twitch\.tv\/(?:videos\/|popout\/|moderator\/)?((?!(?:directory|jobs|p|privacy|store|turbo)\b)\w+)/i; + /^https?:\/\/(?:www|m)\.twitch\.tv\/(?:videos\/|popout\/|moderator\/)?((?!(?:directory|downloads|jobs|p|privacy|search|settings|store|turbo)\b)\w+)/i; export const twitchGqlHostRegex = /^gql\.twitch\.tv$/i; export const twitchTvHostRegex = /^(?:www|m)\.twitch\.tv$/i; export const usherHostRegex = /^usher\.ttvnw\.net$/i; diff --git a/src/common/ts/wasChannelSubscriber.ts b/src/common/ts/wasChannelSubscriber.ts deleted file mode 100644 index 672bf2cd..00000000 --- a/src/common/ts/wasChannelSubscriber.ts +++ /dev/null @@ -1,11 +0,0 @@ -import store from "../../store"; - -export default function wasChannelSubscriber( - channelName: string | null -): boolean { - if (!channelName) return false; - const channelNameLower = channelName.toLowerCase(); - return store.state.activeChannelSubscriptions.some( - c => c.toLowerCase() === channelNameLower - ); -} diff --git a/src/content/content.ts b/src/content/content.ts index 9445e204..e660ae18 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -158,6 +158,7 @@ function onPageMessage(event: MessageEvent) { console.log(`[TTV LOL PRO] Adding '${channelName}' to whitelist.`); store.state.whitelistedChannels.push(channelName); } + location.reload(); } else if (wasSubscribed && !isSubscribed) { store.state.activeChannelSubscriptions = store.state.activeChannelSubscriptions.filter( @@ -173,17 +174,9 @@ function onPageMessage(event: MessageEvent) { c => c.toLowerCase() !== channelName.toLowerCase() ); } + location.reload(); } } - window.postMessage({ - type: responseType, - message: { - type: responseMessageType, - whitelistedChannels: JSON.parse( - JSON.stringify(store.state.whitelistedChannels) - ), - }, - }); } // --- else if (message.type === MessageType.UsherResponse) { diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index 437953ca..cfb6bc65 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -49,24 +49,6 @@ export function getFetch(pageState: PageState): typeof fetch { newPlaybackAccessToken, }); break; - case MessageType.ChannelSubStatusQuery: - try { - const req = getSubStatusRequest(message.channelName); - const res = await NATIVE_FETCH(req); - const body = await res.json(); - const isSubscribed = - body.data.user.self.subscriptionBenefit != null; - pageState.sendMessageToWorkerScripts(pageState.twitchWorkers, { - type: MessageType.ChannelSubStatusQueryResponse, - isSubscribed, - }); - } catch (error) { - pageState.sendMessageToWorkerScripts(pageState.twitchWorkers, { - type: MessageType.ChannelSubStatusQueryResponse, - error: `${error}`, - }); - } - break; } }); } @@ -282,14 +264,6 @@ export function getFetch(pageState: PageState): typeof fetch { encodeURIComponent('"player_type":"frontpage"') ); const channelName = findChannelFromUsherUrl(url); - if ( - pageState.state?.whitelistChannelSubscriptions && - isLivestream && - channelName != null - ) { - // TODO: Maybe also check before PlaybackAccessToken requests? (But then that's a LOT of overhead.) - await checkChannelSubStatus(channelName, pageState); - } const isWhitelisted = isChannelWhitelisted(channelName, pageState); if (!isLivestream || isFrontpage || isWhitelisted) { console.log( @@ -425,6 +399,65 @@ export function getFetch(pageState: PageState): typeof fetch { //#region Responses + graphqlRes: if ( + host != null && + twitchGqlHostRegex.test(host) && + response.status < 400 + ) { + responseBody ??= await readResponseBody(); + // Preliminary check to avoid parsing the response body if possible. + if ( + !responseBody.includes('"UserSelfConnection"') || + !responseBody.includes('"subscriptionBenefit"') || + !responseBody.includes('"login"') + ) { + break graphqlRes; + } + try { + let channelName: string; + let isSubscribed: boolean; + const body = JSON.parse(responseBody); + if (Array.isArray(body)) { + const match = body.find( + (obj: any) => + obj.data && + obj.data.user && + obj.data.user.login != null && + obj.data.user.self && + "subscriptionBenefit" in obj.data.user.self + ); + if (match == null) break graphqlRes; + channelName = match.data.user.login; + isSubscribed = match.data.user.self.subscriptionBenefit != null; + } else { + const isMatch = + body.data && + body.data.user && + body.data.user.login != null && + body.data.user.self && + "subscriptionBenefit" in body.data.user.self; + if (!isMatch) break graphqlRes; + channelName = body.data.user.login; + isSubscribed = body.data.user.self.subscriptionBenefit != null; + } + const isLivestream = !/^\d+$/.test(channelName); // VODs have numeric IDs. + if (!isLivestream) break graphqlRes; + const wasSubscribed = wasChannelSubscriber(channelName, pageState); + const hasSubStatusChanged = + (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); + if (hasSubStatusChanged) { + pageState.sendMessageToContentScript({ + type: MessageType.ChannelSubStatusChange, + channelName, + wasSubscribed, + isSubscribed, + }); + } + } catch (error) { + console.error("[TTV LOL PRO] Failed to parse GraphQL response:", error); + } + } + // Twitch Usher responses. usherRes: if ( host != null && @@ -717,89 +750,6 @@ async function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } -function getSubStatusRequest(channelName: string): Request { - const cookieMap = new Map( - document.cookie - .split(";") - .map(cookie => cookie.trim().split("=")) - .map(([name, value]) => [name, decodeURIComponent(value)]) - ); - const headersMap = new Map([ - [ - "Authorization", - cookieMap.has("auth-token") - ? `OAuth ${cookieMap.get("auth-token")}` - : "undefined", - ], - ["Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"], - ["Device-ID", generateRandomString(32)], - ]); - - return new Request("https://gql.twitch.tv/gql", { - method: "POST", - headers: Object.fromEntries(headersMap), - body: JSON.stringify({ - operationName: "ChannelPage_SubscribeButton_User", - variables: { - login: channelName, - }, - extensions: { - persistedQuery: { - version: 1, - sha256Hash: - "a1da17caf3041632c3f9b4069dfc8d93ff10b5b5023307ec0a694a9d8eae991e", - }, - }, - }), - }); -} - -async function checkChannelSubStatus( - channelName: string, - pageState: PageState -) { - try { - const channelSubStatus = - await pageState.sendMessageToPageScriptAndWaitForResponse( - pageState.scope, - { - type: MessageType.ChannelSubStatusQuery, - channelName, - }, - MessageType.ChannelSubStatusQueryResponse - ); - if (!channelSubStatus || channelSubStatus.error) { - throw new Error( - `Error querying channel sub status: ${channelSubStatus.error}` - ); - } - const wasSubscribed = wasChannelSubscriber(channelName, pageState); - const isSubscribed = channelSubStatus.isSubscribed; - const hasSubStatusChanged = - (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); - if (hasSubStatusChanged) { - try { - const response = - await pageState.sendMessageToContentScriptAndWaitForResponse( - pageState.scope, - { - type: MessageType.ChannelSubStatusChange, - channelName, - wasSubscribed, - isSubscribed, - }, - MessageType.ChannelSubStatusChangeResponse - ); - if (typeof response.whitelistedChannels === "object") { - pageState.state!.whitelistedChannels = response.whitelistedChannels; - } - } catch {} - } - } catch (error) { - console.error("[TTV LOL PRO] Failed to check channel sub status:", error); - } -} - //#region Video Weaver URL replacement /** diff --git a/src/page/page.ts b/src/page/page.ts index b7619ace..694c963e 100644 --- a/src/page/page.ts +++ b/src/page/page.ts @@ -39,6 +39,7 @@ const pageState: PageState = { sendMessageToWorkerScriptsAndWaitForResponse, }; +const NATIVE_FETCH = window.fetch; window.fetch = getFetch(pageState); const NATIVE_WORKER = window.Worker; From 010265c8f04cb2111d6e4831879fefb0e9df1e6c Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:38:26 +0100 Subject: [PATCH 18/28] Cleanup + fix warnings caused by clearStats --- src/content/content.ts | 18 +++++++++++++----- src/page/getFetch.ts | 31 ++++++++++++++++--------------- src/page/types.ts | 1 + src/types.ts | 5 +---- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/content/content.ts b/src/content/content.ts index e660ae18..618d741b 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -47,10 +47,13 @@ function onStoreLoad() { /** * Clear stats for stream on page load/reload. + * @param channelName + * @param delayMs * @returns */ -function clearStats(channelName: string | null) { +async function clearStats(channelName: string | null, delayMs?: number) { if (!channelName) return; + if (delayMs) await new Promise(resolve => setTimeout(resolve, delayMs)); const channelNameLower = channelName.toLowerCase(); if (store.state.streamStatuses.hasOwnProperty(channelNameLower)) { delete store.state.streamStatuses[channelNameLower]; @@ -102,7 +105,7 @@ function onPageMessage(event: MessageEvent) { return; } - const { message, responseType, responseMessageType } = event.data; + const { message } = event.data; if (!message) return; if (message.type === MessageType.GetStoreState) { @@ -150,6 +153,7 @@ function onPageMessage(event: MessageEvent) { isSubscribed, isWhitelisted, }); + const currentChannelName = findChannelFromTwitchTvUrl(location.href); if (store.state.whitelistChannelSubscriptions && channelName != null) { if (!wasSubscribed && isSubscribed) { store.state.activeChannelSubscriptions.push(channelName); @@ -158,7 +162,9 @@ function onPageMessage(event: MessageEvent) { console.log(`[TTV LOL PRO] Adding '${channelName}' to whitelist.`); store.state.whitelistedChannels.push(channelName); } - location.reload(); + if (channelName === currentChannelName) { + location.reload(); + } } else if (wasSubscribed && !isSubscribed) { store.state.activeChannelSubscriptions = store.state.activeChannelSubscriptions.filter( @@ -174,7 +180,9 @@ function onPageMessage(event: MessageEvent) { c => c.toLowerCase() !== channelName.toLowerCase() ); } - location.reload(); + if (channelName === currentChannelName) { + location.reload(); + } } } } @@ -201,6 +209,6 @@ function onPageMessage(event: MessageEvent) { } // --- else if (message.type === MessageType.ClearStats) { - clearStats(message.channelName); + clearStats(message.channelName, 2000); } } diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index cfb6bc65..b616ec65 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -71,9 +71,11 @@ export function getFetch(pageState: PageState): typeof fetch { console.log("[TTV LOL PRO] Cleared stats (getFetch)."); if (!message.channelName) break; const channelNameLower = message.channelName.toLowerCase(); - usherManifests = usherManifests.filter( - manifest => manifest.channelName !== channelNameLower - ); + for (let i = 0; i < usherManifests.length; i++) { + if (usherManifests[i].channelName === channelNameLower) { + usherManifests[i].deleted = true; + } + } if (cachedPlaybackTokenRequestBody?.includes(channelNameLower)) { cachedPlaybackTokenRequestHeaders = null; cachedPlaybackTokenRequestBody = null; @@ -294,9 +296,9 @@ export function getFetch(pageState: PageState): typeof fetch { [...manifest.assignedMap.values()].includes(url) ); if (manifest == null) { - console.log( + console.warn( "[TTV LOL PRO] No associated Usher manifest found for Video Weaver request." - ); // This can happen just after a ClearStats message if Twitch decides to send another Video Weaver request. + ); } if (videoWeaverUrlsToNotProxy.has(url)) { if (IS_DEVELOPMENT) { @@ -442,6 +444,7 @@ export function getFetch(pageState: PageState): typeof fetch { } const isLivestream = !/^\d+$/.test(channelName); // VODs have numeric IDs. if (!isLivestream) break graphqlRes; + await waitForStore(pageState); const wasSubscribed = wasChannelSubscriber(channelName, pageState); const hasSubStatusChanged = (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); @@ -465,6 +468,7 @@ export function getFetch(pageState: PageState): typeof fetch { response.status < 400 ) { //#region Usher responses. + // No need to wait for store here because all Usher requests have already waited for it. const isLivestream = !url.includes("/vod/"); const isFrontpage = url.includes( encodeURIComponent('"player_type":"frontpage"') @@ -474,6 +478,7 @@ export function getFetch(pageState: PageState): typeof fetch { if (!isLivestream) break usherRes; responseBody ??= await readResponseBody(); + usherManifests = usherManifests.filter(manifest => !manifest.deleted); // Clean up deleted manifests. const assignedMap = parseUsherManifest(responseBody); if (assignedMap != null) { console.debug( @@ -486,9 +491,12 @@ export function getFetch(pageState: PageState): typeof fetch { replacementMap: null, consecutiveMidrollResponses: 0, consecutiveMidrollCooldown: 0, + deleted: false, }); } else { - console.debug("[TTV LOL PRO] Received Usher response."); + console.error( + "[TTV LOL PRO] Received Usher response but failed to parse it." + ); } // Send Video Weaver URLs to content script. const videoWeaverUrls = [...(assignedMap?.values() ?? [])]; @@ -534,14 +542,11 @@ export function getFetch(pageState: PageState): typeof fetch { console.log("[TTV LOL PRO] Midroll ad detected."); manifest.consecutiveMidrollResponses += 1; manifest.consecutiveMidrollCooldown = 15; - const isWhitelisted = isChannelWhitelisted( - manifest.channelName, - pageState - ); + await waitForStore(pageState); const shouldUpdateReplacementMap = pageState.state?.optimizedProxiesEnabled === true && manifest.consecutiveMidrollResponses <= 2 && // Avoid infinite loop. - !isWhitelisted; + !videoWeaverUrlsToNotProxy.has(url); if (shouldUpdateReplacementMap) { const success = await updateVideoWeaverReplacementMap( pageState, @@ -746,10 +751,6 @@ function cancelRequest(): never { throw new Error(); } -async function sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); -} - //#region Video Weaver URL replacement /** diff --git a/src/page/types.ts b/src/page/types.ts index a782b754..151ca7f3 100644 --- a/src/page/types.ts +++ b/src/page/types.ts @@ -36,6 +36,7 @@ export interface UsherManifest { replacementMap: Map | null; // Same as above, but with new URLs. consecutiveMidrollResponses: number; // Used to avoid infinite loops. consecutiveMidrollCooldown: number; // Used to avoid infinite loops. + deleted: boolean; // Deletion flag for cleanup. } export interface PlaybackAccessToken { diff --git a/src/types.ts b/src/types.ts index 43b0aa85..d642a206 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,13 +79,10 @@ export const enum MessageType { EnableFullMode = "TLP_EnableFullMode", EnableFullModeResponse = "TLP_EnableFullModeResponse", DisableFullMode = "TLP_DisableFullMode", - ChannelSubStatusQuery = "TLP_ChannelSubStatusQuery", - ChannelSubStatusQueryResponse = "TLP_ChannelSubStatusQueryResponse", - ChannelSubStatusChange = "TLP_ChannelSubStatusChange", - ChannelSubStatusChangeResponse = "TLP_ChannelSubStatusChangeResponse", UsherResponse = "TLP_UsherResponse", NewPlaybackAccessToken = "TLP_NewPlaybackAccessToken", NewPlaybackAccessTokenResponse = "TLP_NewPlaybackAccessTokenResponse", + ChannelSubStatusChange = "TLP_ChannelSubStatusChange", MultipleAdBlockersInUse = "TLP_MultipleAdBlockersInUse", ClearStats = "TLP_ClearStats", } From 9f45b77b83a7e122a623283d1b7fd25440bb7162 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:09:27 +0100 Subject: [PATCH 19/28] Upgrade dependencies --- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4343bbf3..3a5ffe09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,8 @@ }, "devDependencies": { "@parcel/config-webextension": "^2.13.3", - "@types/chrome": "^0.0.300", - "@types/node": "^22.13.0", + "@types/chrome": "^0.0.301", + "@types/node": "^22.13.1", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "parcel": "^2.13.3", @@ -2079,9 +2079,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.0.300", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.300.tgz", - "integrity": "sha512-vS5bUmNjMrbPut43Q8plS8GTAiJE+pBOxw1ovGC4LcwiGNKTithAH7TxhzHeX4wNq/FsaLj5KaW7riI0CgYjIg==", + "version": "0.0.301", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.301.tgz", + "integrity": "sha512-BljW7InXXOfDYr4nG79y5lnaklrZ0gmeTwCUkuCXK2+69dHnZIrg13KhXJE/HrcFUmy8NG/EK+RTGScsh/Hbiw==", "dev": true, "license": "MIT", "dependencies": { @@ -2114,9 +2114,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", - "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 78411854..8a790105 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,8 @@ }, "devDependencies": { "@parcel/config-webextension": "^2.13.3", - "@types/chrome": "^0.0.300", - "@types/node": "^22.13.0", + "@types/chrome": "^0.0.301", + "@types/node": "^22.13.1", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "parcel": "^2.13.3", From 6fcae2eea1c8df88cf689b93e544ba786c766b77 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Tue, 4 Feb 2025 16:09:34 +0100 Subject: [PATCH 20/28] Fix review comments --- src/common/ts/isChannelWhitelisted.ts | 2 +- src/content/content.ts | 38 +++++++++++++++------------ src/page/getFetch.ts | 14 ++++++---- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/common/ts/isChannelWhitelisted.ts b/src/common/ts/isChannelWhitelisted.ts index be72ed16..1a02c8ac 100644 --- a/src/common/ts/isChannelWhitelisted.ts +++ b/src/common/ts/isChannelWhitelisted.ts @@ -6,6 +6,6 @@ export default function isChannelWhitelisted( if (!channelName) return false; const channelNameLower = channelName.toLowerCase(); return store.state.whitelistedChannels.some( - c => c.toLowerCase() === channelNameLower + channel => channel.toLowerCase() === channelNameLower ); } diff --git a/src/content/content.ts b/src/content/content.ts index 618d741b..4da32df6 100644 --- a/src/content/content.ts +++ b/src/content/content.ts @@ -145,43 +145,47 @@ function onPageMessage(event: MessageEvent) { } // --- else if (message.type === MessageType.ChannelSubStatusChange) { - const { channelName, wasSubscribed, isSubscribed } = message; - const isWhitelisted = isChannelWhitelisted(channelName); + const { channelNameLower, wasSubscribed, isSubscribed } = message; + const isWhitelisted = isChannelWhitelisted(channelNameLower); console.log("[TTV LOL PRO] ChannelSubStatusChange", { - channelName, + channelNameLower, wasSubscribed, isSubscribed, isWhitelisted, }); - const currentChannelName = findChannelFromTwitchTvUrl(location.href); - if (store.state.whitelistChannelSubscriptions && channelName != null) { + const currentChannelNameLower = findChannelFromTwitchTvUrl( + location.href + )?.toLowerCase(); + if (store.state.whitelistChannelSubscriptions && channelNameLower != null) { if (!wasSubscribed && isSubscribed) { - store.state.activeChannelSubscriptions.push(channelName); + store.state.activeChannelSubscriptions.push(channelNameLower); // Add to whitelist. if (!isWhitelisted) { - console.log(`[TTV LOL PRO] Adding '${channelName}' to whitelist.`); - store.state.whitelistedChannels.push(channelName); - } - if (channelName === currentChannelName) { - location.reload(); + console.log( + `[TTV LOL PRO] Adding '${channelNameLower}' to whitelist.` + ); + store.state.whitelistedChannels.push(channelNameLower); + if (channelNameLower === currentChannelNameLower) { + location.reload(); + } } } else if (wasSubscribed && !isSubscribed) { store.state.activeChannelSubscriptions = store.state.activeChannelSubscriptions.filter( - c => c.toLowerCase() !== channelName.toLowerCase() + channel => channel.toLowerCase() !== channelNameLower ); // Remove from whitelist. if (isWhitelisted) { console.log( - `[TTV LOL PRO] Removing '${channelName}' from whitelist.` + `[TTV LOL PRO] Removing '${channelNameLower}' from whitelist.` ); store.state.whitelistedChannels = store.state.whitelistedChannels.filter( - c => c.toLowerCase() !== channelName.toLowerCase() + channel => channel.toLowerCase() !== channelNameLower ); - } - if (channelName === currentChannelName) { - location.reload(); + if (channelNameLower === currentChannelNameLower) { + location.reload(); + } } } } diff --git a/src/page/getFetch.ts b/src/page/getFetch.ts index b616ec65..c44badbe 100644 --- a/src/page/getFetch.ts +++ b/src/page/getFetch.ts @@ -72,7 +72,9 @@ export function getFetch(pageState: PageState): typeof fetch { if (!message.channelName) break; const channelNameLower = message.channelName.toLowerCase(); for (let i = 0; i < usherManifests.length; i++) { - if (usherManifests[i].channelName === channelNameLower) { + if ( + usherManifests[i].channelName?.toLowerCase() === channelNameLower + ) { usherManifests[i].deleted = true; } } @@ -406,6 +408,8 @@ export function getFetch(pageState: PageState): typeof fetch { twitchGqlHostRegex.test(host) && response.status < 400 ) { + await waitForStore(pageState); + if (!pageState.state?.whitelistChannelSubscriptions) break graphqlRes; responseBody ??= await readResponseBody(); // Preliminary check to avoid parsing the response body if possible. if ( @@ -442,16 +446,16 @@ export function getFetch(pageState: PageState): typeof fetch { channelName = body.data.user.login; isSubscribed = body.data.user.self.subscriptionBenefit != null; } + if (!channelName) break graphqlRes; const isLivestream = !/^\d+$/.test(channelName); // VODs have numeric IDs. if (!isLivestream) break graphqlRes; - await waitForStore(pageState); const wasSubscribed = wasChannelSubscriber(channelName, pageState); const hasSubStatusChanged = (wasSubscribed && !isSubscribed) || (!wasSubscribed && isSubscribed); if (hasSubStatusChanged) { pageState.sendMessageToContentScript({ type: MessageType.ChannelSubStatusChange, - channelName, + channelNameLower: channelName.toLowerCase(), wasSubscribed, isSubscribed, }); @@ -682,7 +686,7 @@ function isChannelWhitelisted( const channelNameLower = channelName.toLowerCase(); return ( pageState.state?.whitelistedChannels.some( - c => c.toLowerCase() === channelNameLower + channel => channel.toLowerCase() === channelNameLower ) ?? false ); } @@ -695,7 +699,7 @@ function wasChannelSubscriber( const channelNameLower = channelName.toLowerCase(); return ( pageState.state?.activeChannelSubscriptions.some( - c => c.toLowerCase() === channelNameLower + channel => channel.toLowerCase() === channelNameLower ) ?? false ); } From f9fcce5cac46c91aac33fe7ef09daac01a0e83a9 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:30:41 +0100 Subject: [PATCH 21/28] Update workflows --- .github/workflows/build.yml | 2 ++ .github/workflows/codeql.yml | 2 ++ .github/workflows/dependency-review.yml | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ae23db9..7e560334 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,11 +6,13 @@ on: tags-ignore: ["**"] pull_request: branches: ["**"] + types: [opened, synchronize, reopened, ready_for_review] jobs: build: name: Build runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} concurrency: build-${{ github.ref }} steps: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d55392c7..e67c8553 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -18,6 +18,7 @@ on: pull_request: # The branches below must be a subset of the branches above branches: ["v2"] + types: [opened, synchronize, reopened, ready_for_review] schedule: - cron: "32 9 * * 6" @@ -25,6 +26,7 @@ jobs: analyze: name: Analyze runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} concurrency: codeql-${{ github.ref }} permissions: actions: read diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 9eab75db..890bb910 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -5,14 +5,20 @@ # Source repository: https://github.com/actions/dependency-review-action # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement name: "Dependency Review" -on: [pull_request] +on: + pull_request: + branches: ["**"] + types: [opened, synchronize, reopened, ready_for_review] permissions: contents: read jobs: dependency-review: + name: Dependency Review runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} + concurrency: dependencies-${{ github.ref }} steps: - name: "Checkout Repository" uses: actions/checkout@v4 From de97812b2400c77df8d60011aec4b651f0c45cdb Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:54:31 +0100 Subject: [PATCH 22/28] Reformat code, add toggle option for protocol support --- .../handlers/onBeforeVideoWeaverRequest.ts | 2 +- src/background/handlers/onProxyRequest.ts | 14 +++--- src/background/handlers/onResponseStarted.ts | 2 +- src/common/ts/proxyInfo.ts | 43 ++++++------------- src/common/ts/proxySettings.ts | 12 +++++- src/options/options.ts | 27 ++++++++---- src/options/page.html | 30 +++++++++++++ src/store/getDefaultState.ts | 1 + src/store/types.ts | 1 + src/types.ts | 12 +----- 10 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/background/handlers/onBeforeVideoWeaverRequest.ts b/src/background/handlers/onBeforeVideoWeaverRequest.ts index deec2f29..9eba3c74 100644 --- a/src/background/handlers/onBeforeVideoWeaverRequest.ts +++ b/src/background/handlers/onBeforeVideoWeaverRequest.ts @@ -38,7 +38,7 @@ export default function onBeforeVideoWeaverRequest( textLower.includes("https://example.com") && textLower.includes("https://help.twitch.tv/"); const proxy = - details.proxyInfo && details.proxyInfo.type !== "DIRECT" + details.proxyInfo && details.proxyInfo.type !== "direct" ? getUrlFromProxyInfo(details.proxyInfo) : null; diff --git a/src/background/handlers/onProxyRequest.ts b/src/background/handlers/onProxyRequest.ts index a27e60d4..5dbaf5fa 100644 --- a/src/background/handlers/onProxyRequest.ts +++ b/src/background/handlers/onProxyRequest.ts @@ -32,7 +32,7 @@ export default async function onProxyRequest( } const host = getHostFromUrl(details.url); - if (!host) return { type: "DIRECT" }; + if (!host) return { type: "direct" }; const documentHost = details.documentUrl ? getHostFromUrl(details.documentUrl) @@ -43,7 +43,7 @@ export default async function onProxyRequest( !passportHostRegex.test(documentHost) && // Passport requests have a `passport.twitch.tv` document URL. !twitchTvHostRegex.test(documentHost) ) { - return { type: "DIRECT" }; + return { type: "direct" }; } const proxies = store.state.optimizedProxiesEnabled @@ -92,12 +92,12 @@ export default async function onProxyRequest( if (proxyUsherRequest && usherHostRegex.test(host)) { if (details.url.includes("/vod/")) { console.log(`✋ '${details.url}' is a VOD manifest.`); - return { type: "DIRECT" }; + return { type: "direct" }; } const channelName = findChannelFromUsherUrl(details.url); if (isChannelWhitelisted(channelName)) { console.log(`✋ Channel '${channelName}' is whitelisted.`); - return { type: "DIRECT" }; + return { type: "direct" }; } console.log( `⌛ Proxying ${details.url} (${ @@ -119,7 +119,7 @@ export default async function onProxyRequest( findChannelFromTwitchTvUrl(tabUrl); if (isChannelWhitelisted(channelName)) { console.log(`✋ Channel '${channelName}' is whitelisted.`); - return { type: "DIRECT" }; + return { type: "direct" }; } console.log( `⌛ Proxying ${details.url} (${ @@ -149,12 +149,12 @@ export default async function onProxyRequest( return proxyInfoArray; } - return { type: "DIRECT" }; + return { type: "direct" }; } function getProxyInfoArrayFromUrls(urls: string[]): ProxyInfo[] { return [ ...urls.map(getProxyInfoFromUrl), - { type: "DIRECT" } as ProxyInfo, // Fallback to direct connection if all proxies fail. + { type: "direct" } as ProxyInfo, // Fallback to direct connection if all proxies fail. ]; } diff --git a/src/background/handlers/onResponseStarted.ts b/src/background/handlers/onResponseStarted.ts index e1883869..a02b4367 100644 --- a/src/background/handlers/onResponseStarted.ts +++ b/src/background/handlers/onResponseStarted.ts @@ -171,7 +171,7 @@ function getProxyFromDetails( return getUrlFromProxyInfo(possibleProxies[0]); } else { const proxyInfo = details.proxyInfo; // Firefox only. - if (!proxyInfo || proxyInfo.type === "DIRECT") return null; + if (!proxyInfo || proxyInfo.type === "direct") return null; return getUrlFromProxyInfo(proxyInfo); } } diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index 7f42552a..1e463491 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -1,36 +1,24 @@ import { Address6 } from "ip-address"; -import type { ProxyInfo } from "../../types"; +import type { ProxyInfo, ProxyType } from "../../types"; -export const proxySchemes = { - direct: "DIRECT", - http: "PROXY", - https: "HTTPS", - socks: "SOCKS", - socks4: "SOCKS4", - socks5: "SOCKS5", - quic: "QUIC", -} as const; - -type Protocol = keyof typeof proxySchemes; - -const defaultPorts: Partial<{ - [key in keyof typeof proxySchemes]: number; -}> = { +const DEFAULT_PORTS: Readonly> = Object.freeze({ + direct: 0, http: 80, https: 443, socks: 1080, socks4: 1080, - socks5: 1080, - quic: 443, -}; +}); -export function getProxyInfoFromUrl(url: string) { - let protocol = ""; +export function getProxyInfoFromUrl( + url: string +): ProxyInfo & { host: string; port: number } { + let type: ProxyType | undefined = undefined; if (url.includes("://")) { - const [_protocol, urlWithoutProtocol] = url.split("://"); - protocol = _protocol; + const [protocol, urlWithoutProtocol] = url.split("://", 2); + type = protocol as ProxyType; url = urlWithoutProtocol; } + const lastIndexOfAt = url.lastIndexOf("@"); const hostname = url.substring(lastIndexOfAt + 1, url.length); const lastIndexOfColon = getLastIndexOfColon(hostname); @@ -39,9 +27,7 @@ export function getProxyInfoFromUrl(url: string) { let port: number | undefined = undefined; if (lastIndexOfColon === -1) { host = hostname; - if (!protocol) { - port = 3128; // Default port - } + port = !type ? 3128 : DEFAULT_PORTS[type]; // Default port } else { host = hostname.substring(0, lastIndexOfColon); port = Number(hostname.substring(lastIndexOfColon + 1, hostname.length)); @@ -59,11 +45,8 @@ export function getProxyInfoFromUrl(url: string) { password = credentials.substring(indexOfColon + 1, credentials.length); } - port = port ? port : defaultPorts[protocol as Protocol]; - return { - type: proxySchemes[protocol as Protocol] ?? "PROXY", - protocol, + type: type ?? "http", host, port, username, diff --git a/src/common/ts/proxySettings.ts b/src/common/ts/proxySettings.ts index d493f5fd..39f3de5f 100644 --- a/src/common/ts/proxySettings.ts +++ b/src/common/ts/proxySettings.ts @@ -1,5 +1,5 @@ import store from "../../store"; -import { ProxyRequestType } from "../../types"; +import { ProxyRequestType, ProxyType } from "../../types"; import isRequestTypeProxied from "./isRequestTypeProxied"; import { getProxyInfoFromUrl, getUrlFromProxyInfo } from "./proxyInfo"; import { @@ -11,6 +11,14 @@ import { } from "./regexes"; import updateDnsResponses from "./updateDnsResponses"; +const PROXY_TYPE_MAP: Readonly> = Object.freeze({ + direct: "DIRECT", + http: "PROXY", + https: "HTTPS", + socks4: "SOCKS4", + socks: "SOCKS5", +}); + export function updateProxySettings(requestFilter?: ProxyRequestType[]) { const { optimizedProxiesEnabled, passportLevel } = store.state; @@ -92,7 +100,7 @@ function getProxyInfoStringFromUrls(urls: string[]): string { return [ ...urls.map(url => { const proxyInfo = getProxyInfoFromUrl(url); - return `${proxyInfo.type} ${getUrlFromProxyInfo({ + return `${PROXY_TYPE_MAP[proxyInfo.type]} ${getUrlFromProxyInfo({ ...proxyInfo, // Don't include username/password in PAC script. username: undefined, diff --git a/src/options/options.ts b/src/options/options.ts index c78a0167..75e4a38b 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -85,6 +85,9 @@ const optimizedProxiesListElement = $( ) as HTMLOListElement; const normalProxiesInputElement = $("#normal") as HTMLInputElement; const normalProxiesListElement = $("#normal-proxies-list") as HTMLOListElement; +const otherProtocolsCheckboxElement = $( + "#other-protocols-checkbox" +) as HTMLInputElement; // Ad log const adLogEnabledCheckboxElement = $( "#ad-log-enabled-checkbox" @@ -219,6 +222,12 @@ function main() { hidePromptMarker: true, insertMode: "both", }); + otherProtocolsCheckboxElement.checked = store.state.allowOtherProxyProtocols; + otherProtocolsCheckboxElement.addEventListener("change", () => { + store.state.allowOtherProxyProtocols = + otherProtocolsCheckboxElement.checked; + location.reload(); + }); // Ad log adLogEnabledCheckboxElement.checked = store.state.adLogEnabled; adLogEnabledCheckboxElement.addEventListener("change", () => { @@ -336,16 +345,18 @@ function isOptimizedProxyUrlAllowed(url: string): AllowedResult { return [false, "TTV LOL PRO v1 proxies are not compatible"]; } - const proxyInfo = getProxyInfoFromUrl(url); - if (proxyInfo.host.includes("/")) { - return [false, "Proxy URLs must not contain a path (e.g. '/path')"]; + if (url.includes("://")) { + const [protocol, urlWithoutProtocol] = url.split("://", 2); + if (!store.state.allowOtherProxyProtocols) { + return [false, "Proxy URLs must not contain a protocol (e.g. 'http://')"]; + } else if (!["http", "https", "socks", "socks4"].includes(protocol)) { + return [false, `'${protocol}' is not a supported protocol`]; + } + url = urlWithoutProtocol; } - try { - const host = url.substring(url.lastIndexOf("@") + 1, url.length); - new URL(`http://${host}`); // Throws if the host is invalid. - } catch { - return [false, `'${url}' is not a valid proxy URL`]; + if (url.includes("/")) { + return [false, "Proxy URLs must not contain a path (e.g. '/path')"]; } try { diff --git a/src/options/page.html b/src/options/page.html index d11724ce..44f67732 100644 --- a/src/options/page.html +++ b/src/options/page.html @@ -200,6 +200,36 @@

    Proxies

    >List of other proxies" discussion on TTV LOL PRO's GitHub repository. +

    +
      +
    • + + +
      + + By default, only HTTP proxies are allowed. Enabling this option + will allow the use of other protocols like HTTPS, SOCKS4, and + SOCKS5. + +
      + + To provide a protocol, use the format + protocol://hostname:port. Available protocols are + http, https, socks, and + socks4. + +
      + + ONLY ENABLE THIS OPTION IF YOU KNOW WHAT YOU ARE DOING. + +
    • +
    diff --git a/src/store/getDefaultState.ts b/src/store/getDefaultState.ts index ea99dc2f..3831f457 100644 --- a/src/store/getDefaultState.ts +++ b/src/store/getDefaultState.ts @@ -7,6 +7,7 @@ export default function getDefaultState() { adLog: [], adLogEnabled: true, adLogLastSent: 0, + allowOtherProxyProtocols: false, anonymousMode: true, chromiumProxyActive: false, dnsResponses: [], diff --git a/src/store/types.ts b/src/store/types.ts index f244c2d2..666554b7 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -10,6 +10,7 @@ export interface State { adLog: AdLogEntry[]; adLogEnabled: boolean; adLogLastSent: number; + allowOtherProxyProtocols: boolean; anonymousMode: boolean; chromiumProxyActive: boolean; dnsResponses: DnsResponse[]; diff --git a/src/types.ts b/src/types.ts index 86853f96..b8b45ea5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,19 +3,11 @@ export type KeyOfType = keyof { [P in keyof T as T[P] extends V ? P : never]: any; }; -// From https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md#proxy-server-schemes -export type ProxyScheme = - | "DIRECT" - | "PROXY" - | "HTTPS" - | "SOCKS" - | "SOCKS4" - | "SOCKS5" - | "QUIC"; +export type ProxyType = "direct" | "http" | "https" | "socks" | "socks4"; // From https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/proxy/ProxyInfo export interface ProxyInfo { - type: ProxyScheme; + type: ProxyType; host?: string; port?: number; username?: string; From 6df1cc763802b3563aadf2cc1d19d6de89a4dacb Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Fri, 7 Feb 2025 16:15:33 +0100 Subject: [PATCH 23/28] Improve code --- src/common/ts/proxyInfo.ts | 4 ++-- src/common/ts/proxySettings.ts | 2 +- src/options/options.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index 1e463491..1994f5da 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -14,9 +14,9 @@ export function getProxyInfoFromUrl( ): ProxyInfo & { host: string; port: number } { let type: ProxyType | undefined = undefined; if (url.includes("://")) { - const [protocol, urlWithoutProtocol] = url.split("://", 2); + const [protocol] = url.split("://", 1); type = protocol as ProxyType; - url = urlWithoutProtocol; + url = url.substring(protocol.length + 3, url.length); } const lastIndexOfAt = url.lastIndexOf("@"); diff --git a/src/common/ts/proxySettings.ts b/src/common/ts/proxySettings.ts index 39f3de5f..366e495b 100644 --- a/src/common/ts/proxySettings.ts +++ b/src/common/ts/proxySettings.ts @@ -15,8 +15,8 @@ const PROXY_TYPE_MAP: Readonly> = Object.freeze({ direct: "DIRECT", http: "PROXY", https: "HTTPS", - socks4: "SOCKS4", socks: "SOCKS5", + socks4: "SOCKS4", }); export function updateProxySettings(requestFilter?: ProxyRequestType[]) { diff --git a/src/options/options.ts b/src/options/options.ts index 75e4a38b..bee4b2ed 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -346,13 +346,13 @@ function isOptimizedProxyUrlAllowed(url: string): AllowedResult { } if (url.includes("://")) { - const [protocol, urlWithoutProtocol] = url.split("://", 2); + const [protocol] = url.split("://", 1); if (!store.state.allowOtherProxyProtocols) { return [false, "Proxy URLs must not contain a protocol (e.g. 'http://')"]; } else if (!["http", "https", "socks", "socks4"].includes(protocol)) { return [false, `'${protocol}' is not a supported protocol`]; } - url = urlWithoutProtocol; + url = url.substring(protocol.length + 3, url.length); } if (url.includes("/")) { From 2cba7c150921db7ce2d8ed437283175ba0aa900c Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 9 Feb 2025 15:12:29 +0100 Subject: [PATCH 24/28] Improve UX of "Allow other protocols" option --- src/common/ts/proxyInfo.ts | 2 +- src/options/options.ts | 95 +++++++++++++++++++------------------- src/options/page.html | 16 +++---- 3 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/common/ts/proxyInfo.ts b/src/common/ts/proxyInfo.ts index 1994f5da..b3a2ea83 100644 --- a/src/common/ts/proxyInfo.ts +++ b/src/common/ts/proxyInfo.ts @@ -27,7 +27,7 @@ export function getProxyInfoFromUrl( let port: number | undefined = undefined; if (lastIndexOfColon === -1) { host = hostname; - port = !type ? 3128 : DEFAULT_PORTS[type]; // Default port + port = type ? DEFAULT_PORTS[type] : 3128; // Default port } else { host = hostname.substring(0, lastIndexOfColon); port = Number(hostname.substring(lastIndexOfColon + 1, hostname.length)); diff --git a/src/options/options.ts b/src/options/options.ts index bee4b2ed..6965b515 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -28,7 +28,7 @@ type ListOptions = { getPromptPlaceholder(insertMode: InsertMode): string; isAddAllowed(text: string): AllowedResult; isEditAllowed(text: string): AllowedResult; - onEdit?(text: string): void; + onChange?(oldText: string | undefined, newText: string): void; focusPrompt: boolean; hidePromptMarker: boolean; insertMode: InsertMode; @@ -162,12 +162,6 @@ function main() { } return [true]; }, - isEditAllowed(text) { - if (!/^[a-z0-9_]+$/i.test(text)) { - return [false, `'${text}' is not a valid channel name`]; - } - return [true]; - }, }); whitelistSubscriptionsCheckboxElement.checked = store.state.whitelistChannelSubscriptions; @@ -183,50 +177,21 @@ function main() { if (store.state.optimizedProxiesEnabled) optimizedProxiesInputElement.checked = true; else normalProxiesInputElement.checked = true; - const onProxyTypeChange = () => { + const onProxyModeChange = () => { store.state.optimizedProxiesEnabled = optimizedProxiesInputElement.checked; if (isChromium && store.state.chromiumProxyActive) { updateProxySettings(); } updateProxyUsage(); }; - optimizedProxiesInputElement.addEventListener("change", onProxyTypeChange); - normalProxiesInputElement.addEventListener("change", onProxyTypeChange); - listInit(optimizedProxiesListElement, "optimizedProxies", { - getPromptPlaceholder: insertMode => { - if (insertMode == "prepend") return "Enter a proxy URL… (Primary)"; - return "Enter a proxy URL… (Fallback)"; - }, - isAddAllowed: isOptimizedProxyUrlAllowed, - isEditAllowed: isOptimizedProxyUrlAllowed, - onEdit() { - if (isChromium && store.state.chromiumProxyActive) { - updateProxySettings(); - } - }, - hidePromptMarker: true, - insertMode: "both", - }); - listInit(normalProxiesListElement, "normalProxies", { - getPromptPlaceholder: insertMode => { - if (insertMode == "prepend") return "Enter a proxy URL… (Primary)"; - return "Enter a proxy URL… (Fallback)"; - }, - isAddAllowed: isNormalProxyUrlAllowed, - isEditAllowed: isNormalProxyUrlAllowed, - onEdit() { - if (isChromium && store.state.chromiumProxyActive) { - updateProxySettings(); - } - }, - hidePromptMarker: true, - insertMode: "both", - }); + optimizedProxiesInputElement.addEventListener("change", onProxyModeChange); + normalProxiesInputElement.addEventListener("change", onProxyModeChange); + loadProxiesLists(); otherProtocolsCheckboxElement.checked = store.state.allowOtherProxyProtocols; otherProtocolsCheckboxElement.addEventListener("change", () => { store.state.allowOtherProxyProtocols = otherProtocolsCheckboxElement.checked; - location.reload(); + loadProxiesLists(); }); // Ad log adLogEnabledCheckboxElement.checked = store.state.adLogEnabled; @@ -313,6 +278,37 @@ function updateProxyUsage() { } } +function loadProxiesLists() { + listInit(optimizedProxiesListElement, "optimizedProxies", { + getPromptPlaceholder: insertMode => { + if (insertMode == "prepend") return "Enter a proxy URL… (Primary)"; + return "Enter a proxy URL… (Fallback)"; + }, + isAddAllowed: isOptimizedProxyUrlAllowed, + onChange() { + if (isChromium && store.state.chromiumProxyActive) { + updateProxySettings(); + } + }, + hidePromptMarker: true, + insertMode: "both", + }); + listInit(normalProxiesListElement, "normalProxies", { + getPromptPlaceholder: insertMode => { + if (insertMode == "prepend") return "Enter a proxy URL… (Primary)"; + return "Enter a proxy URL… (Fallback)"; + }, + isAddAllowed: isNormalProxyUrlAllowed, + onChange() { + if (isChromium && store.state.chromiumProxyActive) { + updateProxySettings(); + } + }, + hidePromptMarker: true, + insertMode: "both", + }); +} + function isOptimizedProxyUrlAllowed(url: string): AllowedResult { const urlLower = url.toLowerCase(); @@ -348,7 +344,10 @@ function isOptimizedProxyUrlAllowed(url: string): AllowedResult { if (url.includes("://")) { const [protocol] = url.split("://", 1); if (!store.state.allowOtherProxyProtocols) { - return [false, "Proxy URLs must not contain a protocol (e.g. 'http://')"]; + return [ + false, + "Proxy URLs are not allowed to contain a protocol (e.g. 'http://')", + ]; } else if (!["http", "https", "socks", "socks4"].includes(protocol)) { return [false, `'${protocol}' is not a supported protocol`]; } @@ -416,6 +415,7 @@ function listInit( storeKey: StoreStringArrayKey, options: Partial = {} ) { + listElement.innerHTML = ""; // Reset list element. const listOptions: ListOptions = { ...DEFAULT_LIST_OPTIONS, ...options }; for (const text of store.state[storeKey]) { _listAppend(listElement, storeKey, text, { @@ -475,18 +475,19 @@ function _listAppend( return console.error(`Item '${text}' not found in '${storeKey}' array`); const textInput = e.target as HTMLInputElement; + const oldText = text; const newText = textInput.value.trim(); // Remove item if text is empty. if (newText === "") { store.state[storeKey].splice(itemIndex, 1); listItem.remove(); - if (options.onEdit) options.onEdit(newText); + if (options.onChange) options.onChange(oldText, newText); return; } // Check if text is valid. - const [allowed, error] = options.isEditAllowed(newText); + const [allowed, error] = options.isAddAllowed(newText); if (!allowed) { - alert(error || "You cannot edit this item"); + alert(error || "You cannot add this item"); textInput.value = text; return; } @@ -495,7 +496,7 @@ function _listAppend( textInput.placeholder = options.getItemPlaceholder(newText); textInput.value = newText; // Update text in case it was trimmed. text = newText; // Update current text variable. - if (options.onEdit) options.onEdit(newText); + if (options.onChange) options.onChange(oldText, newText); }); listItem.append(textInput); @@ -550,7 +551,7 @@ function _listPrompt( if (options.insertMode === "prepend") newArray.unshift(text); else newArray.push(text); store.state[storeKey] = newArray; - if (options.onEdit) options.onEdit(text); + if (options.onChange) options.onChange(undefined, text); listItem.remove(); _listAppend(listElement, storeKey, text, options); diff --git a/src/options/page.html b/src/options/page.html index 44f67732..cae79625 100644 --- a/src/options/page.html +++ b/src/options/page.html @@ -209,24 +209,22 @@

    Proxies

    id="other-protocols-checkbox" /> + For advanced users only
    - By default, only HTTP proxies are allowed. Enabling this option - will allow the use of other protocols like HTTPS, SOCKS4, and - SOCKS5. + This option allows you to use protocols other than HTTP.
    - To provide a protocol, use the format - protocol://hostname:port. Available protocols are - http, https, socks, and - socks4. + Supported protocols are HTTPS (https://), SOCKS4 + (socks4://), and SOCKS5 (socks://).
    - ONLY ENABLE THIS OPTION IF YOU KNOW WHAT YOU ARE DOING. + To provide a protocol, use the format + protocol://hostname:port. From 21fc889cbd1781b5badeaeb5d0f4996087c9375a Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 9 Feb 2025 15:12:36 +0100 Subject: [PATCH 25/28] Upgrade dependencies --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3a5ffe09..7f91ec60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@parcel/config-webextension": "^2.13.3", - "@types/chrome": "^0.0.301", + "@types/chrome": "^0.0.304", "@types/node": "^22.13.1", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", @@ -2079,9 +2079,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.0.301", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.301.tgz", - "integrity": "sha512-BljW7InXXOfDYr4nG79y5lnaklrZ0gmeTwCUkuCXK2+69dHnZIrg13KhXJE/HrcFUmy8NG/EK+RTGScsh/Hbiw==", + "version": "0.0.304", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.304.tgz", + "integrity": "sha512-ms9CLILU+FEMK7gcmgz/Mtn2E81YQWiMIzCFF8ktp98EVNIIfoqaDTD4+ailOCq1sGjbnEmfJxQ1FAsQtk5M3A==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 8a790105..42dec359 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@parcel/config-webextension": "^2.13.3", - "@types/chrome": "^0.0.301", + "@types/chrome": "^0.0.304", "@types/node": "^22.13.1", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", From 4693ceb9a50a5ad24eaf3ffb067de1970e915a23 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 9 Feb 2025 16:21:05 +0100 Subject: [PATCH 26/28] Fix export of `allowOtherProxyProtocols` setting --- src/options/options.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/options/options.ts b/src/options/options.ts index 6965b515..1988af39 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -572,6 +572,7 @@ function _listPrompt( exportButtonElement.addEventListener("click", () => { const state: Partial = { adLogEnabled: store.state.adLogEnabled, + allowOtherProxyProtocols: store.state.allowOtherProxyProtocols, anonymousMode: store.state.anonymousMode, normalProxies: store.state.normalProxies, optimizedProxies: store.state.optimizedProxies, From e7f00f4e561821a32a50f815b95cb6e41bd48d9f Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Sun, 9 Feb 2025 16:24:25 +0100 Subject: [PATCH 27/28] Remove extra dot to avoid format confusion --- src/options/page.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options/page.html b/src/options/page.html index cae79625..d878d261 100644 --- a/src/options/page.html +++ b/src/options/page.html @@ -224,7 +224,7 @@

    Proxies


    To provide a protocol, use the format - protocol://hostname:port. + protocol://hostname:port From 9d86b37d0005b1e52a4e1b7b9ddbc1bda7bc31f1 Mon Sep 17 00:00:00 2001 From: Younes Aassila <47226184+younesaassila@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:04:46 +0100 Subject: [PATCH 28/28] Upgrade dependencies --- package-lock.json | 124 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f91ec60..b0640957 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "devDependencies": { "@parcel/config-webextension": "^2.13.3", "@types/chrome": "^0.0.304", - "@types/node": "^22.13.1", + "@types/node": "^22.13.2", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "parcel": "^2.13.3", @@ -1833,9 +1833,9 @@ } }, "node_modules/@swc/core": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.12.tgz", - "integrity": "sha512-+iUL0PYpPm6N9AdV1wvafakvCqFegQus1aoEDxgFsv3/uNVNIyRaupf/v/Zkp5hbep2EzhtoJR0aiJIzDbXWHg==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.16.tgz", + "integrity": "sha512-nOINg/OUcZazCW7B55QV2/UB8QAqz9FYe4+z229+4RYboBTZ102K7ebOEjY5sKn59JgAkhjZTz+5BKmXpDFopw==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -1851,16 +1851,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.10.12", - "@swc/core-darwin-x64": "1.10.12", - "@swc/core-linux-arm-gnueabihf": "1.10.12", - "@swc/core-linux-arm64-gnu": "1.10.12", - "@swc/core-linux-arm64-musl": "1.10.12", - "@swc/core-linux-x64-gnu": "1.10.12", - "@swc/core-linux-x64-musl": "1.10.12", - "@swc/core-win32-arm64-msvc": "1.10.12", - "@swc/core-win32-ia32-msvc": "1.10.12", - "@swc/core-win32-x64-msvc": "1.10.12" + "@swc/core-darwin-arm64": "1.10.16", + "@swc/core-darwin-x64": "1.10.16", + "@swc/core-linux-arm-gnueabihf": "1.10.16", + "@swc/core-linux-arm64-gnu": "1.10.16", + "@swc/core-linux-arm64-musl": "1.10.16", + "@swc/core-linux-x64-gnu": "1.10.16", + "@swc/core-linux-x64-musl": "1.10.16", + "@swc/core-win32-arm64-msvc": "1.10.16", + "@swc/core-win32-ia32-msvc": "1.10.16", + "@swc/core-win32-x64-msvc": "1.10.16" }, "peerDependencies": { "@swc/helpers": "*" @@ -1872,9 +1872,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.12.tgz", - "integrity": "sha512-pOANQegUTAriW7jq3SSMZGM5l89yLVMs48R0F2UG6UZsH04SiViCnDctOGlA/Sa++25C+rL9MGMYM1jDLylBbg==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.16.tgz", + "integrity": "sha512-iikIxwqCQ4Bvz79vJ4ELh26efPf1u5D9TFdmXSJUBs7C3mmMHvk5zyWD9A9cTowXiW6WHs2gE58U1R9HOTTIcg==", "cpu": [ "arm64" ], @@ -1889,9 +1889,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.12.tgz", - "integrity": "sha512-m4kbpIDDsN1FrwfNQMU+FTrss356xsXvatLbearwR+V0lqOkjLBP0VmRvQfHEg+uy13VPyrT9gj4HLoztlci7w==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.16.tgz", + "integrity": "sha512-R2Eb9aktWd62vPfW9H/c/OaQ0e94iURibBo4uzUUcgxNNmB4+wb6piKbHxGdr/5bEsT+vJ1lwZFSRzfb45E7DA==", "cpu": [ "x64" ], @@ -1906,9 +1906,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.12.tgz", - "integrity": "sha512-OY9LcupgqEu8zVK+rJPes6LDJJwPDmwaShU96beTaxX2K6VrXbpwm5WbPS/8FfQTsmpnuA7dCcMPUKhNgmzTrQ==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.16.tgz", + "integrity": "sha512-mkqN3HBAMnuiSGZ/k2utScuH8rAPshvNj0T1LjBWon+X9DkMNHSA+aMLdWsy0yZKF1zjOPc4L3Uq2l2wzhUlzA==", "cpu": [ "arm" ], @@ -1923,9 +1923,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.12.tgz", - "integrity": "sha512-nJD587rO0N4y4VZszz3xzVr7JIiCzSMhEMWnPjuh+xmPxDBz0Qccpr8xCr1cSxpl1uY7ERkqAGlKr6CwoV5kVg==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.16.tgz", + "integrity": "sha512-PH/+q/L5nVZJ91CU07CL6Q9Whs6iR6nneMZMAgtVF9Ix8ST0cWVItdUhs6D38kFklCFhaOrpHhS01HlMJ72vWw==", "cpu": [ "arm64" ], @@ -1940,9 +1940,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.12.tgz", - "integrity": "sha512-oqhSmV+XauSf0C//MoQnVErNUB/5OzmSiUzuazyLsD5pwqKNN+leC3JtRQ/QVzaCpr65jv9bKexT9+I2Tt3xDw==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.16.tgz", + "integrity": "sha512-1169+C9XbydKKc6Ec1XZxTGKtHjZHDIFn0r+Nqp/QSVwkORrOY1Vz2Hdu7tn/lWMg36ZkGePS+LnnyV67s/7yg==", "cpu": [ "arm64" ], @@ -1957,9 +1957,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.12.tgz", - "integrity": "sha512-XldSIHyjD7m1Gh+/8rxV3Ok711ENLI420CU2EGEqSe3VSGZ7pHJvJn9ZFbYpWhsLxPqBYMFjp3Qw+J6OXCPXCA==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.16.tgz", + "integrity": "sha512-n2rV0XwkjoHn4MDJmpYp5RBrnyi94/6GsJVpbn6f+/eqSrZn3mh3dT7pdZc9zCN1Qp9eDHo+uI6e/wgvbL22uA==", "cpu": [ "x64" ], @@ -1974,9 +1974,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.12.tgz", - "integrity": "sha512-wvPXzJxzPgTqhyp1UskOx1hRTtdWxlyFD1cGWOxgLsMik0V9xKRgqKnMPv16Nk7L9xl6quQ6DuUHj9ID7L3oVw==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.16.tgz", + "integrity": "sha512-EevCpwreBrkPrJjQVIbiM81lK42ukNNSlBmrSRxxbx2V9VGmOd5qxX0cJBn0TRRSLIPi62BuMS76F9iYjqsjgg==", "cpu": [ "x64" ], @@ -1991,9 +1991,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.12.tgz", - "integrity": "sha512-TUYzWuu1O7uyIcRfxdm6Wh1u+gNnrW5M1DUgDOGZLsyQzgc2Zjwfh2llLhuAIilvCVg5QiGbJlpibRYJ/8QGsg==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.16.tgz", + "integrity": "sha512-BvE7RWAnKJeELVQWLok6env5I4GUVBTZSvaSN/VPgxnTjF+4PsTeQptYx0xCYhp5QCv68wWYsBnZKuPDS+SBsw==", "cpu": [ "arm64" ], @@ -2008,9 +2008,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.12.tgz", - "integrity": "sha512-4Qrw+0Xt+Fe2rz4OJ/dEPMeUf/rtuFWWAj/e0vL7J5laUHirzxawLRE5DCJLQTarOiYR6mWnmadt9o3EKzV6Xg==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.16.tgz", + "integrity": "sha512-7Jf/7AeCgbLR/JsQgMJuacHIq4Jeie3knf6+mXxn8aCvRypsOTIEu0eh7j24SolOboxK1ijqJ86GyN1VA2Rebg==", "cpu": [ "ia32" ], @@ -2025,9 +2025,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.10.12", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.12.tgz", - "integrity": "sha512-YiloZXLW7rUxJpALwHXaGjVaAEn+ChoblG7/3esque+Y7QCyheoBUJp2DVM1EeVA43jBfZ8tvYF0liWd9Tpz1A==", + "version": "1.10.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.16.tgz", + "integrity": "sha512-p0blVm0R8bjaTtmW+FoPmLxLSQdRNbqhuWcR/8g80OzMSkka9mk5/J3kn/5JRVWh+MaR9LHRHZc1Q1L8zan13g==", "cpu": [ "x64" ], @@ -2114,9 +2114,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "version": "22.13.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.2.tgz", + "integrity": "sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg==", "dev": true, "license": "MIT", "dependencies": { @@ -2311,9 +2311,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001696", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", - "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", + "version": "1.0.30001699", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", + "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", "dev": true, "funding": [ { @@ -2642,9 +2642,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", - "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", + "version": "1.5.98", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.98.tgz", + "integrity": "sha512-bI/LbtRBxU2GzK7KK5xxFd2y9Lf9XguHooPYbcXWy6wUoT8NMnffsvRhPmSeUHLSDKAEtKuTaEtK4Ms15zkIEA==", "dev": true, "license": "ISC" }, @@ -2892,9 +2892,9 @@ "license": "BSD-3-Clause" }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3651,9 +3651,9 @@ } }, "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "dev": true, "funding": [ { @@ -4022,9 +4022,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 42dec359..5f7923c3 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "devDependencies": { "@parcel/config-webextension": "^2.13.3", "@types/chrome": "^0.0.304", - "@types/node": "^22.13.1", + "@types/node": "^22.13.2", "@types/webextension-polyfill": "^0.12.1", "buffer": "^6.0.3", "parcel": "^2.13.3",