From c9ff17558dc23f2b305d061bd40e5c4dc9db413d Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 12:18:15 +0700
Subject: [PATCH 01/26] prettier formatting, add manifest url in console.log
---
.prettierignore | 3 +
.prettierrc.json | 8 +
background.js | 130 +-
content.js | 115 +-
frontend/eslint.config.js | 57 +-
frontend/index.html | 18 +-
frontend/package-lock.json | 6810 +++++++++++++-------------
frontend/package.json | 56 +-
frontend/src/App.jsx | 121 +-
frontend/src/components/results.jsx | 266 +-
frontend/src/components/settings.jsx | 263 +-
frontend/src/components/sidenav.jsx | 77 +-
frontend/src/components/topnav.jsx | 145 +-
frontend/src/index.css | 14 +-
frontend/src/main.jsx | 18 +-
frontend/vite.config.js | 12 +-
inject.js | 1001 ++--
manifest.json | 76 +-
18 files changed, 4754 insertions(+), 4436 deletions(-)
create mode 100644 .prettierignore
create mode 100644 .prettierrc.json
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..474c34a
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+react/
+frontend/dist/
+frontend/src/assets/
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..eb0d496
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+ "trailingComma": "es5",
+ "tabWidth": 4,
+ "semi": true,
+ "singleQuote": false,
+ "useTabs": false,
+ "printWidth": 100
+}
diff --git a/background.js b/background.js
index a04773a..331927d 100644
--- a/background.js
+++ b/background.js
@@ -1,84 +1,84 @@
// Open popout window when the extension icon is clicked
chrome.browserAction.onClicked.addListener(() => {
- chrome.windows.create({
- url: chrome.runtime.getURL("react/index.html"),
- type: "popup", // opens as a floating window
- width: 800,
- height: 600
- });
+ chrome.windows.create({
+ url: chrome.runtime.getURL("react/index.html"),
+ type: "popup", // opens as a floating window
+ width: 800,
+ height: 600,
+ });
});
// Listen for messages and store data in chrome.storage.local
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
- const { type, data } = message;
+ const { type, data } = message;
- switch (type) {
- case "DRM_TYPE":
- console.log("DRM Type:", data);
- chrome.storage.local.set({ drmType: data });
- break;
+ switch (type) {
+ case "DRM_TYPE":
+ console.log("DRM Type:", data);
+ chrome.storage.local.set({ drmType: data });
+ break;
- case "PSSH_DATA":
- console.log("Storing PSSH:", data);
- chrome.storage.local.set({ latestPSSH: data });
- break;
+ case "PSSH_DATA":
+ console.log("Storing PSSH:", data);
+ chrome.storage.local.set({ latestPSSH: data });
+ break;
- case "KEYS_DATA":
- console.log("Storing Decryption Keys:", data);
- chrome.storage.local.set({ latestKeys: data });
- break;
-
- case "LICENSE_URL":
- console.log("Storling License URL " + data);
- chrome.storage.local.set({licenseURL: data});
- break;
+ case "KEYS_DATA":
+ console.log("Storing Decryption Keys:", data);
+ chrome.storage.local.set({ latestKeys: data });
+ break;
- default:
- console.warn("Unknown message type received:", type);
- }
+ case "LICENSE_URL":
+ console.log("Storling License URL " + data);
+ chrome.storage.local.set({ licenseURL: data });
+ break;
+
+ default:
+ console.warn("Unknown message type received:", type);
+ }
});
// Set initial config and injection type on install
chrome.runtime.onInstalled.addListener((details) => {
- if (details.reason === "install") {
- chrome.storage.local.set({ valid_config: false }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error setting valid_config:", chrome.runtime.lastError);
- } else {
- console.log("valid_config set to false on first install.");
- }
- });
+ if (details.reason === "install") {
+ chrome.storage.local.set({ valid_config: false }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting valid_config:", chrome.runtime.lastError);
+ } else {
+ console.log("valid_config set to false on first install.");
+ }
+ });
- chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error setting Injection Type:", chrome.runtime.lastError);
- } else {
- console.log("Injection type set to LICENSE on first install.");
- }
- });
+ chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting Injection Type:", chrome.runtime.lastError);
+ } else {
+ console.log("Injection type set to LICENSE on first install.");
+ }
+ });
- chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error setting DRM Override type:", chrome.runtime.lastError);
- } else {
- console.log("DRM Override type set to DISABLED on first install.");
- }
- });
+ chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting DRM Override type:", chrome.runtime.lastError);
+ } else {
+ console.log("DRM Override type set to DISABLED on first install.");
+ }
+ });
- chrome.storage.local.set({ cdrm_instance: null }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error setting CDRM instance:", chrome.runtime.lastError);
- } else {
- console.log("CDRM instance set to null.");
- }
- });
+ chrome.storage.local.set({ cdrm_instance: null }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting CDRM instance:", chrome.runtime.lastError);
+ } else {
+ console.log("CDRM instance set to null.");
+ }
+ });
- chrome.storage.local.set({ cdrm_api_key: null }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
- } else {
- console.log("CDRM API Key set.");
- }
- });
- }
+ chrome.storage.local.set({ cdrm_api_key: null }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
+ } else {
+ console.log("CDRM API Key set.");
+ }
+ });
+ }
});
diff --git a/content.js b/content.js
index 31a8e53..55b7891 100644
--- a/content.js
+++ b/content.js
@@ -1,67 +1,96 @@
// Inject `inject.js` into the page context
(function injectScript() {
- const script = document.createElement('script');
- script.src = chrome.runtime.getURL('inject.js');
- script.type = 'text/javascript';
- script.onload = () => script.remove(); // Clean up
- // Inject directly into or
- (document.documentElement || document.head || document.body).appendChild(script);
+ const script = document.createElement("script");
+ script.src = chrome.runtime.getURL("inject.js");
+ script.type = "text/javascript";
+ script.onload = () => script.remove(); // Clean up
+ // Inject directly into or
+ (document.documentElement || document.head || document.body).appendChild(script);
})();
// Listen for messages from the injected script
-window.addEventListener("message", function(event) {
+window.addEventListener("message", function (event) {
if (event.source !== window) return;
- if (["__DRM_TYPE__", "__PSSH_DATA__", "__KEYS_DATA__", "__LICENSE_URL__"].includes(event.data?.type)) {
+ if (
+ ["__DRM_TYPE__", "__PSSH_DATA__", "__KEYS_DATA__", "__LICENSE_URL__"].includes(
+ event.data?.type
+ )
+ ) {
chrome.runtime.sendMessage({
type: event.data.type.replace("__", "").replace("__", ""),
- data: event.data.data
+ data: event.data.data,
});
}
if (event.data.type === "__GET_CDM_DEVICES__") {
+ chrome.storage.local.get(["widevine_device", "playready_device"], (result) => {
+ const widevine_device = result.widevine_device || null;
+ const playready_device = result.playready_device || null;
- chrome.storage.local.get(["widevine_device", "playready_device"], (result) => {
- const widevine_device = result.widevine_device || null;
- const playready_device = result.playready_device || null;
-
- window.postMessage(
- {
- type: "__CDM_DEVICES__",
- widevine_device,
- playready_device
- },
- "*"
- );
- });
+ window.postMessage(
+ {
+ type: "__CDM_DEVICES__",
+ widevine_device,
+ playready_device,
+ },
+ "*"
+ );
+ });
}
if (event.data.type === "__GET_INJECTION_TYPE__") {
+ chrome.storage.local.get("injection_type", (result) => {
+ const injectionType = result.injection_type || "LICENSE";
- chrome.storage.local.get("injection_type", (result) => {
- const injectionType = result.injection_type || "LICENSE";
-
- window.postMessage(
- {
- type: "__INJECTION_TYPE__",
- injectionType
- },
- "*"
- );
- });
+ window.postMessage(
+ {
+ type: "__INJECTION_TYPE__",
+ injectionType,
+ },
+ "*"
+ );
+ });
}
+
if (event.data.type === "__GET_DRM_OVERRIDE__") {
+ chrome.storage.local.get("drm_override", (result) => {
+ const drmOverride = result.drm_override || "DISABLED";
- chrome.storage.local.get("drm_override", (result) => {
- const drmOverride = result.drm_override || "DISABLED";
+ window.postMessage(
+ {
+ type: "__DRM_OVERRIDE__",
+ drmOverride,
+ },
+ "*"
+ );
+ });
+ }
- window.postMessage(
- {
- type: "__DRM_OVERRIDE__",
- drmOverride
- },
- "*"
- );
- });
+ // Manifest header and URL
+
+ const seenManifestUrls = new Set();
+
+ if (event.data?.type === "__MANIFEST_URL__") {
+ const url = event.data.data;
+ if (seenManifestUrls.has(url)) return;
+ seenManifestUrls.add(url);
+ console.log("✅ [Content] Unique manifest URL:", url);
+
+ chrome.runtime.sendMessage({
+ type: "MANIFEST_URL_FOUND",
+ data: url,
+ });
+ }
+
+ if (event.data?.type === "__MANIFEST_HEADERS__") {
+ const { url, headers } = event.data;
+ console.log("[Content.js] Manifest Headers:", url, headers);
+
+ chrome.runtime.sendMessage({
+ type: "MANIFEST_HEADERS",
+ url,
+ headers,
+ });
}
});
diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js
index ec2b712..ab358f6 100644
--- a/frontend/eslint.config.js
+++ b/frontend/eslint.config.js
@@ -1,33 +1,30 @@
-import js from '@eslint/js'
-import globals from 'globals'
-import reactHooks from 'eslint-plugin-react-hooks'
-import reactRefresh from 'eslint-plugin-react-refresh'
+import js from "@eslint/js";
+import globals from "globals";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
export default [
- { ignores: ['dist'] },
- {
- files: ['**/*.{js,jsx}'],
- languageOptions: {
- ecmaVersion: 2020,
- globals: globals.browser,
- parserOptions: {
- ecmaVersion: 'latest',
- ecmaFeatures: { jsx: true },
- sourceType: 'module',
- },
+ { ignores: ["dist"] },
+ {
+ files: ["**/*.{js,jsx}"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ parserOptions: {
+ ecmaVersion: "latest",
+ ecmaFeatures: { jsx: true },
+ sourceType: "module",
+ },
+ },
+ plugins: {
+ "react-hooks": reactHooks,
+ "react-refresh": reactRefresh,
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ ...reactHooks.configs.recommended.rules,
+ "no-unused-vars": ["error", { varsIgnorePattern: "^[A-Z_]" }],
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
+ },
},
- plugins: {
- 'react-hooks': reactHooks,
- 'react-refresh': reactRefresh,
- },
- rules: {
- ...js.configs.recommended.rules,
- ...reactHooks.configs.recommended.rules,
- 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
- 'react-refresh/only-export-components': [
- 'warn',
- { allowConstantExport: true },
- ],
- },
- },
-]
+];
diff --git a/frontend/index.html b/frontend/index.html
index 788ba95..e830ac7 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,12 +1,12 @@
-
-
-
- CDRM Decryption Extension
-
-
-
-
-
+
+
+
+ CDRM Decryption Extension
+
+
+
+
+
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 98c30eb..39b3ac5 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,3411 +1,3411 @@
{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "frontend",
- "version": "0.0.0",
- "dependencies": {
- "@tailwindcss/vite": "^4.1.7",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-router-dom": "^7.6.1",
- "tailwindcss": "^4.1.7"
- },
- "devDependencies": {
- "@eslint/js": "^9.25.0",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "@vitejs/plugin-react": "^4.4.1",
- "eslint": "^9.25.0",
- "eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.19",
- "globals": "^16.0.0",
- "vite": "^6.3.5"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
- "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.27.1",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz",
- "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
- "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.27.1",
- "@babel/helper-compilation-targets": "^7.27.1",
- "@babel/helper-module-transforms": "^7.27.1",
- "@babel/helpers": "^7.27.1",
- "@babel/parser": "^7.27.1",
- "@babel/template": "^7.27.1",
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
- "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.27.1",
- "@babel/types": "^7.27.1",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
- "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.27.2",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
- "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
- "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1",
- "@babel/traverse": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
- "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
- "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
- "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
- "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.1"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
- "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
- "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
- "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/parser": "^7.27.2",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
- "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.27.1",
- "@babel/parser": "^7.27.1",
- "@babel/template": "^7.27.1",
- "@babel/types": "^7.27.1",
- "debug": "^4.3.1",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse/node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
- "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
- "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
- "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
- "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
- "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
- "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
- "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
- "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
- "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
- "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
- "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
- "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
- "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
- "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
- "cpu": [
- "mips64el"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
- "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
- "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
- "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
- "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
- "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
- "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
- "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
- "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
- "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
- "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
- "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
- "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
- "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
- "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/config-array": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
- "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/object-schema": "^2.1.6",
- "debug": "^4.3.1",
- "minimatch": "^3.1.2"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/config-helpers": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
- "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/core": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
- "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@types/json-schema": "^7.0.15"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/eslintrc": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
- "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^10.0.1",
- "globals": "^14.0.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@eslint/js": {
- "version": "9.27.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
- "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- }
- },
- "node_modules/@eslint/object-schema": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
- "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/plugin-kit": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
- "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^0.14.0",
- "levn": "^0.4.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@humanfs/core": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
- "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/@humanfs/node": {
- "version": "0.16.6",
- "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
- "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@humanfs/core": "^0.19.1",
- "@humanwhocodes/retry": "^0.3.0"
- },
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
- "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=12.22"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/retry": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
- "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@isaacs/fs-minipass": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
- "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^7.0.4"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
- "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz",
- "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz",
- "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz",
- "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz",
- "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz",
- "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz",
- "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz",
- "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz",
- "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz",
- "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz",
- "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz",
- "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==",
- "cpu": [
- "loong64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz",
- "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==",
- "cpu": [
- "ppc64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz",
- "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz",
- "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==",
- "cpu": [
- "riscv64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz",
- "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==",
- "cpu": [
- "s390x"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz",
- "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz",
- "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz",
- "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz",
- "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==",
- "cpu": [
- "ia32"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz",
- "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
- "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
- "license": "MIT",
- "dependencies": {
- "@ampproject/remapping": "^2.3.0",
- "enhanced-resolve": "^5.18.1",
- "jiti": "^2.4.2",
- "lightningcss": "1.30.1",
- "magic-string": "^0.30.17",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.1.7"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
- "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.4",
- "tar": "^7.4.3"
- },
- "engines": {
- "node": ">= 10"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.1.7",
- "@tailwindcss/oxide-darwin-arm64": "4.1.7",
- "@tailwindcss/oxide-darwin-x64": "4.1.7",
- "@tailwindcss/oxide-freebsd-x64": "4.1.7",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
- "@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
- "@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
- "@tailwindcss/oxide-linux-x64-musl": "4.1.7",
- "@tailwindcss/oxide-wasm32-wasi": "4.1.7",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
- "@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
- }
- },
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
- "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
- "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
- "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
- "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
- "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
- "cpu": [
- "arm"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
- "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
- "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
- "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
- "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
- "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
- "cpu": [
- "wasm32"
- ],
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.4.3",
- "@emnapi/runtime": "^1.4.3",
- "@emnapi/wasi-threads": "^1.0.2",
- "@napi-rs/wasm-runtime": "^0.2.9",
- "@tybys/wasm-util": "^0.9.0",
- "tslib": "^2.8.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
- "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
- "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz",
- "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.1.7",
- "@tailwindcss/oxide": "4.1.7",
- "tailwindcss": "4.1.7"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
- "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.20.7"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
- "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
- "license": "MIT"
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/react": {
- "version": "19.1.4",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz",
- "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.0.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "19.1.5",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz",
- "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^19.0.0"
- }
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz",
- "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.26.10",
- "@babel/plugin-transform-react-jsx-self": "^7.25.9",
- "@babel/plugin-transform-react-jsx-source": "^7.25.9",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.17.0"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
- }
- },
- "node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/browserslist": {
- "version": "4.24.5",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
- "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
+ "name": "frontend",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "frontend",
+ "version": "0.0.0",
+ "dependencies": {
+ "@tailwindcss/vite": "^4.1.7",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.6.1",
+ "tailwindcss": "^4.1.7"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.25.0",
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^4.4.1",
+ "eslint": "^9.25.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.19",
+ "globals": "^16.0.0",
+ "vite": "^6.3.5"
+ }
},
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
},
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz",
+ "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
+ "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.1",
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helpers": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/template": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
+ "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
+ "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
+ "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
+ "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.27.1"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
+ "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.1",
+ "@babel/parser": "^7.27.1",
+ "@babel/template": "^7.27.1",
+ "@babel/types": "^7.27.1",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
+ "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
+ "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
+ "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
+ "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
+ "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
+ "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
+ "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
+ "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
+ "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
+ "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
+ "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
+ "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
+ "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
+ "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
+ "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
+ "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
+ "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
+ "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
+ "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
+ "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
+ "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
+ "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
+ "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
+ "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
+ "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
+ "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
+ "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.27.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
+ "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
+ "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.14.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz",
+ "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz",
+ "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz",
+ "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz",
+ "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz",
+ "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz",
+ "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz",
+ "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz",
+ "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz",
+ "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz",
+ "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz",
+ "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz",
+ "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz",
+ "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz",
+ "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz",
+ "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz",
+ "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz",
+ "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz",
+ "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz",
+ "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz",
+ "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
+ "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "enhanced-resolve": "^5.18.1",
+ "jiti": "^2.4.2",
+ "lightningcss": "1.30.1",
+ "magic-string": "^0.30.17",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.7"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
+ "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.4",
+ "tar": "^7.4.3"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.7",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.7",
+ "@tailwindcss/oxide-darwin-x64": "4.1.7",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.7",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.7",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.7",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
+ "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
+ "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
+ "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
+ "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
+ "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
+ "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
+ "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
+ "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
+ "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
+ "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@emnapi/wasi-threads": "^1.0.2",
+ "@napi-rs/wasm-runtime": "^0.2.9",
+ "@tybys/wasm-util": "^0.9.0",
+ "tslib": "^2.8.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
+ "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
+ "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz",
+ "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.1.7",
+ "@tailwindcss/oxide": "4.1.7",
+ "tailwindcss": "4.1.7"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+ "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
+ "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "19.1.4",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz",
+ "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.1.5",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz",
+ "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.0.0"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz",
+ "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.26.10",
+ "@babel/plugin-transform-react-jsx-self": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-source": "^7.25.9",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
+ "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001716",
+ "electron-to-chromium": "^1.5.149",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001718",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
+ "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+ "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.155",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz",
+ "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.18.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
+ "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
+ "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.4",
+ "@esbuild/android-arm": "0.25.4",
+ "@esbuild/android-arm64": "0.25.4",
+ "@esbuild/android-x64": "0.25.4",
+ "@esbuild/darwin-arm64": "0.25.4",
+ "@esbuild/darwin-x64": "0.25.4",
+ "@esbuild/freebsd-arm64": "0.25.4",
+ "@esbuild/freebsd-x64": "0.25.4",
+ "@esbuild/linux-arm": "0.25.4",
+ "@esbuild/linux-arm64": "0.25.4",
+ "@esbuild/linux-ia32": "0.25.4",
+ "@esbuild/linux-loong64": "0.25.4",
+ "@esbuild/linux-mips64el": "0.25.4",
+ "@esbuild/linux-ppc64": "0.25.4",
+ "@esbuild/linux-riscv64": "0.25.4",
+ "@esbuild/linux-s390x": "0.25.4",
+ "@esbuild/linux-x64": "0.25.4",
+ "@esbuild/netbsd-arm64": "0.25.4",
+ "@esbuild/netbsd-x64": "0.25.4",
+ "@esbuild/openbsd-arm64": "0.25.4",
+ "@esbuild/openbsd-x64": "0.25.4",
+ "@esbuild/sunos-x64": "0.25.4",
+ "@esbuild/win32-arm64": "0.25.4",
+ "@esbuild/win32-ia32": "0.25.4",
+ "@esbuild/win32-x64": "0.25.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.27.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
+ "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.20.0",
+ "@eslint/config-helpers": "^0.2.1",
+ "@eslint/core": "^0.14.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.27.0",
+ "@eslint/plugin-kit": "^0.3.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.3.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.20",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz",
+ "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=8.40"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
+ "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+ "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.4.4",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
+ "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "16.1.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
+ "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "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": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jiti": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
+ "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-darwin-arm64": "1.30.1",
+ "lightningcss-darwin-x64": "1.30.1",
+ "lightningcss-freebsd-x64": "1.30.1",
+ "lightningcss-linux-arm-gnueabihf": "1.30.1",
+ "lightningcss-linux-arm64-gnu": "1.30.1",
+ "lightningcss-linux-arm64-musl": "1.30.1",
+ "lightningcss-linux-x64-gnu": "1.30.1",
+ "lightningcss-linux-x64-musl": "1.30.1",
+ "lightningcss-win32-arm64-msvc": "1.30.1",
+ "lightningcss-win32-x64-msvc": "1.30.1"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
+ "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
+ "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
+ "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
+ "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
+ "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
+ "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
+ "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
+ "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
+ "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
+ "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
+ "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "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/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
+ "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.8",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
+ "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.0"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+ "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.1.tgz",
+ "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.1.tgz",
+ "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.6.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.40.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz",
+ "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.7"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.40.2",
+ "@rollup/rollup-android-arm64": "4.40.2",
+ "@rollup/rollup-darwin-arm64": "4.40.2",
+ "@rollup/rollup-darwin-x64": "4.40.2",
+ "@rollup/rollup-freebsd-arm64": "4.40.2",
+ "@rollup/rollup-freebsd-x64": "4.40.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.40.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.40.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.40.2",
+ "@rollup/rollup-linux-arm64-musl": "4.40.2",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.40.2",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.40.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.40.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.40.2",
+ "@rollup/rollup-linux-x64-gnu": "4.40.2",
+ "@rollup/rollup-linux-x64-musl": "4.40.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.40.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.40.2",
+ "@rollup/rollup-win32-x64-msvc": "4.40.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
+ "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
+ "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
+ "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
+ "license": "ISC",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.0.1",
+ "mkdirp": "^3.0.1",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tar/node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
+ "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
+ "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
- ],
- "license": "MIT",
- "dependencies": {
- "caniuse-lite": "^1.0.30001716",
- "electron-to-chromium": "^1.5.149",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001718",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
- "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chownr": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
- "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
- "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/detect-libc": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
- "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.155",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz",
- "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/enhanced-resolve": {
- "version": "5.18.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
- "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.2.0"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/esbuild": {
- "version": "0.25.4",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
- "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.4",
- "@esbuild/android-arm": "0.25.4",
- "@esbuild/android-arm64": "0.25.4",
- "@esbuild/android-x64": "0.25.4",
- "@esbuild/darwin-arm64": "0.25.4",
- "@esbuild/darwin-x64": "0.25.4",
- "@esbuild/freebsd-arm64": "0.25.4",
- "@esbuild/freebsd-x64": "0.25.4",
- "@esbuild/linux-arm": "0.25.4",
- "@esbuild/linux-arm64": "0.25.4",
- "@esbuild/linux-ia32": "0.25.4",
- "@esbuild/linux-loong64": "0.25.4",
- "@esbuild/linux-mips64el": "0.25.4",
- "@esbuild/linux-ppc64": "0.25.4",
- "@esbuild/linux-riscv64": "0.25.4",
- "@esbuild/linux-s390x": "0.25.4",
- "@esbuild/linux-x64": "0.25.4",
- "@esbuild/netbsd-arm64": "0.25.4",
- "@esbuild/netbsd-x64": "0.25.4",
- "@esbuild/openbsd-arm64": "0.25.4",
- "@esbuild/openbsd-x64": "0.25.4",
- "@esbuild/sunos-x64": "0.25.4",
- "@esbuild/win32-arm64": "0.25.4",
- "@esbuild/win32-ia32": "0.25.4",
- "@esbuild/win32-x64": "0.25.4"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "9.27.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
- "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.20.0",
- "@eslint/config-helpers": "^0.2.1",
- "@eslint/core": "^0.14.0",
- "@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.27.0",
- "@eslint/plugin-kit": "^0.3.1",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "@types/json-schema": "^7.0.15",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.3.0",
- "eslint-visitor-keys": "^4.2.0",
- "espree": "^10.3.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-react-hooks": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
- "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
- }
- },
- "node_modules/eslint-plugin-react-refresh": {
- "version": "0.4.20",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz",
- "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "eslint": ">=8.40"
- }
- },
- "node_modules/eslint-scope": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
- "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
- "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/espree": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
- "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.14.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fdir": {
- "version": "6.4.4",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
- "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
- "license": "MIT",
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globals": {
- "version": "16.1.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
- "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/import-fresh": {
- "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": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/jiti": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
- "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
- "license": "MIT",
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/lightningcss": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
- "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-darwin-arm64": "1.30.1",
- "lightningcss-darwin-x64": "1.30.1",
- "lightningcss-freebsd-x64": "1.30.1",
- "lightningcss-linux-arm-gnueabihf": "1.30.1",
- "lightningcss-linux-arm64-gnu": "1.30.1",
- "lightningcss-linux-arm64-musl": "1.30.1",
- "lightningcss-linux-x64-gnu": "1.30.1",
- "lightningcss-linux-x64-musl": "1.30.1",
- "lightningcss-win32-arm64-msvc": "1.30.1",
- "lightningcss-win32-x64-msvc": "1.30.1"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
- "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
- "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
- "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
- "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
- "cpu": [
- "arm"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
- "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
- "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
- "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
- "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
- "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
- "cpu": [
- "arm64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
- "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.17",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
- "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/minizlib": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
- "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/mkdirp": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
- "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
- "license": "MIT",
- "bin": {
- "mkdirp": "dist/cjs/src/bin.js"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-releases": {
- "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/optionator": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
- "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.5"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
- "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.8",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/react": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
- "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-dom": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
- "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.26.0"
- },
- "peerDependencies": {
- "react": "^19.1.0"
- }
- },
- "node_modules/react-refresh": {
- "version": "0.17.0",
- "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
- "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-router": {
- "version": "7.6.1",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.1.tgz",
- "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
- "license": "MIT",
- "dependencies": {
- "cookie": "^1.0.1",
- "set-cookie-parser": "^2.6.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/react-router-dom": {
- "version": "7.6.1",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.1.tgz",
- "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==",
- "license": "MIT",
- "dependencies": {
- "react-router": "7.6.1"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "react": ">=18",
- "react-dom": ">=18"
- }
- },
- "node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/rollup": {
- "version": "4.40.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz",
- "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==",
- "license": "MIT",
- "dependencies": {
- "@types/estree": "1.0.7"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.40.2",
- "@rollup/rollup-android-arm64": "4.40.2",
- "@rollup/rollup-darwin-arm64": "4.40.2",
- "@rollup/rollup-darwin-x64": "4.40.2",
- "@rollup/rollup-freebsd-arm64": "4.40.2",
- "@rollup/rollup-freebsd-x64": "4.40.2",
- "@rollup/rollup-linux-arm-gnueabihf": "4.40.2",
- "@rollup/rollup-linux-arm-musleabihf": "4.40.2",
- "@rollup/rollup-linux-arm64-gnu": "4.40.2",
- "@rollup/rollup-linux-arm64-musl": "4.40.2",
- "@rollup/rollup-linux-loongarch64-gnu": "4.40.2",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2",
- "@rollup/rollup-linux-riscv64-gnu": "4.40.2",
- "@rollup/rollup-linux-riscv64-musl": "4.40.2",
- "@rollup/rollup-linux-s390x-gnu": "4.40.2",
- "@rollup/rollup-linux-x64-gnu": "4.40.2",
- "@rollup/rollup-linux-x64-musl": "4.40.2",
- "@rollup/rollup-win32-arm64-msvc": "4.40.2",
- "@rollup/rollup-win32-ia32-msvc": "4.40.2",
- "@rollup/rollup-win32-x64-msvc": "4.40.2",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/scheduler": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
- "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/set-cookie-parser": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
- "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
- "license": "MIT"
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
- "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
- "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
- "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
- "license": "ISC",
- "dependencies": {
- "@isaacs/fs-minipass": "^4.0.0",
- "chownr": "^3.0.0",
- "minipass": "^7.1.2",
- "minizlib": "^3.0.1",
- "mkdirp": "^3.0.1",
- "yallist": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tar/node_modules/yallist": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
- "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/tinyglobby": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
- "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
- "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/vite": {
- "version": "6.3.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
- "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.25.0",
- "fdir": "^6.4.4",
- "picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "jiti": ">=1.21.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "jiti": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- },
- "tsx": {
- "optional": true
- },
- "yaml": {
- "optional": true
- }
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
- "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
}
- }
}
diff --git a/frontend/package.json b/frontend/package.json
index fe5f67d..2998847 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,30 +1,30 @@
{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "eslint .",
- "preview": "vite preview"
- },
- "dependencies": {
- "@tailwindcss/vite": "^4.1.7",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-router-dom": "^7.6.1",
- "tailwindcss": "^4.1.7"
- },
- "devDependencies": {
- "@eslint/js": "^9.25.0",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "@vitejs/plugin-react": "^4.4.1",
- "eslint": "^9.25.0",
- "eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.19",
- "globals": "^16.0.0",
- "vite": "^6.3.5"
- }
+ "name": "frontend",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tailwindcss/vite": "^4.1.7",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.6.1",
+ "tailwindcss": "^4.1.7"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.25.0",
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@vitejs/plugin-react": "^4.4.1",
+ "eslint": "^9.25.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.19",
+ "globals": "^16.0.0",
+ "vite": "^6.3.5"
+ }
}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 2cd84d0..4b5b5ae 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,77 +1,72 @@
import { useState, useEffect } from "react";
-import {
- HashRouter as Router,
- Routes,
- Route,
- Navigate,
-} from "react-router-dom";
+import { HashRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import TopNav from "./components/topnav";
import SideNav from "./components/sidenav";
import Results from "./components/results";
import Settings from "./components/settings";
function App() {
- const [isSideNavOpen, setIsSideNavOpen] = useState(false);
- const [validConfig, setValidConfig] = useState(null); // null = loading
+ const [isSideNavOpen, setIsSideNavOpen] = useState(false);
+ const [validConfig, setValidConfig] = useState(null); // null = loading
- useEffect(() => {
- chrome.storage.local.get("valid_config", (result) => {
- if (chrome.runtime.lastError) {
- console.error("Error reading valid_config:", chrome.runtime.lastError);
- setValidConfig(false); // fallback
- } else {
- setValidConfig(result.valid_config === true);
- }
- });
- }, []);
+ useEffect(() => {
+ chrome.storage.local.get("valid_config", (result) => {
+ if (chrome.runtime.lastError) {
+ console.error("Error reading valid_config:", chrome.runtime.lastError);
+ setValidConfig(false); // fallback
+ } else {
+ setValidConfig(result.valid_config === true);
+ }
+ });
+ }, []);
+
+ if (validConfig === null) {
+ return (
+
+ Loading...
+
+ );
+ }
- if (validConfig === null) {
return (
-
- Loading...
-
+
+
+
+ setIsSideNavOpen(true)} />
+
+
+
+
+ {!validConfig ? (
+ <>
+ setValidConfig(true)} />
+ }
+ />
+ } />
+ >
+ ) : (
+ <>
+ } />
+ } />
+ } />
+ >
+ )}
+
+
+
+
+ setIsSideNavOpen(false)} />
+
+
+
);
- }
-
- return (
-
-
-
- setIsSideNavOpen(true)} />
-
-
-
-
- {!validConfig ? (
- <>
- setValidConfig(true)} />
- }
- />
- } />
- >
- ) : (
- <>
- } />
- } />
- } />
- >
- )}
-
-
-
-
- setIsSideNavOpen(false)} />
-
-
-
- );
}
export default App;
diff --git a/frontend/src/components/results.jsx b/frontend/src/components/results.jsx
index ce5550f..1f57730 100644
--- a/frontend/src/components/results.jsx
+++ b/frontend/src/components/results.jsx
@@ -1,149 +1,139 @@
import React, { useEffect, useState } from "react";
function Results() {
- const [drmType, setDrmType] = useState("");
- const [pssh, setPssh] = useState("");
- const [licenseUrl, setLicenseUrl] = useState("");
- const [keys, setKeys] = useState([]);
+ const [drmType, setDrmType] = useState("");
+ const [pssh, setPssh] = useState("");
+ const [licenseUrl, setLicenseUrl] = useState("");
+ const [keys, setKeys] = useState([]);
- useEffect(() => {
- chrome.storage.local.get(
- [
- "drmType",
- "latestPSSH",
- "latestLicenseRequest",
- "latestKeys",
- "licenseURL",
- ],
- (result) => {
- if (result.drmType) setDrmType(result.drmType);
- if (result.latestPSSH) setPssh(result.latestPSSH);
- if (result.licenseURL) setLicenseUrl(result.licenseURL);
- if (result.latestKeys) {
- try {
- const parsed = Array.isArray(result.latestKeys)
- ? result.latestKeys
- : JSON.parse(result.latestKeys);
- setKeys(parsed);
- } catch (e) {
- console.error("Failed to parse keys:", e);
- setKeys([]);
- }
- }
- }
- );
-
- const handleChange = (changes, area) => {
- if (area === "local") {
- if (changes.drmType) {
- setDrmType(changes.drmType.newValue);
- }
- if (changes.latestPSSH) {
- setPssh(changes.latestPSSH.newValue);
- }
- if (changes.licenseURL) {
- setLicenseUrl(changes.licenseURL.newValue);
- }
- if (changes.latestKeys) {
- setKeys(changes.latestKeys.newValue);
- }
- }
- };
-
- chrome.storage.onChanged.addListener(handleChange);
- return () => chrome.storage.onChanged.removeListener(handleChange);
- }, []);
-
- const handleCapture = () => {
- // Reset stored values
- chrome.storage.local.set({
- drmType: "None",
- latestPSSH: "None",
- licenseURL: "None",
- latestKeys: [],
- });
-
- // Get all normal windows to exclude your popup
- chrome.windows.getAll(
- { populate: true, windowTypes: ["normal"] },
- (windows) => {
- if (!windows || windows.length === 0) {
- console.warn("No normal Chrome windows found");
- return;
- }
-
- // Find the last focused normal window
- const lastFocusedWindow = windows.find((w) => w.focused) || windows[0];
-
- if (!lastFocusedWindow) {
- console.warn("No focused normal window found");
- return;
- }
-
- // Find the active tab in that window (that is a regular webpage)
- const activeTab = lastFocusedWindow.tabs.find(
- (tab) => tab.active && tab.url && /^https?:\/\//.test(tab.url)
+ useEffect(() => {
+ chrome.storage.local.get(
+ ["drmType", "latestPSSH", "latestLicenseRequest", "latestKeys", "licenseURL"],
+ (result) => {
+ if (result.drmType) setDrmType(result.drmType);
+ if (result.latestPSSH) setPssh(result.latestPSSH);
+ if (result.licenseURL) setLicenseUrl(result.licenseURL);
+ if (result.latestKeys) {
+ try {
+ const parsed = Array.isArray(result.latestKeys)
+ ? result.latestKeys
+ : JSON.parse(result.latestKeys);
+ setKeys(parsed);
+ } catch (e) {
+ console.error("Failed to parse keys:", e);
+ setKeys([]);
+ }
+ }
+ }
);
- if (activeTab?.id) {
- chrome.tabs.reload(activeTab.id, () => {
- if (chrome.runtime.lastError) {
- console.error("Failed to reload tab:", chrome.runtime.lastError);
+ const handleChange = (changes, area) => {
+ if (area === "local") {
+ if (changes.drmType) {
+ setDrmType(changes.drmType.newValue);
+ }
+ if (changes.latestPSSH) {
+ setPssh(changes.latestPSSH.newValue);
+ }
+ if (changes.licenseURL) {
+ setLicenseUrl(changes.licenseURL.newValue);
+ }
+ if (changes.latestKeys) {
+ setKeys(changes.latestKeys.newValue);
+ }
}
- });
- } else {
- console.warn("No active tab found in the last focused normal window");
- }
- }
- );
- };
+ };
- return (
-
-
-
DRM Type
-
-
PSSH
-
-
License URL
-
-
Keys
-
- {Array.isArray(keys) &&
- keys.filter((k) => k.type !== "SIGNING").length > 0 ? (
- keys
- .filter((k) => k.type !== "SIGNING")
- .map((k) => `${k.key_id || k.keyId}:${k.key}`)
- .join("\n")
- ) : (
- None
- )}
-
-
- );
+ chrome.storage.onChanged.addListener(handleChange);
+ return () => chrome.storage.onChanged.removeListener(handleChange);
+ }, []);
+
+ const handleCapture = () => {
+ // Reset stored values
+ chrome.storage.local.set({
+ drmType: "None",
+ latestPSSH: "None",
+ licenseURL: "None",
+ latestKeys: [],
+ });
+
+ // Get all normal windows to exclude your popup
+ chrome.windows.getAll({ populate: true, windowTypes: ["normal"] }, (windows) => {
+ if (!windows || windows.length === 0) {
+ console.warn("No normal Chrome windows found");
+ return;
+ }
+
+ // Find the last focused normal window
+ const lastFocusedWindow = windows.find((w) => w.focused) || windows[0];
+
+ if (!lastFocusedWindow) {
+ console.warn("No focused normal window found");
+ return;
+ }
+
+ // Find the active tab in that window (that is a regular webpage)
+ const activeTab = lastFocusedWindow.tabs.find(
+ (tab) => tab.active && tab.url && /^https?:\/\//.test(tab.url)
+ );
+
+ if (activeTab?.id) {
+ chrome.tabs.reload(activeTab.id, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Failed to reload tab:", chrome.runtime.lastError);
+ }
+ });
+ } else {
+ console.warn("No active tab found in the last focused normal window");
+ }
+ });
+ };
+
+ return (
+
+
+
DRM Type
+
+
PSSH
+
+
License URL
+
+
Keys
+
+ {Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0 ? (
+ keys
+ .filter((k) => k.type !== "SIGNING")
+ .map((k) => `${k.key_id || k.keyId}:${k.key}`)
+ .join("\n")
+ ) : (
+ None
+ )}
+
+
+ );
}
export default Results;
diff --git a/frontend/src/components/settings.jsx b/frontend/src/components/settings.jsx
index e618848..7e7ba9a 100644
--- a/frontend/src/components/settings.jsx
+++ b/frontend/src/components/settings.jsx
@@ -2,149 +2,140 @@ import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
function Settings({ onConfigSaved }) {
- const [instanceUrl, setInstanceUrl] = useState("");
- const [storedUrl, setStoredUrl] = useState(null);
- const [message, setMessage] = useState(null);
- const [messageType, setMessageType] = useState(null);
- const [loading, setLoading] = useState(false);
+ const [instanceUrl, setInstanceUrl] = useState("");
+ const [storedUrl, setStoredUrl] = useState(null);
+ const [message, setMessage] = useState(null);
+ const [messageType, setMessageType] = useState(null);
+ const [loading, setLoading] = useState(false);
- const navigate = useNavigate();
+ const navigate = useNavigate();
- useEffect(() => {
- chrome.storage.local.get("cdrm_instance", (result) => {
- if (chrome.runtime.lastError) {
- console.error(
- "Error fetching CDRM instance:",
- chrome.runtime.lastError
- );
- } else if (result.cdrm_instance) {
- setStoredUrl(result.cdrm_instance);
- }
- });
- }, []);
-
- const handleSave = async () => {
- const trimmedUrl = instanceUrl.trim().replace(/\/+$/, "");
- if (!trimmedUrl) {
- setMessage("Please enter a valid URL.");
- setMessageType("error");
- return;
- }
-
- const endpoint = trimmedUrl + "/api/extension";
- setLoading(true);
- setMessage(null);
-
- try {
- const response = await fetch(endpoint, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- });
-
- const data = await response.json();
-
- if (data.status === true) {
- setMessage("Successfully connected to CDRM Instance.");
- setMessageType("success");
-
- const widevineRes = await fetch(
- `${trimmedUrl}/remotecdm/widevine/deviceinfo`
- );
- if (!widevineRes.ok)
- throw new Error("Failed to fetch Widevine device info");
- const widevineData = await widevineRes.json();
-
- const playreadyRes = await fetch(
- `${trimmedUrl}/remotecdm/playready/deviceinfo`
- );
- if (!playreadyRes.ok)
- throw new Error("Failed to fetch PlayReady device info");
- const playreadyData = await playreadyRes.json();
-
- chrome.storage.local.set(
- {
- valid_config: true,
- cdrm_instance: trimmedUrl,
- widevine_device: {
- device_type: widevineData.device_type,
- system_id: widevineData.system_id,
- security_level: widevineData.security_level,
- secret: widevineData.secret,
- device_name: widevineData.device_name,
- host: trimmedUrl,
- },
- playready_device: {
- security_level: playreadyData.security_level,
- secret: playreadyData.secret,
- device_name: playreadyData.device_name,
- host: trimmedUrl,
- },
- },
- () => {
+ useEffect(() => {
+ chrome.storage.local.get("cdrm_instance", (result) => {
if (chrome.runtime.lastError) {
- console.error(
- "Error saving to chrome.storage:",
- chrome.runtime.lastError
- );
- setMessage("Error saving configuration.");
- setMessageType("error");
- } else {
- console.log("Configuration saved.");
- setStoredUrl(trimmedUrl);
- setInstanceUrl("");
- if (onConfigSaved) onConfigSaved();
- navigate("/results"); // Automatically redirect after success
+ console.error("Error fetching CDRM instance:", chrome.runtime.lastError);
+ } else if (result.cdrm_instance) {
+ setStoredUrl(result.cdrm_instance);
}
- }
- );
- } else {
- throw new Error("Invalid response from endpoint.");
- }
- } catch (err) {
- console.error("Connection error:", err);
- setMessage("Invalid endpoint or device info could not be retrieved.");
- setMessageType("error");
- } finally {
- setLoading(false);
- }
- };
+ });
+ }, []);
- return (
-
-
setInstanceUrl(e.target.value)}
- placeholder={
- storedUrl
- ? `Current CDRM Instance: ${storedUrl}`
- : "CDRM Instance URL (e.g., https://cdrm-project.com/, http://127.0.0.1:5000/)"
+ const handleSave = async () => {
+ const trimmedUrl = instanceUrl.trim().replace(/\/+$/, "");
+ if (!trimmedUrl) {
+ setMessage("Please enter a valid URL.");
+ setMessageType("error");
+ return;
}
- className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4"
- />
-
- {message && (
-
- {message}
-
- )}
-
- );
+ const endpoint = trimmedUrl + "/api/extension";
+ setLoading(true);
+ setMessage(null);
+
+ try {
+ const response = await fetch(endpoint, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const data = await response.json();
+
+ if (data.status === true) {
+ setMessage("Successfully connected to CDRM Instance.");
+ setMessageType("success");
+
+ const widevineRes = await fetch(`${trimmedUrl}/remotecdm/widevine/deviceinfo`);
+ if (!widevineRes.ok) throw new Error("Failed to fetch Widevine device info");
+ const widevineData = await widevineRes.json();
+
+ const playreadyRes = await fetch(`${trimmedUrl}/remotecdm/playready/deviceinfo`);
+ if (!playreadyRes.ok) throw new Error("Failed to fetch PlayReady device info");
+ const playreadyData = await playreadyRes.json();
+
+ chrome.storage.local.set(
+ {
+ valid_config: true,
+ cdrm_instance: trimmedUrl,
+ widevine_device: {
+ device_type: widevineData.device_type,
+ system_id: widevineData.system_id,
+ security_level: widevineData.security_level,
+ secret: widevineData.secret,
+ device_name: widevineData.device_name,
+ host: trimmedUrl,
+ },
+ playready_device: {
+ security_level: playreadyData.security_level,
+ secret: playreadyData.secret,
+ device_name: playreadyData.device_name,
+ host: trimmedUrl,
+ },
+ },
+ () => {
+ if (chrome.runtime.lastError) {
+ console.error(
+ "Error saving to chrome.storage:",
+ chrome.runtime.lastError
+ );
+ setMessage("Error saving configuration.");
+ setMessageType("error");
+ } else {
+ console.log("Configuration saved.");
+ setStoredUrl(trimmedUrl);
+ setInstanceUrl("");
+ if (onConfigSaved) onConfigSaved();
+ navigate("/results"); // Automatically redirect after success
+ }
+ }
+ );
+ } else {
+ throw new Error("Invalid response from endpoint.");
+ }
+ } catch (err) {
+ console.error("Connection error:", err);
+ setMessage("Invalid endpoint or device info could not be retrieved.");
+ setMessageType("error");
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
setInstanceUrl(e.target.value)}
+ placeholder={
+ storedUrl
+ ? `Current CDRM Instance: ${storedUrl}`
+ : "CDRM Instance URL (e.g., https://cdrm-project.com/, http://127.0.0.1:5000/)"
+ }
+ className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4"
+ />
+
+
+ {message && (
+
+ {message}
+
+ )}
+
+ );
}
export default Settings;
diff --git a/frontend/src/components/sidenav.jsx b/frontend/src/components/sidenav.jsx
index 4bf4dfe..15a33aa 100644
--- a/frontend/src/components/sidenav.jsx
+++ b/frontend/src/components/sidenav.jsx
@@ -4,48 +4,45 @@ import settingsIcon from "../assets/settings.svg";
import closeIcon from "../assets/close.svg";
function SideNav({ onClose }) {
- return (
-
-
-
-
+ return (
+
+
+
+
-
-
-
- Home
-
-
+
+
+
+ Home
+
+
-
-
-
- Settings
-
-
-
- );
+
+
+
+ Settings
+
+
+
+ );
}
export default SideNav;
diff --git a/frontend/src/components/topnav.jsx b/frontend/src/components/topnav.jsx
index 1653a06..aa86dbf 100644
--- a/frontend/src/components/topnav.jsx
+++ b/frontend/src/components/topnav.jsx
@@ -2,84 +2,81 @@ import { useEffect, useState } from "react";
import hamburgerIcon from "../assets/hamburger.svg";
function TopNav({ onMenuClick }) {
- const [injectionType, setInjectionType] = useState("LICENSE");
- const [drmOverride, setDrmOverride] = useState("DISABLED");
+ const [injectionType, setInjectionType] = useState("LICENSE");
+ const [drmOverride, setDrmOverride] = useState("DISABLED");
- useEffect(() => {
- chrome.storage.local.get(["injection_type", "drm_override"], (result) => {
- if (result.injection_type !== undefined) {
- setInjectionType(result.injection_type);
- }
- if (result.drm_override !== undefined) {
- setDrmOverride(result.drm_override);
- }
- });
- }, []);
+ useEffect(() => {
+ chrome.storage.local.get(["injection_type", "drm_override"], (result) => {
+ if (result.injection_type !== undefined) {
+ setInjectionType(result.injection_type);
+ }
+ if (result.drm_override !== undefined) {
+ setDrmOverride(result.drm_override);
+ }
+ });
+ }, []);
- const handleInjectionTypeChange = (type) => {
- chrome.storage.local.set({ injection_type: type }, () => {
- if (chrome.runtime.lastError) {
- console.error(
- "Error updating injection_type:",
- chrome.runtime.lastError
- );
- } else {
- setInjectionType(type);
- console.log(`Injection type updated to ${type}`);
- }
- });
- };
+ const handleInjectionTypeChange = (type) => {
+ chrome.storage.local.set({ injection_type: type }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error updating injection_type:", chrome.runtime.lastError);
+ } else {
+ setInjectionType(type);
+ console.log(`Injection type updated to ${type}`);
+ }
+ });
+ };
- const handleDrmOverrideChange = (type) => {
- chrome.storage.local.set({ drm_override: type }, () => {
- if (chrome.runtime.lastError) {
- console.error("Error updating drm_override:", chrome.runtime.lastError);
- } else {
- setDrmOverride(type);
- console.log(`DRM Override updated to ${type}`);
- }
- });
- };
+ const handleDrmOverrideChange = (type) => {
+ chrome.storage.local.set({ drm_override: type }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error updating drm_override:", chrome.runtime.lastError);
+ } else {
+ setDrmOverride(type);
+ console.log(`DRM Override updated to ${type}`);
+ }
+ });
+ };
- return (
-
-

-
-
- Injection Type:
-
-
-
-
-
-
- );
+ return (
+
+

+
+
+ Injection Type:
+
+
+
+
+
+
+ );
}
export default TopNav;
diff --git a/frontend/src/index.css b/frontend/src/index.css
index e6d7ec6..032c11f 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,8 +1,10 @@
@import "tailwindcss";
-html, body, #root {
- height: 100%;
- width: 100%;
- margin: 0;
- padding: 0;
-}
\ No newline at end of file
+html,
+body,
+#root {
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+}
diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx
index b9a1a6d..46adf76 100644
--- a/frontend/src/main.jsx
+++ b/frontend/src/main.jsx
@@ -1,10 +1,10 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
-import App from './App.jsx'
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import "./index.css";
+import App from "./App.jsx";
-createRoot(document.getElementById('root')).render(
-
-
- ,
-)
+createRoot(document.getElementById("root")).render(
+
+
+
+);
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 44780a5..a4c9f4d 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -1,9 +1,9 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
-import tailwindcss from '@tailwindcss/vite'
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+import tailwindcss from "@tailwindcss/vite";
// https://vite.dev/config/
export default defineConfig({
- base: './',
- plugins: [react(), tailwindcss()],
-})
+ base: "./",
+ plugins: [react(), tailwindcss()],
+});
diff --git a/inject.js b/inject.js
index 5c49cb2..fdcb029 100644
--- a/inject.js
+++ b/inject.js
@@ -1,6 +1,6 @@
let widevineDeviceInfo = null;
let playreadyDeviceInfo = null;
-let originalChallenge = null
+let originalChallenge = null;
let serviceCertFound = false;
let drmType = "NONE";
let psshFound = false;
@@ -21,11 +21,11 @@ let keysRetrieved = false;
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
// Add listener for DRM override messages
-window.addEventListener("message", function(event) {
- if (event.source !== window) return;
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
if (event.data.type === "__DRM_OVERRIDE__") {
- drmOverride = event.data.drmOverride || "DISABLED";
- console.log("DRM Override set to:", drmOverride);
+ drmOverride = event.data.drmOverride || "DISABLED";
+ console.log("DRM Override set to:", drmOverride);
}
});
@@ -33,32 +33,148 @@ window.addEventListener("message", function(event) {
window.postMessage({ type: "__GET_INJECTION_TYPE__" }, "*");
// Add listener for injection type messages
-window.addEventListener("message", function(event) {
- if (event.source !== window) return;
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
- if (event.data.type === "__INJECTION_TYPE__") {
- interceptType = event.data.injectionType || "DISABLED";
- console.log("Injection type set to:", interceptType);
- }
+ if (event.data.type === "__INJECTION_TYPE__") {
+ interceptType = event.data.injectionType || "DISABLED";
+ console.log("Injection type set to:", interceptType);
+ }
});
// Post message to get CDM devices
window.postMessage({ type: "__GET_CDM_DEVICES__" }, "*");
// Add listener for CDM device messages
-window.addEventListener("message", function(event) {
- if (event.source !== window) return;
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
- if (event.data.type === "__CDM_DEVICES__") {
- const { widevine_device, playready_device } = event.data;
+ if (event.data.type === "__CDM_DEVICES__") {
+ const { widevine_device, playready_device } = event.data;
- console.log("Received device info:", widevine_device, playready_device);
+ console.log("Received device info:", widevine_device, playready_device);
- widevineDeviceInfo = widevine_device;
- playreadyDeviceInfo = playready_device;
- }
+ widevineDeviceInfo = widevine_device;
+ playreadyDeviceInfo = playready_device;
+ }
});
+function safeHeaderShellEscape(str) {
+ return str
+ .replace(/\\/g, "\\\\")
+ .replace(/"/g, '\\"')
+ .replace(/\$/g, "\\$") // escape shell expansion
+ .replace(/`/g, "\\`")
+ .replace(/\n/g, ""); // strip newlines
+}
+
+// Intercep network to find manifest
+function injectManifestInterceptor() {
+ const script = document.createElement("script");
+ script.textContent = `
+ (function() {
+ function isProbablyManifest(text = "", contentType = "") {
+ const lowerCT = contentType?.toLowerCase() ?? "";
+ const sample = text.slice(0, 2000);
+
+ const isHLSMime = lowerCT.includes("mpegurl");
+ const isDASHMime = lowerCT.includes("dash+xml");
+ const isSmoothMime = lowerCT.includes("sstr+xml");
+
+ const isHLSKeyword = sample.includes("#EXTM3U") || sample.includes("#EXT-X-STREAM-INF");
+ const isDASHKeyword = sample.includes(" {
+ headersObj[key] = value;
+ });
+
+ const headerFlags = Object.entries(headersObj)
+ .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
+ .join(" ");
+
+ window.postMessage({
+ type: "__MANIFEST_HEADERS__",
+ url,
+ headers: headerFlags
+ }, "*");
+ }
+ } catch (e) {}
+
+ return response;
+ };
+
+ const originalXHROpen = XMLHttpRequest.prototype.open;
+ const originalXHRSend = XMLHttpRequest.prototype.send;
+
+ XMLHttpRequest.prototype.open = function(method, url) {
+ this.__url = url;
+ return originalXHROpen.apply(this, arguments);
+ };
+
+ XMLHttpRequest.prototype.send = function(body) {
+ this.addEventListener("load", function () {
+ try {
+ const contentType = this.getResponseHeader("content-type") || "";
+ const text = this.responseText;
+
+ if (isProbablyManifest(text, contentType)) {
+ window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
+ console.log("[Manifest][xhr]", this.__url, contentType);
+
+ const xhrHeaders = {};
+ const rawHeaders = this.getAllResponseHeaders().trim().split(/\\r?\\n/);
+ rawHeaders.forEach(line => {
+ const parts = line.split(": ");
+ if (parts.length === 2) {
+ xhrHeaders[parts[0]] = parts[1];
+ }
+ });
+
+ const headerFlags = Object.entries(xhrHeaders)
+ .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
+ .join(" ");
+
+ window.postMessage({
+ type: "__MANIFEST_HEADERS__",
+ url: this.__url,
+ headers: headerFlags
+ }, "*");
+ }
+ } catch (e) {}
+ });
+ return originalXHRSend.apply(this, arguments);
+ };
+ })();
+ `;
+ document.documentElement.appendChild(script);
+ script.remove();
+}
+
+injectManifestInterceptor();
// PlayReady Remote CDM Class
class remotePlayReadyCDM {
@@ -76,8 +192,8 @@ class remotePlayReadyCDM {
openSession() {
const url = `${this.host}/remotecdm/playready/${this.device_name}/open`;
const xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.session_id) {
@@ -93,11 +209,11 @@ class remotePlayReadyCDM {
getChallenge(init_data) {
const url = `${this.host}/remotecdm/playready/${this.device_name}/get_license_challenge`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
session_id: this.session_id,
- init_data: init_data
+ init_data: init_data,
};
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
@@ -114,16 +230,17 @@ class remotePlayReadyCDM {
parseLicense(license_message) {
const url = `${this.host}/remotecdm/playready/${this.device_name}/parse_license`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
session_id: this.session_id,
- license_message: license_message
- }
+ license_message: license_message,
+ };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
- if (jsonData.message === "Successfully parsed and loaded the Keys from the License message")
- {
+ if (
+ jsonData.message === "Successfully parsed and loaded the Keys from the License message"
+ ) {
console.log("PlayReady license response parsed successfully");
return true;
} else {
@@ -136,11 +253,11 @@ class remotePlayReadyCDM {
getKeys() {
const url = `${this.host}/remotecdm/playready/${this.device_name}/get_keys`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
- session_id: this.session_id
- }
+ session_id: this.session_id,
+ };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.keys) {
@@ -153,11 +270,11 @@ class remotePlayReadyCDM {
}
// Close PlayReady session
- closeSession () {
+ closeSession() {
const url = `${this.host}/remotecdm/playready/${this.device_name}/close/${this.session_id}`;
const xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData) {
@@ -171,24 +288,24 @@ class remotePlayReadyCDM {
// Widevine Remote CDM Class
class remoteWidevineCDM {
- constructor(device_type, system_id, security_level, host, secret, device_name) {
- this.device_type = device_type;
- this.system_id = system_id;
- this.security_level = security_level;
- this.host = host;
- this.secret = secret;
- this.device_name = device_name;
- this.session_id = null;
- this.challenge = null;
- this.keys = null;
- }
+ constructor(device_type, system_id, security_level, host, secret, device_name) {
+ this.device_type = device_type;
+ this.system_id = system_id;
+ this.security_level = security_level;
+ this.host = host;
+ this.secret = secret;
+ this.device_name = device_name;
+ this.session_id = null;
+ this.challenge = null;
+ this.keys = null;
+ }
// Open Widevine session
- openSession () {
+ openSession() {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/open`;
const xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.session_id) {
@@ -204,12 +321,12 @@ class remoteWidevineCDM {
setServiceCertificate(certificate) {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/set_service_certificate`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
session_id: this.session_id,
- certificate: certificate ?? null
- }
+ certificate: certificate ?? null,
+ };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.status === 200) {
@@ -221,15 +338,15 @@ class remoteWidevineCDM {
}
// Get Widevine challenge
- getChallenge(init_data, license_type = 'STREAMING') {
+ getChallenge(init_data, license_type = "STREAMING") {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_license_challenge/${license_type}`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
session_id: this.session_id,
init_data: init_data,
- privacy_mode: serviceCertFound
+ privacy_mode: serviceCertFound,
};
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
@@ -244,13 +361,13 @@ class remoteWidevineCDM {
// Parse Widevine license response
parseLicense(license_message) {
- const url = `${this.host}/remotecdm/widevine/${this.device_name}/parse_license`;
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/parse_license`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
session_id: this.session_id,
- license_message: license_message
+ license_message: license_message,
};
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
@@ -267,10 +384,10 @@ class remoteWidevineCDM {
getKeys() {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_keys/ALL`;
const xhr = new XMLHttpRequest();
- xhr.open('POST', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
const body = {
- session_id: this.session_id
+ session_id: this.session_id,
};
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
@@ -287,8 +404,8 @@ class remoteWidevineCDM {
closeSession() {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/close/${this.session_id}`;
const xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData) {
@@ -302,22 +419,22 @@ class remoteWidevineCDM {
// Utility functions
function hexStrToU8(hexString) {
- return Uint8Array.from(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
+ return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
}
function u8ToHexStr(bytes) {
- return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
+ return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
}
function b64ToHexStr(b64) {
- return [...atob(b64)].map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join``;
+ return [...atob(b64)].map((c) => c.charCodeAt(0).toString(16).padStart(2, "0")).join``;
}
function jsonContainsValue(obj, prefix = "CAES") {
if (typeof obj === "string") return obj.startsWith(prefix);
- if (Array.isArray(obj)) return obj.some(val => jsonContainsValue(val, prefix));
+ if (Array.isArray(obj)) return obj.some((val) => jsonContainsValue(val, prefix));
if (typeof obj === "object" && obj !== null) {
- return Object.values(obj).some(val => jsonContainsValue(val, prefix));
+ return Object.values(obj).some((val) => jsonContainsValue(val, prefix));
}
return false;
}
@@ -328,7 +445,7 @@ function jsonReplaceValue(obj, newValue) {
}
if (Array.isArray(obj)) {
- return obj.map(item => jsonReplaceValue(item, newValue));
+ return obj.map((item) => jsonReplaceValue(item, newValue));
}
if (typeof obj === "object" && obj !== null) {
@@ -379,10 +496,10 @@ function getPlayReadyPssh(buffer) {
}
function getClearkey(response) {
- let obj = JSON.parse((new TextDecoder("utf-8")).decode(response));
- return obj["keys"].map(o => ({
- key_id: b64ToHexStr(o["kid"].replace(/-/g, '+').replace(/_/g, '/')),
- key: b64ToHexStr(o["k"].replace(/-/g, '+').replace(/_/g, '/')),
+ let obj = JSON.parse(new TextDecoder("utf-8").decode(response));
+ return obj["keys"].map((o) => ({
+ key_id: b64ToHexStr(o["kid"].replace(/-/g, "+").replace(/_/g, "/")),
+ key: b64ToHexStr(o["k"].replace(/-/g, "+").replace(/_/g, "/")),
}));
}
@@ -397,7 +514,7 @@ function base64ToUint8Array(base64) {
}
function arrayBufferToBase64(uint8array) {
- let binary = '';
+ let binary = "";
const len = uint8array.length;
for (let i = 0; i < len; i++) {
@@ -409,20 +526,20 @@ function arrayBufferToBase64(uint8array) {
// Challenge generator interceptor
const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
-MediaKeySession.prototype.generateRequest = function(initDataType, initData) {
+MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
const session = this;
let playReadyPssh = getPlayReadyPssh(initData);
if (playReadyPssh) {
console.log("[DRM Detected] PlayReady");
foundPlayreadyPssh = playReadyPssh;
- console.log("[PlayReady PSSH found] " + playReadyPssh)
+ console.log("[PlayReady PSSH found] " + playReadyPssh);
}
- let wideVinePssh = getWidevinePssh(initData)
+ let wideVinePssh = getWidevinePssh(initData);
if (wideVinePssh) {
// Widevine code
console.log("[DRM Detected] Widevine");
foundWidevinePssh = wideVinePssh;
- console.log("[Widevine PSSH found] " + wideVinePssh)
+ console.log("[Widevine PSSH found] " + wideVinePssh);
}
// Challenge message interceptor
if (!remoteListenerMounted) {
@@ -432,10 +549,16 @@ MediaKeySession.prototype.generateRequest = function(initDataType, initData) {
const uint8Array = new Uint8Array(event.message);
const base64challenge = arrayBufferToBase64(uint8Array);
if (base64challenge === "CAQ=" && interceptType !== "DISABLED" && !serviceCertFound) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
+ const { device_type, system_id, security_level, host, secret, device_name } =
+ widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
remoteCDM.openSession();
}
if (!injectionSuccess && base64challenge !== "CAQ=" && interceptType !== "DISABLED") {
@@ -450,30 +573,53 @@ MediaKeySession.prototype.generateRequest = function(initDataType, initData) {
window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
if (interceptType === "EME" && !remoteCDM) {
const {
- device_type, system_id, security_level, host, secret, device_name
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
} = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
- }}
+ }
+ }
if (!originalChallenge.startsWith("CAES")) {
const buffer = event.message;
- const decoder = new TextDecoder('utf-16');
+ const decoder = new TextDecoder("utf-16");
const decodedText = decoder.decode(buffer);
- const match = decodedText.match(/([^<]+)<\/Challenge>/);
+ const match = decodedText.match(
+ /([^<]+)<\/Challenge>/
+ );
if (match) {
window.postMessage({ type: "__DRM_TYPE__", data: "PlayReady" }, "*");
- window.postMessage({ type: "__PSSH_DATA__", data: foundPlayreadyPssh }, "*");
+ window.postMessage(
+ { type: "__PSSH_DATA__", data: foundPlayreadyPssh },
+ "*"
+ );
originalChallenge = match[1];
- if (interceptType === "EME" && !remoteCDM) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name)
+ if (interceptType === "EME" && !remoteCDM) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
remoteCDM.openSession();
remoteCDM.getChallenge(foundPlayreadyPssh);
}
- }}
+ }
+ }
if (interceptType === "EME" && remoteCDM) {
const uint8challenge = base64ToUint8Array(remoteCDM.challenge);
const challengeBuffer = uint8challenge.buffer;
@@ -482,24 +628,24 @@ MediaKeySession.prototype.generateRequest = function(initDataType, initData) {
origin: event.origin,
lastEventId: event.lastEventId,
source: event.source,
- ports: event.ports
+ ports: event.ports,
});
Object.defineProperty(syntheticEvent, "message", {
- get: () => challengeBuffer
+ get: () => challengeBuffer,
});
- console.log("Intercepted EME Challenge and injected custom one.")
+ console.log("Intercepted EME Challenge and injected custom one.");
session.dispatchEvent(syntheticEvent);
}
}
- })
+ });
console.log("Message interceptor mounted.");
}
-return originalGenerateRequest.call(session, initDataType, initData);
+ return originalGenerateRequest.call(session, initDataType, initData);
};
// Message update interceptors
const originalUpdate = MediaKeySession.prototype.update;
-MediaKeySession.prototype.update = function(response) {
+MediaKeySession.prototype.update = function (response) {
const uint8 = response instanceof Uint8Array ? response : new Uint8Array(response);
const base64Response = window.btoa(String.fromCharCode(...uint8));
if (base64Response.startsWith("CAUS") && foundWidevinePssh && remoteCDM && !serviceCertFound) {
@@ -511,7 +657,11 @@ MediaKeySession.prototype.update = function(response) {
window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
serviceCertFound = true;
}
- if (!base64Response.startsWith("CAUS") && (foundWidevinePssh || foundPlayreadyPssh) && !keysRetrieved) {
+ if (
+ !base64Response.startsWith("CAUS") &&
+ (foundWidevinePssh || foundPlayreadyPssh) &&
+ !keysRetrieved
+ ) {
if (licenseResponseCounter === 1 || foundChallengeInBody) {
remoteCDM.parseLicense(base64Response);
remoteCDM.getKeys();
@@ -527,20 +677,20 @@ MediaKeySession.prototype.update = function(response) {
.then(() => {
let clearKeys = getClearkey(response);
if (clearKeys && clearKeys.length > 0) {
- console.log("[CLEARKEY] ", clearKeys);
- const drmType = {
- type: "__DRM_TYPE__",
- data: 'ClearKey'
- };
- window.postMessage(drmType, "*");
- const keysData = {
- type: "__KEYS_DATA__",
- data: clearKeys
- };
- window.postMessage(keysData, "*");
+ console.log("[CLEARKEY] ", clearKeys);
+ const drmType = {
+ type: "__DRM_TYPE__",
+ data: "ClearKey",
+ };
+ window.postMessage(drmType, "*");
+ const keysData = {
+ type: "__KEYS_DATA__",
+ data: clearKeys,
+ };
+ window.postMessage(keysData, "*");
}
})
- .catch(e => {
+ .catch((e) => {
console.log("[CLEARKEY] Not found");
});
}
@@ -549,265 +699,424 @@ MediaKeySession.prototype.update = function(response) {
};
// fetch POST interceptor
-(function() {
- const originalFetch = window.fetch;
+(function () {
+ const originalFetch = window.fetch;
- window.fetch = async function(resource, config = {}) {
- const method = (config.method || 'GET').toUpperCase();
+ window.fetch = async function (resource, config = {}) {
+ const method = (config.method || "GET").toUpperCase();
- if (method === 'POST') {
- let body = config.body;
- if (body) {
- if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
- const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
- const base64Body = window.btoa(String.fromCharCode(...buffer));
- if ((base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) && (!remoteCDM || remoteCDM.challenge === null || base64Body !== remoteCDM.challenge) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
- if ((base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) && interceptType == "LICENSE" &&!foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (base64Body.startsWith("CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ if (method === "POST") {
+ let body = config.body;
+ if (body) {
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
+ const base64Body = window.btoa(String.fromCharCode(...buffer));
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64Body !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (base64Body.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64Body.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64Body.startsWith("PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
+ const injectedBody = base64ToUint8Array(remoteCDM.challenge);
+ config.body = injectedBody;
+ return originalFetch(resource, config);
+ }
+ }
+ if (typeof body === "string" && !isJson(body)) {
+ const base64EncodedBody = btoa(body);
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64EncodedBody !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (base64EncodedBody.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64EncodedBody.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
}
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = base64ToUint8Array(remoteCDM.challenge);
- config.body = injectedBody;
- return originalFetch(resource, config);
- }
- }
- if (typeof body === 'string' && !isJson(body)) {
- const base64EncodedBody = btoa(body);
- if ((base64EncodedBody.startsWith("CAES") || base64EncodedBody.startsWith("PD94")) && (!remoteCDM || remoteCDM.challenge === null || base64EncodedBody !== remoteCDM.challenge) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
- if ((base64EncodedBody.startsWith("CAES") || base64EncodedBody.startsWith("PD94")) && interceptType == "LICENSE" && !foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (base64EncodedBody.startsWith("CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64EncodedBody.startsWith("PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
+ const injectedBody = atob(remoteCDM.challenge);
+ config.body = injectedBody;
+ return originalFetch(resource, config);
+ }
+ }
+ if (typeof body === "string" && isJson(body)) {
+ const jsonBody = JSON.parse(body);
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ (!remoteCDM || remoteCDM.challenge === null) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ interceptType === "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (jsonContainsValue(jsonBody, "CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (jsonContainsValue(jsonBody, "PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
}
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = atob(remoteCDM.challenge);
- config.body = injectedBody;
- return originalFetch(resource, config);
- }
- }
- if (typeof body === 'string' && isJson(body)) {
- const jsonBody = JSON.parse(body);
-
- if ((jsonContainsValue(jsonBody, "CAES") || jsonContainsValue(jsonBody, "PD94")) && (!remoteCDM || remoteCDM.challenge === null) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
-
- if ((jsonContainsValue(jsonBody, "CAES") || jsonContainsValue(jsonBody, "PD94")) && interceptType === "LICENSE" && !foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, "CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (jsonContainsValue(jsonBody, "PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
- }
+ const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
+ config.body = JSON.stringify(injectedBody);
}
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
- config.body = JSON.stringify(injectedBody);
}
}
}
- }
- return originalFetch(resource, config);
- };
+ return originalFetch(resource, config);
+ };
})();
// XHR POST interceptor
-(function() {
- const originalOpen = XMLHttpRequest.prototype.open;
- const originalSend = XMLHttpRequest.prototype.send;
+(function () {
+ const originalOpen = XMLHttpRequest.prototype.open;
+ const originalSend = XMLHttpRequest.prototype.send;
- XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
- this._method = method;
- this._url = url;
- return originalOpen.apply(this, arguments);
- };
+ XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
+ this._method = method;
+ this._url = url;
+ return originalOpen.apply(this, arguments);
+ };
- XMLHttpRequest.prototype.send = function(body) {
- if (this._method && this._method.toUpperCase() === 'POST') {
- if (body) {
-
- if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
- const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
- const base64Body = window.btoa(String.fromCharCode(...buffer));
- if ((base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) && (!remoteCDM || remoteCDM.challenge === null || base64Body !== remoteCDM.challenge) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
- if ((base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) && interceptType == "LICENSE" &&!foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (base64Body.startsWith("CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ XMLHttpRequest.prototype.send = function (body) {
+ if (this._method && this._method.toUpperCase() === "POST") {
+ if (body) {
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
+ const base64Body = window.btoa(String.fromCharCode(...buffer));
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64Body !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (base64Body.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64Body.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64Body.startsWith("PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
- }
+ const injectedBody = base64ToUint8Array(remoteCDM.challenge);
+ return originalSend.call(this, injectedBody);
}
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = base64ToUint8Array(remoteCDM.challenge);
- return originalSend.call(this, injectedBody);
}
- }
- if (typeof body === 'string' && !isJson(body)) {
- const base64EncodedBody = btoa(body);
- if ((base64EncodedBody.startsWith("CAES") || base64EncodedBody.startsWith("PD94")) && (!remoteCDM || remoteCDM.challenge === null || base64EncodedBody !== remoteCDM.challenge) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
- if ((base64EncodedBody.startsWith("CAES") || base64EncodedBody.startsWith("PD94")) && interceptType == "LICENSE" && !foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (base64EncodedBody.startsWith("CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ if (typeof body === "string" && !isJson(body)) {
+ const base64EncodedBody = btoa(body);
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64EncodedBody !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (base64EncodedBody.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64EncodedBody.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64EncodedBody.startsWith("PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
+ const injectedBody = atob(remoteCDM.challenge);
+ return originalSend.call(this, injectedBody);
+ }
+ }
+
+ if (typeof body === "string" && isJson(body)) {
+ const jsonBody = JSON.parse(body);
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ (!remoteCDM || remoteCDM.challenge === null) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ interceptType === "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (jsonContainsValue(jsonBody, "CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (jsonContainsValue(jsonBody, "PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
}
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = atob(remoteCDM.challenge);
- return originalSend.call(this, injectedBody);
- }
- }
-
- if (typeof body === 'string' && isJson(body)) {
- const jsonBody = JSON.parse(body);
-
- if ((jsonContainsValue(jsonBody, "CAES") || jsonContainsValue(jsonBody, "PD94")) && (!remoteCDM || remoteCDM.challenge === null) && interceptType === "EME") {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
-
- if ((jsonContainsValue(jsonBody, "CAES") || jsonContainsValue(jsonBody, "PD94")) && interceptType === "LICENSE" && !foundChallengeInBody) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, "CAES")) {
- const {
- device_type, system_id, security_level, host, secret, device_name
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(device_type, system_id, security_level, host, secret, device_name);
- remoteCDM.openSession();
+ if (remoteCDM && remoteCDM.challenge === null) {
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (jsonContainsValue(jsonBody, "PD94")) {
- const {
- security_level, host, secret, device_name
- } = playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
- }
+ const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
+ return originalSend.call(this, JSON.stringify(injectedBody));
}
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
- return originalSend.call(this, JSON.stringify(injectedBody));
}
}
}
- }
- return originalSend.apply(this, arguments);
- };
-})();
\ No newline at end of file
+ return originalSend.apply(this, arguments);
+ };
+})();
diff --git a/manifest.json b/manifest.json
index 78c3145..5c54ba4 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,41 +1,41 @@
{
- "manifest_version": 2,
- "name": "CDRM Extension 2.0",
- "version": "2.0",
- "description": "Decrypt DRM Protected content",
- "permissions": [
- "webRequest",
- "webRequestBlocking",
- "",
- "activeTab",
- "storage",
- "tabs",
- "contextMenus"
- ],
- "background": {
- "scripts": ["background.js"],
- "persistent": true
- },
- "content_scripts": [
- {
- "matches": [""],
- "js": ["content.js"],
- "run_at": "document_start",
- "all_frames": true
+ "manifest_version": 2,
+ "name": "CDRM Extension 2.0",
+ "version": "2.0",
+ "description": "Decrypt DRM Protected content",
+ "permissions": [
+ "webRequest",
+ "webRequestBlocking",
+ "",
+ "activeTab",
+ "storage",
+ "tabs",
+ "contextMenus"
+ ],
+ "background": {
+ "scripts": ["background.js"],
+ "persistent": true
+ },
+ "content_scripts": [
+ {
+ "matches": [""],
+ "js": ["content.js"],
+ "run_at": "document_start",
+ "all_frames": true
+ }
+ ],
+ "web_accessible_resources": ["inject.js"],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+ "browser_action": {
+ "default_icon": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+ },
+ "icons": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
}
- ],
- "web_accessible_resources": ["inject.js"],
- "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
- "browser_action": {
- "default_icon": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
- }
- },
- "icons": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
- }
}
--
2.43.0
From 935d235ad9f387cf1bde4e72be11030448e5bcd9 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 14:22:04 +0700
Subject: [PATCH 02/26] organize files and folders, remove unnecessary
generated build files, add new script to build extension to
`extension-release` folder
---
.gitignore | 30 ++
buildext.js | 65 ++++
frontend/dist/assets/index-UaipKa9p.css | 1 -
frontend/dist/index.html | 26 +-
frontend/package-lock.json | 487 ++++++++++++------------
frontend/package.json | 22 +-
package.json | 21 +
react/assets/index-UaipKa9p.css | 1 -
react/assets/index-ydPQKJSy.js | 52 ---
react/index.html | 13 -
background.js => src/background.js | 2 +-
content.js => src/content.js | 0
inject.js => src/inject.js | 0
manifest.json => src/manifest.json | 0
14 files changed, 382 insertions(+), 338 deletions(-)
create mode 100644 .gitignore
create mode 100644 buildext.js
delete mode 100644 frontend/dist/assets/index-UaipKa9p.css
create mode 100644 package.json
delete mode 100644 react/assets/index-UaipKa9p.css
delete mode 100644 react/assets/index-ydPQKJSy.js
delete mode 100644 react/index.html
rename background.js => src/background.js (98%)
rename content.js => src/content.js (100%)
rename inject.js => src/inject.js (100%)
rename manifest.json => src/manifest.json (100%)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..65e2b16
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+frontend/node_modules
+frontend/dist
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# extension release folder
+extension-release
diff --git a/buildext.js b/buildext.js
new file mode 100644
index 0000000..de5beb0
--- /dev/null
+++ b/buildext.js
@@ -0,0 +1,65 @@
+import { execSync } from "child_process";
+import fs from "fs";
+import path from "path";
+import url from "url";
+
+const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
+const frontendDir = path.join(__dirname, "frontend");
+const distDir = path.join(frontendDir, "dist");
+const srcDir = path.join(__dirname, "src");
+const iconDir = path.join(__dirname, "icons");
+const releaseDir = path.join(__dirname, "extension-release");
+
+function run(cmd, cwd) {
+ console.log(`🛠️ Running: ${cmd}`);
+ execSync(cmd, { cwd, stdio: "inherit" });
+}
+
+async function copyDir(src, dest) {
+ await fs.promises.mkdir(dest, { recursive: true });
+ await fs.promises.cp(src, dest, {
+ recursive: true,
+ force: true,
+ filter: (src) => !src.endsWith(".map"),
+ });
+}
+
+async function main() {
+ console.log("🚀 Starting extension build...");
+
+ // 1. Install frontend deps if needed
+ if (!fs.existsSync(path.join(frontendDir, "node_modules"))) {
+ console.log("📦 node_modules not found. Running npm install...");
+ run("npm install", frontendDir);
+ }
+
+ // 2. Build frontend
+ console.log("📦 Building frontend...");
+ run("npm run build", frontendDir);
+
+ // 3. Clean release folder
+ if (fs.existsSync(releaseDir)) {
+ console.log("🧹 Cleaning existing extension-release folder...");
+ await fs.promises.rm(releaseDir, { recursive: true, force: true });
+ }
+ await fs.promises.mkdir(releaseDir);
+
+ // 4. Copy src files (manifest, background, etc) to release
+ console.log("📦 Copying src files to extension-release...");
+ await copyDir(srcDir, releaseDir);
+
+ // 5. Copy frontend dist files to release (merged at root)
+ console.log("📦 Copying frontend dist files to extension-release...");
+ await copyDir(distDir, releaseDir);
+
+ // 6. Copy icon directory to release (merged at root)
+ console.log("📦 Copying icon directory to extension-release...");
+ await copyDir(iconDir, path.join(releaseDir, "icons"));
+
+ console.log("✅ Build complete! extension-release ready.");
+}
+
+main().catch((e) => {
+ console.error("❌ Build failed:", e);
+ process.exit(1);
+});
diff --git a/frontend/dist/assets/index-UaipKa9p.css b/frontend/dist/assets/index-UaipKa9p.css
deleted file mode 100644
index 7dcc3f4..0000000
--- a/frontend/dist/assets/index-UaipKa9p.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-duration:initial;--tw-ease:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-slate-800:oklch(27.9% .041 260.031);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-bold:700;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4,0,.2,1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.left-0{left:calc(var(--spacing)*0)}.z-20{z-index:20}.z-50{z-index:50}.m-1{margin:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-5{margin-top:calc(var(--spacing)*5)}.mr-2{margin-right:calc(var(--spacing)*2)}.ml-auto{margin-left:auto}.flex{display:flex}.h-10{height:calc(var(--spacing)*10)}.h-16{height:calc(var(--spacing)*16)}.h-64{height:calc(var(--spacing)*64)}.h-full{height:100%}.h-screen{height:100vh}.max-h-16{max-height:calc(var(--spacing)*16)}.min-h-16{min-height:calc(var(--spacing)*16)}.min-h-64{min-height:calc(var(--spacing)*64)}.min-h-full{min-height:100%}.w-16{width:calc(var(--spacing)*16)}.w-full{width:100%}.min-w-full{min-width:100%}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.items-center{align-items:center}.justify-center{justify-content:center}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-r-2{border-right-style:var(--tw-border-style);border-right-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-gray-700{border-color:var(--color-gray-700)}.border-r-white{border-right-color:var(--color-white)}.border-b-white{border-bottom-color:var(--color-white)}.border-l-white{border-left-color:var(--color-white)}.bg-black{background-color:var(--color-black)}.bg-black\/95{background-color:#000000f2}@supports (color:color-mix(in lab,red,red)){.bg-black\/95{background-color:color-mix(in oklab,var(--color-black)95%,transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-green-500\/70{background-color:#00c758b3}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/70{background-color:color-mix(in oklab,var(--color-green-500)70%,transparent)}}.bg-red-500\/70{background-color:#fb2c36b3}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/70{background-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/70{background-color:#00a5efb3}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/70{background-color:color-mix(in oklab,var(--color-sky-500)70%,transparent)}}.bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/50{background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-nowrap{text-wrap:nowrap}.whitespace-pre-line{white-space:pre-line}.text-gray-400{color:var(--color-gray-400)}.text-green-400{color:var(--color-green-400)}.text-red-400{color:var(--color-red-400)}.text-white{color:var(--color-white)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}@media (hover:hover){.hover\:cursor-pointer:hover{cursor:pointer}.hover\:border-l-1:hover{border-left-style:var(--tw-border-style);border-left-width:1px}.hover\:bg-black\/50:hover{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/50:hover{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-sky-600:hover{background-color:var(--color-sky-600)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}}html,body,#root{width:100%;height:100%;margin:0;padding:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
diff --git a/frontend/dist/index.html b/frontend/dist/index.html
index 0042fc4..7d51312 100644
--- a/frontend/dist/index.html
+++ b/frontend/dist/index.html
@@ -1,13 +1,13 @@
-
-
-
-
-
- CDRM Decryption Extension
-
-
-
-
-
-
-
+
+
+
+
+
+ CDRM Decryption Extension
+
+
+
+
+
+
+
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 39b3ac5..c86a3ab 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,22 +8,22 @@
"name": "frontend",
"version": "0.0.0",
"dependencies": {
- "@tailwindcss/vite": "^4.1.7",
+ "@tailwindcss/vite": "^4.1.11",
"react": "^19.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^7.6.1",
- "tailwindcss": "^4.1.7"
+ "react-router-dom": "^7.7.0",
+ "tailwindcss": "^4.1.11"
},
"devDependencies": {
- "@eslint/js": "^9.25.0",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "@vitejs/plugin-react": "^4.4.1",
- "eslint": "^9.25.0",
+ "@eslint/js": "^9.31.0",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@vitejs/plugin-react": "^4.7.0",
+ "eslint": "^9.31.0",
"eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.19",
- "globals": "^16.0.0",
- "vite": "^6.3.5"
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^7.0.5"
}
},
"node_modules/@ampproject/remapping": {
@@ -65,22 +65,22 @@
}
},
"node_modules/@babel/core": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
- "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
+ "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.27.1",
- "@babel/helper-compilation-targets": "^7.27.1",
- "@babel/helper-module-transforms": "^7.27.1",
- "@babel/helpers": "^7.27.1",
- "@babel/parser": "^7.27.1",
- "@babel/template": "^7.27.1",
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.27.3",
+ "@babel/helpers": "^7.27.6",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.0",
+ "@babel/types": "^7.28.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -96,16 +96,16 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
- "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
+ "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.27.1",
- "@babel/types": "^7.27.1",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
+ "@babel/parser": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"engines": {
@@ -129,6 +129,16 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-module-imports": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
@@ -144,15 +154,15 @@
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
- "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+ "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1",
- "@babel/traverse": "^7.27.1"
+ "@babel/traverse": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@@ -202,27 +212,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
- "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
+ "version": "7.27.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
+ "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.27.1",
- "@babel/types": "^7.27.1"
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.27.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
- "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
+ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.27.1"
+ "@babel/types": "^7.28.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -279,38 +289,28 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
- "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
+ "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.27.1",
- "@babel/parser": "^7.27.1",
- "@babel/template": "^7.27.1",
- "@babel/types": "^7.27.1",
- "debug": "^4.3.1",
- "globals": "^11.1.0"
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.0",
+ "debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/traverse/node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/@babel/types": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
- "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
+ "version": "7.28.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz",
+ "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -764,9 +764,9 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
- "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -779,9 +779,9 @@
}
},
"node_modules/@eslint/config-helpers": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
- "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
+ "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -789,9 +789,9 @@
}
},
"node_modules/@eslint/core": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
- "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
+ "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -839,9 +839,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.27.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
- "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
+ "version": "9.31.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz",
+ "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -862,13 +862,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
- "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz",
+ "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.14.0",
+ "@eslint/core": "^0.15.1",
"levn": "^0.4.1"
},
"engines": {
@@ -954,17 +954,13 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
- "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"license": "MIT",
"dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
@@ -976,15 +972,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/@jridgewell/set-array": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -992,15 +979,22 @@
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "version": "0.3.29",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.27",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+ "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.40.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz",
@@ -1262,9 +1256,9 @@
]
},
"node_modules/@tailwindcss/node": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
- "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz",
+ "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
@@ -1273,13 +1267,13 @@
"lightningcss": "1.30.1",
"magic-string": "^0.30.17",
"source-map-js": "^1.2.1",
- "tailwindcss": "4.1.7"
+ "tailwindcss": "4.1.11"
}
},
"node_modules/@tailwindcss/oxide": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
- "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz",
+ "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -1290,24 +1284,24 @@
"node": ">= 10"
},
"optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.1.7",
- "@tailwindcss/oxide-darwin-arm64": "4.1.7",
- "@tailwindcss/oxide-darwin-x64": "4.1.7",
- "@tailwindcss/oxide-freebsd-x64": "4.1.7",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
- "@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
- "@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
- "@tailwindcss/oxide-linux-x64-musl": "4.1.7",
- "@tailwindcss/oxide-wasm32-wasi": "4.1.7",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
- "@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
+ "@tailwindcss/oxide-android-arm64": "4.1.11",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.11",
+ "@tailwindcss/oxide-darwin-x64": "4.1.11",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.11",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.11",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.11",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.11",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.11",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.11"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
- "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz",
+ "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==",
"cpu": [
"arm64"
],
@@ -1321,9 +1315,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
- "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz",
+ "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==",
"cpu": [
"arm64"
],
@@ -1337,9 +1331,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
- "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz",
+ "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==",
"cpu": [
"x64"
],
@@ -1353,9 +1347,9 @@
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
- "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz",
+ "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==",
"cpu": [
"x64"
],
@@ -1369,9 +1363,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
- "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz",
+ "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==",
"cpu": [
"arm"
],
@@ -1385,9 +1379,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
- "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz",
+ "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==",
"cpu": [
"arm64"
],
@@ -1401,9 +1395,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
- "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz",
+ "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==",
"cpu": [
"arm64"
],
@@ -1417,9 +1411,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
- "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz",
+ "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==",
"cpu": [
"x64"
],
@@ -1433,9 +1427,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
- "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz",
+ "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==",
"cpu": [
"x64"
],
@@ -1449,9 +1443,9 @@
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
- "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz",
+ "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
@@ -1469,7 +1463,7 @@
"@emnapi/core": "^1.4.3",
"@emnapi/runtime": "^1.4.3",
"@emnapi/wasi-threads": "^1.0.2",
- "@napi-rs/wasm-runtime": "^0.2.9",
+ "@napi-rs/wasm-runtime": "^0.2.11",
"@tybys/wasm-util": "^0.9.0",
"tslib": "^2.8.0"
},
@@ -1478,9 +1472,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
- "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
+ "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==",
"cpu": [
"arm64"
],
@@ -1494,9 +1488,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
- "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz",
+ "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==",
"cpu": [
"x64"
],
@@ -1510,17 +1504,17 @@
}
},
"node_modules/@tailwindcss/vite": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz",
- "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz",
+ "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==",
"license": "MIT",
"dependencies": {
- "@tailwindcss/node": "4.1.7",
- "@tailwindcss/oxide": "4.1.7",
- "tailwindcss": "4.1.7"
+ "@tailwindcss/node": "4.1.11",
+ "@tailwindcss/oxide": "4.1.11",
+ "tailwindcss": "4.1.11"
},
"peerDependencies": {
- "vite": "^5.2.0 || ^6"
+ "vite": "^5.2.0 || ^6 || ^7"
}
},
"node_modules/@types/babel__core": {
@@ -1582,9 +1576,9 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "19.1.4",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz",
- "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==",
+ "version": "19.1.8",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
+ "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1592,9 +1586,9 @@
}
},
"node_modules/@types/react-dom": {
- "version": "19.1.5",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz",
- "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==",
+ "version": "19.1.6",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
+ "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -1602,15 +1596,16 @@
}
},
"node_modules/@vitejs/plugin-react": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz",
- "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==",
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
+ "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/core": "^7.26.10",
- "@babel/plugin-transform-react-jsx-self": "^7.25.9",
- "@babel/plugin-transform-react-jsx-source": "^7.25.9",
+ "@babel/core": "^7.28.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.27",
"@types/babel__core": "^7.20.5",
"react-refresh": "^0.17.0"
},
@@ -1618,13 +1613,13 @@
"node": "^14.18.0 || >=16.0.0"
},
"peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
"node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -1692,9 +1687,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1899,9 +1894,9 @@
"license": "ISC"
},
"node_modules/enhanced-resolve": {
- "version": "5.18.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
- "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
+ "version": "5.18.2",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
+ "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -1975,19 +1970,19 @@
}
},
"node_modules/eslint": {
- "version": "9.27.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
- "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
+ "version": "9.31.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz",
+ "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.20.0",
- "@eslint/config-helpers": "^0.2.1",
- "@eslint/core": "^0.14.0",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.0",
+ "@eslint/core": "^0.15.0",
"@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.27.0",
+ "@eslint/js": "9.31.0",
"@eslint/plugin-kit": "^0.3.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -1999,9 +1994,9 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.3.0",
- "eslint-visitor-keys": "^4.2.0",
- "espree": "^10.3.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
"esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -2059,9 +2054,9 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
- "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -2076,9 +2071,9 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
- "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -2089,15 +2084,15 @@
}
},
"node_modules/espree": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
- "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.14.0",
+ "acorn": "^8.15.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.0"
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2174,9 +2169,9 @@
"license": "MIT"
},
"node_modules/fdir": {
- "version": "6.4.4",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
- "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
@@ -2276,9 +2271,9 @@
}
},
"node_modules/globals": {
- "version": "16.1.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
- "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
+ "version": "16.3.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
+ "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2919,9 +2914,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
- "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -2931,9 +2926,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"funding": [
{
"type": "opencollective",
@@ -2950,7 +2945,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.8",
+ "nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -3010,9 +3005,9 @@
}
},
"node_modules/react-router": {
- "version": "7.6.1",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.1.tgz",
- "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.0.tgz",
+ "integrity": "sha512-3FUYSwlvB/5wRJVTL/aavqHmfUKe0+Xm9MllkYgGo9eDwNdkvwlJGjpPxono1kCycLt6AnDTgjmXvK3/B4QGuw==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
@@ -3032,12 +3027,12 @@
}
},
"node_modules/react-router-dom": {
- "version": "7.6.1",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.1.tgz",
- "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==",
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.0.tgz",
+ "integrity": "sha512-wwGS19VkNBkneVh9/YD0pK3IsjWxQUVMDD6drlG7eJpo1rXBtctBqDyBm/k+oKHRAm1x9XWT3JFC82QI9YOXXA==",
"license": "MIT",
"dependencies": {
- "react-router": "7.6.1"
+ "react-router": "7.7.0"
},
"engines": {
"node": ">=20.0.0"
@@ -3177,9 +3172,9 @@
}
},
"node_modules/tailwindcss": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
- "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
+ "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
"license": "MIT"
},
"node_modules/tapable": {
@@ -3218,9 +3213,9 @@
}
},
"node_modules/tinyglobby": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
- "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
+ "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
@@ -3288,23 +3283,23 @@
}
},
"node_modules/vite": {
- "version": "6.3.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
- "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.5.tgz",
+ "integrity": "sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==",
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",
- "fdir": "^6.4.4",
+ "fdir": "^6.4.6",
"picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
+ "postcss": "^8.5.6",
+ "rollup": "^4.40.0",
+ "tinyglobby": "^0.2.14"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ "node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
@@ -3313,14 +3308,14 @@
"fsevents": "~2.3.3"
},
"peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0",
- "less": "*",
+ "less": "^4.0.0",
"lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
"terser": "^5.16.0",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
diff --git a/frontend/package.json b/frontend/package.json
index 2998847..b4df8fd 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,21 +10,21 @@
"preview": "vite preview"
},
"dependencies": {
- "@tailwindcss/vite": "^4.1.7",
+ "@tailwindcss/vite": "^4.1.11",
"react": "^19.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^7.6.1",
- "tailwindcss": "^4.1.7"
+ "react-router-dom": "^7.7.0",
+ "tailwindcss": "^4.1.11"
},
"devDependencies": {
- "@eslint/js": "^9.25.0",
- "@types/react": "^19.1.2",
- "@types/react-dom": "^19.1.2",
- "@vitejs/plugin-react": "^4.4.1",
- "eslint": "^9.25.0",
+ "@eslint/js": "^9.31.0",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@vitejs/plugin-react": "^4.7.0",
+ "eslint": "^9.31.0",
"eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.19",
- "globals": "^16.0.0",
- "vite": "^6.3.5"
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^7.0.5"
}
}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..74ba2f6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "cdrm-extension",
+ "version": "1.0.0",
+ "description": "",
+ "main": "background.js",
+ "scripts": {
+ "buildext": "node buildext.js",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://cdm-project.com/tpd94/CDRM-Extension.git"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "type": "module",
+ "engines": {
+ "node": ">=21.0.0"
+ }
+}
diff --git a/react/assets/index-UaipKa9p.css b/react/assets/index-UaipKa9p.css
deleted file mode 100644
index 7dcc3f4..0000000
--- a/react/assets/index-UaipKa9p.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-duration:initial;--tw-ease:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-sky-500:oklch(68.5% .169 237.323);--color-sky-600:oklch(58.8% .158 241.966);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-slate-800:oklch(27.9% .041 260.031);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-bold:700;--radius-md:.375rem;--ease-in-out:cubic-bezier(.4,0,.2,1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.left-0{left:calc(var(--spacing)*0)}.z-20{z-index:20}.z-50{z-index:50}.m-1{margin:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-5{margin-top:calc(var(--spacing)*5)}.mr-2{margin-right:calc(var(--spacing)*2)}.ml-auto{margin-left:auto}.flex{display:flex}.h-10{height:calc(var(--spacing)*10)}.h-16{height:calc(var(--spacing)*16)}.h-64{height:calc(var(--spacing)*64)}.h-full{height:100%}.h-screen{height:100vh}.max-h-16{max-height:calc(var(--spacing)*16)}.min-h-16{min-height:calc(var(--spacing)*16)}.min-h-64{min-height:calc(var(--spacing)*64)}.min-h-full{min-height:100%}.w-16{width:calc(var(--spacing)*16)}.w-full{width:100%}.min-w-full{min-width:100%}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-0{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.items-center{align-items:center}.justify-center{justify-content:center}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-r-2{border-right-style:var(--tw-border-style);border-right-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-gray-700{border-color:var(--color-gray-700)}.border-r-white{border-right-color:var(--color-white)}.border-b-white{border-bottom-color:var(--color-white)}.border-l-white{border-left-color:var(--color-white)}.bg-black{background-color:var(--color-black)}.bg-black\/95{background-color:#000000f2}@supports (color:color-mix(in lab,red,red)){.bg-black\/95{background-color:color-mix(in oklab,var(--color-black)95%,transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-green-500\/70{background-color:#00c758b3}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/70{background-color:color-mix(in oklab,var(--color-green-500)70%,transparent)}}.bg-red-500\/70{background-color:#fb2c36b3}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/70{background-color:color-mix(in oklab,var(--color-red-500)70%,transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/70{background-color:#00a5efb3}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/70{background-color:color-mix(in oklab,var(--color-sky-500)70%,transparent)}}.bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.bg-slate-800\/50{background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-nowrap{text-wrap:nowrap}.whitespace-pre-line{white-space:pre-line}.text-gray-400{color:var(--color-gray-400)}.text-green-400{color:var(--color-green-400)}.text-red-400{color:var(--color-red-400)}.text-white{color:var(--color-white)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,visibility,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}@media (hover:hover){.hover\:cursor-pointer:hover{cursor:pointer}.hover\:border-l-1:hover{border-left-style:var(--tw-border-style);border-left-width:1px}.hover\:bg-black\/50:hover{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/50:hover{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-sky-600:hover{background-color:var(--color-sky-600)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}}html,body,#root{width:100%;height:100%;margin:0;padding:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
diff --git a/react/assets/index-ydPQKJSy.js b/react/assets/index-ydPQKJSy.js
deleted file mode 100644
index e29c9f8..0000000
--- a/react/assets/index-ydPQKJSy.js
+++ /dev/null
@@ -1,52 +0,0 @@
-(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const h of document.querySelectorAll('link[rel="modulepreload"]'))r(h);new MutationObserver(h=>{for(const v of h)if(v.type==="childList")for(const T of v.addedNodes)T.tagName==="LINK"&&T.rel==="modulepreload"&&r(T)}).observe(document,{childList:!0,subtree:!0});function s(h){const v={};return h.integrity&&(v.integrity=h.integrity),h.referrerPolicy&&(v.referrerPolicy=h.referrerPolicy),h.crossOrigin==="use-credentials"?v.credentials="include":h.crossOrigin==="anonymous"?v.credentials="omit":v.credentials="same-origin",v}function r(h){if(h.ep)return;h.ep=!0;const v=s(h);fetch(h.href,v)}})();var pf={exports:{}},Ou={};/**
- * @license React
- * react-jsx-runtime.production.js
- *
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */var C0;function U1(){if(C0)return Ou;C0=1;var c=Symbol.for("react.transitional.element"),o=Symbol.for("react.fragment");function s(r,h,v){var T=null;if(v!==void 0&&(T=""+v),h.key!==void 0&&(T=""+h.key),"key"in h){v={};for(var O in h)O!=="key"&&(v[O]=h[O])}else v=h;return h=v.ref,{$$typeof:c,type:r,key:T,ref:h!==void 0?h:null,props:v}}return Ou.Fragment=o,Ou.jsx=s,Ou.jsxs=s,Ou}var U0;function N1(){return U0||(U0=1,pf.exports=U1()),pf.exports}var K=N1(),Sf={exports:{}},et={};/**
- * @license React
- * react.production.js
- *
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */var N0;function H1(){if(N0)return et;N0=1;var c=Symbol.for("react.transitional.element"),o=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),h=Symbol.for("react.profiler"),v=Symbol.for("react.consumer"),T=Symbol.for("react.context"),O=Symbol.for("react.forward_ref"),p=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),R=Symbol.for("react.lazy"),w=Symbol.iterator;function C(y){return y===null||typeof y!="object"?null:(y=w&&y[w]||y["@@iterator"],typeof y=="function"?y:null)}var B={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},H=Object.assign,G={};function Q(y,N,X){this.props=y,this.context=N,this.refs=G,this.updater=X||B}Q.prototype.isReactComponent={},Q.prototype.setState=function(y,N){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,N,"setState")},Q.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function L(){}L.prototype=Q.prototype;function Y(y,N,X){this.props=y,this.context=N,this.refs=G,this.updater=X||B}var $=Y.prototype=new L;$.constructor=Y,H($,Q.prototype),$.isPureReactComponent=!0;var it=Array.isArray,I={H:null,A:null,T:null,S:null,V:null},zt=Object.prototype.hasOwnProperty;function Rt(y,N,X,q,J,ft){return X=ft.ref,{$$typeof:c,type:y,key:N,ref:X!==void 0?X:null,props:ft}}function Ot(y,N){return Rt(y.type,N,void 0,void 0,void 0,y.props)}function St(y){return typeof y=="object"&&y!==null&&y.$$typeof===c}function Jt(y){var N={"=":"=0",":":"=2"};return"$"+y.replace(/[=:]/g,function(X){return N[X]})}var oe=/\/+/g;function Xt(y,N){return typeof y=="object"&&y!==null&&y.key!=null?Jt(""+y.key):N.toString(36)}function El(){}function Tl(y){switch(y.status){case"fulfilled":return y.value;case"rejected":throw y.reason;default:switch(typeof y.status=="string"?y.then(El,El):(y.status="pending",y.then(function(N){y.status==="pending"&&(y.status="fulfilled",y.value=N)},function(N){y.status==="pending"&&(y.status="rejected",y.reason=N)})),y.status){case"fulfilled":return y.value;case"rejected":throw y.reason}}throw y}function Vt(y,N,X,q,J){var ft=typeof y;(ft==="undefined"||ft==="boolean")&&(y=null);var tt=!1;if(y===null)tt=!0;else switch(ft){case"bigint":case"string":case"number":tt=!0;break;case"object":switch(y.$$typeof){case c:case o:tt=!0;break;case R:return tt=y._init,Vt(tt(y._payload),N,X,q,J)}}if(tt)return J=J(y),tt=q===""?"."+Xt(y,0):q,it(J)?(X="",tt!=null&&(X=tt.replace(oe,"$&/")+"/"),Vt(J,N,X,"",function($e){return $e})):J!=null&&(St(J)&&(J=Ot(J,X+(J.key==null||y&&y.key===J.key?"":(""+J.key).replace(oe,"$&/")+"/")+tt)),N.push(J)),1;tt=0;var te=q===""?".":q+":";if(it(y))for(var bt=0;bt>>1,y=M[yt];if(0>>1;yth(q,F))Jh(ft,q)?(M[yt]=ft,M[J]=F,yt=J):(M[yt]=q,M[X]=F,yt=X);else if(Jh(ft,F))M[yt]=ft,M[J]=F,yt=J;else break t}}return j}function h(M,j){var F=M.sortIndex-j.sortIndex;return F!==0?F:M.id-j.id}if(c.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var v=performance;c.unstable_now=function(){return v.now()}}else{var T=Date,O=T.now();c.unstable_now=function(){return T.now()-O}}var p=[],d=[],R=1,w=null,C=3,B=!1,H=!1,G=!1,Q=!1,L=typeof setTimeout=="function"?setTimeout:null,Y=typeof clearTimeout=="function"?clearTimeout:null,$=typeof setImmediate<"u"?setImmediate:null;function it(M){for(var j=s(d);j!==null;){if(j.callback===null)r(d);else if(j.startTime<=M)r(d),j.sortIndex=j.expirationTime,o(p,j);else break;j=s(d)}}function I(M){if(G=!1,it(M),!H)if(s(p)!==null)H=!0,zt||(zt=!0,Xt());else{var j=s(d);j!==null&&Vt(I,j.startTime-M)}}var zt=!1,Rt=-1,Ot=5,St=-1;function Jt(){return Q?!0:!(c.unstable_now()-StM&&Jt());){var yt=w.callback;if(typeof yt=="function"){w.callback=null,C=w.priorityLevel;var y=yt(w.expirationTime<=M);if(M=c.unstable_now(),typeof y=="function"){w.callback=y,it(M),j=!0;break e}w===s(p)&&r(p),it(M)}else r(p);w=s(p)}if(w!==null)j=!0;else{var N=s(d);N!==null&&Vt(I,N.startTime-M),j=!1}}break t}finally{w=null,C=F,B=!1}j=void 0}}finally{j?Xt():zt=!1}}}var Xt;if(typeof $=="function")Xt=function(){$(oe)};else if(typeof MessageChannel<"u"){var El=new MessageChannel,Tl=El.port2;El.port1.onmessage=oe,Xt=function(){Tl.postMessage(null)}}else Xt=function(){L(oe,0)};function Vt(M,j){Rt=L(function(){M(c.unstable_now())},j)}c.unstable_IdlePriority=5,c.unstable_ImmediatePriority=1,c.unstable_LowPriority=4,c.unstable_NormalPriority=3,c.unstable_Profiling=null,c.unstable_UserBlockingPriority=2,c.unstable_cancelCallback=function(M){M.callback=null},c.unstable_forceFrameRate=function(M){0>M||125yt?(M.sortIndex=F,o(d,M),s(p)===null&&M===s(d)&&(G?(Y(Rt),Rt=-1):G=!0,Vt(I,F-yt))):(M.sortIndex=y,o(p,M),H||B||(H=!0,zt||(zt=!0,Xt()))),M},c.unstable_shouldYield=Jt,c.unstable_wrapCallback=function(M){var j=C;return function(){var F=C;C=j;try{return M.apply(this,arguments)}finally{C=F}}}}(Tf)),Tf}var L0;function L1(){return L0||(L0=1,Ef.exports=w1()),Ef.exports}var xf={exports:{}},Kt={};/**
- * @license React
- * react-dom.production.js
- *
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */var B0;function B1(){if(B0)return Kt;B0=1;var c=Mf();function o(p){var d="https://react.dev/errors/"+p;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(o){console.error(o)}}return c(),xf.exports=B1(),xf.exports}/**
- * @license React
- * react-dom-client.production.js
- *
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */var j0;function j1(){if(j0)return Du;j0=1;var c=L1(),o=Mf(),s=q1();function r(t){var e="https://react.dev/errors/"+t;if(1y||(t.current=yt[y],yt[y]=null,y--)}function q(t,e){y++,yt[y]=t.current,t.current=e}var J=N(null),ft=N(null),tt=N(null),te=N(null);function bt(t,e){switch(q(tt,e),q(ft,t),q(J,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?n0(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=n0(e),t=i0(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}X(J),q(J,t)}function $e(){X(J),X(ft),X(tt)}function li(t){t.memoizedState!==null&&q(te,t);var e=J.current,l=i0(e,t.type);e!==l&&(q(ft,t),q(J,l))}function Hu(t){ft.current===t&&(X(J),X(ft)),te.current===t&&(X(te),Tu._currentValue=F)}var ai=Object.prototype.hasOwnProperty,ui=c.unstable_scheduleCallback,ni=c.unstable_cancelCallback,od=c.unstable_shouldYield,sd=c.unstable_requestPaint,Ae=c.unstable_now,dd=c.unstable_getCurrentPriorityLevel,qf=c.unstable_ImmediatePriority,jf=c.unstable_UserBlockingPriority,wu=c.unstable_NormalPriority,hd=c.unstable_LowPriority,Yf=c.unstable_IdlePriority,md=c.log,vd=c.unstable_setDisableYieldValue,za=null,ee=null;function We(t){if(typeof md=="function"&&vd(t),ee&&typeof ee.setStrictMode=="function")try{ee.setStrictMode(za,t)}catch{}}var le=Math.clz32?Math.clz32:pd,yd=Math.log,gd=Math.LN2;function pd(t){return t>>>=0,t===0?32:31-(yd(t)/gd|0)|0}var Lu=256,Bu=4194304;function xl(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function qu(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var u=0,n=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var f=a&134217727;return f!==0?(a=f&~n,a!==0?u=xl(a):(i&=f,i!==0?u=xl(i):l||(l=f&~t,l!==0&&(u=xl(l))))):(f=a&~n,f!==0?u=xl(f):i!==0?u=xl(i):l||(l=a&~t,l!==0&&(u=xl(l)))),u===0?0:e!==0&&e!==u&&(e&n)===0&&(n=u&-u,l=e&-e,n>=l||n===32&&(l&4194048)!==0)?e:u}function Ca(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function Sd(t,e){switch(t){case 1:case 2:case 4:case 8:case 64:return e+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Gf(){var t=Lu;return Lu<<=1,(Lu&4194048)===0&&(Lu=256),t}function Xf(){var t=Bu;return Bu<<=1,(Bu&62914560)===0&&(Bu=4194304),t}function ii(t){for(var e=[],l=0;31>l;l++)e.push(t);return e}function Ua(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function bd(t,e,l,a,u,n){var i=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var f=t.entanglements,m=t.expirationTimes,E=t.hiddenUpdates;for(l=i&~l;0)":-1u||m[a]!==E[u]){var D=`
-`+m[a].replace(" at new "," at ");return t.displayName&&D.includes("")&&(D=D.replace("",t.displayName)),D}while(1<=a&&0<=u);break}}}finally{di=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?Jl(l):""}function _d(t){switch(t.tag){case 26:case 27:case 5:return Jl(t.type);case 16:return Jl("Lazy");case 13:return Jl("Suspense");case 19:return Jl("SuspenseList");case 0:case 15:return hi(t.type,!1);case 11:return hi(t.type.render,!1);case 1:return hi(t.type,!0);case 31:return Jl("Activity");default:return""}}function Pf(t){try{var e="";do e+=_d(t),t=t.return;while(t);return e}catch(l){return`
-Error generating stack: `+l.message+`
-`+l.stack}}function se(t){switch(typeof t){case"bigint":case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function If(t){var e=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(e==="checkbox"||e==="radio")}function Od(t){var e=If(t)?"checked":"value",l=Object.getOwnPropertyDescriptor(t.constructor.prototype,e),a=""+t[e];if(!t.hasOwnProperty(e)&&typeof l<"u"&&typeof l.get=="function"&&typeof l.set=="function"){var u=l.get,n=l.set;return Object.defineProperty(t,e,{configurable:!0,get:function(){return u.call(this)},set:function(i){a=""+i,n.call(this,i)}}),Object.defineProperty(t,e,{enumerable:l.enumerable}),{getValue:function(){return a},setValue:function(i){a=""+i},stopTracking:function(){t._valueTracker=null,delete t[e]}}}}function Gu(t){t._valueTracker||(t._valueTracker=Od(t))}function tr(t){if(!t)return!1;var e=t._valueTracker;if(!e)return!0;var l=e.getValue(),a="";return t&&(a=If(t)?t.checked?"true":"false":t.value),t=a,t!==l?(e.setValue(t),!0):!1}function Xu(t){if(t=t||(typeof document<"u"?document:void 0),typeof t>"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var Dd=/[\n"\\]/g;function de(t){return t.replace(Dd,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function mi(t,e,l,a,u,n,i,f){t.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?t.type=i:t.removeAttribute("type"),e!=null?i==="number"?(e===0&&t.value===""||t.value!=e)&&(t.value=""+se(e)):t.value!==""+se(e)&&(t.value=""+se(e)):i!=="submit"&&i!=="reset"||t.removeAttribute("value"),e!=null?vi(t,i,se(e)):l!=null?vi(t,i,se(l)):a!=null&&t.removeAttribute("value"),u==null&&n!=null&&(t.defaultChecked=!!n),u!=null&&(t.checked=u&&typeof u!="function"&&typeof u!="symbol"),f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?t.name=""+se(f):t.removeAttribute("name")}function er(t,e,l,a,u,n,i,f){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(t.type=n),e!=null||l!=null){if(!(n!=="submit"&&n!=="reset"||e!=null))return;l=l!=null?""+se(l):"",e=e!=null?""+se(e):l,f||e===t.value||(t.value=e),t.defaultValue=e}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,t.checked=f?t.checked:!!a,t.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(t.name=i)}function vi(t,e,l){e==="number"&&Xu(t.ownerDocument)===t||t.defaultValue===""+l||(t.defaultValue=""+l)}function kl(t,e,l,a){if(t=t.options,e){e={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),bi=!1;if(Ne)try{var La={};Object.defineProperty(La,"passive",{get:function(){bi=!0}}),window.addEventListener("test",La,La),window.removeEventListener("test",La,La)}catch{bi=!1}var Pe=null,Ei=null,Qu=null;function fr(){if(Qu)return Qu;var t,e=Ei,l=e.length,a,u="value"in Pe?Pe.value:Pe.textContent,n=u.length;for(t=0;t=ja),mr=" ",vr=!1;function yr(t,e){switch(t){case"keyup":return lh.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function gr(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Pl=!1;function uh(t,e){switch(t){case"compositionend":return gr(e);case"keypress":return e.which!==32?null:(vr=!0,mr);case"textInput":return t=e.data,t===mr&&vr?null:t;default:return null}}function nh(t,e){if(Pl)return t==="compositionend"||!_i&&yr(t,e)?(t=fr(),Qu=Ei=Pe=null,Pl=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=Ar(l)}}function Or(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?Or(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function Dr(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=Xu(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=Xu(t.document)}return e}function Mi(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var hh=Ne&&"documentMode"in document&&11>=document.documentMode,Il=null,zi=null,Va=null,Ci=!1;function Mr(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Ci||Il==null||Il!==Xu(a)||(a=Il,"selectionStart"in a&&Mi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Va&&Xa(Va,a)||(Va=a,a=wn(zi,"onSelect"),0>=i,u-=i,we=1<<32-le(e)+u|l<n?n:8;var i=M.T,f={};M.T=f,yc(t,!1,e,l);try{var m=u(),E=M.S;if(E!==null&&E(f,m),m!==null&&typeof m=="object"&&typeof m.then=="function"){var D=Th(m,a);uu(t,e,D,fe(t))}else uu(t,e,a,fe(t))}catch(U){uu(t,e,{then:function(){},status:"rejected",reason:U},fe())}finally{j.p=n,M.T=i}}function Oh(){}function mc(t,e,l,a){if(t.tag!==5)throw Error(r(476));var u=Co(t).queue;zo(t,u,e,F,l===null?Oh:function(){return Uo(t),l(a)})}function Co(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:F,baseState:F,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:je,lastRenderedState:F},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:je,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function Uo(t){var e=Co(t).next.queue;uu(t,e,{},fe())}function vc(){return Zt(Tu)}function No(){return Ut().memoizedState}function Ho(){return Ut().memoizedState}function Dh(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=fe();t=el(l);var a=ll(e,t,l);a!==null&&(re(a,e,l),Pa(a,e,l)),e={cache:Zi()},t.payload=e;return}e=e.return}}function Mh(t,e,l){var a=fe();l={lane:a,revertLane:0,action:l,hasEagerState:!1,eagerState:null,next:null},vn(t)?Lo(e,l):(l=wi(t,e,l,a),l!==null&&(re(l,t,a),Bo(l,e,a)))}function wo(t,e,l){var a=fe();uu(t,e,l,a)}function uu(t,e,l,a){var u={lane:a,revertLane:0,action:l,hasEagerState:!1,eagerState:null,next:null};if(vn(t))Lo(e,u);else{var n=t.alternate;if(t.lanes===0&&(n===null||n.lanes===0)&&(n=e.lastRenderedReducer,n!==null))try{var i=e.lastRenderedState,f=n(i,l);if(u.hasEagerState=!0,u.eagerState=f,ae(f,i))return Fu(t,e,u,0),pt===null&&Wu(),!1}catch{}finally{}if(l=wi(t,e,u,a),l!==null)return re(l,t,a),Bo(l,e,a),!0}return!1}function yc(t,e,l,a){if(a={lane:2,revertLane:kc(),action:a,hasEagerState:!1,eagerState:null,next:null},vn(t)){if(e)throw Error(r(479))}else e=wi(t,l,a,2),e!==null&&re(e,t,2)}function vn(t){var e=t.alternate;return t===lt||e!==null&&e===lt}function Lo(t,e){ra=rn=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function Bo(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,Qf(t,l)}}var yn={readContext:Zt,use:sn,useCallback:Dt,useContext:Dt,useEffect:Dt,useImperativeHandle:Dt,useLayoutEffect:Dt,useInsertionEffect:Dt,useMemo:Dt,useReducer:Dt,useRef:Dt,useState:Dt,useDebugValue:Dt,useDeferredValue:Dt,useTransition:Dt,useSyncExternalStore:Dt,useId:Dt,useHostTransitionStatus:Dt,useFormState:Dt,useActionState:Dt,useOptimistic:Dt,useMemoCache:Dt,useCacheRefresh:Dt},qo={readContext:Zt,use:sn,useCallback:function(t,e){return Ft().memoizedState=[t,e===void 0?null:e],t},useContext:Zt,useEffect:Eo,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,mn(4194308,4,Ao.bind(null,e,t),l)},useLayoutEffect:function(t,e){return mn(4194308,4,t,e)},useInsertionEffect:function(t,e){mn(4,2,t,e)},useMemo:function(t,e){var l=Ft();e=e===void 0?null:e;var a=t();if(Ll){We(!0);try{t()}finally{We(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=Ft();if(l!==void 0){var u=l(e);if(Ll){We(!0);try{l(e)}finally{We(!1)}}}else u=e;return a.memoizedState=a.baseState=u,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:u},a.queue=t,t=t.dispatch=Mh.bind(null,lt,t),[a.memoizedState,t]},useRef:function(t){var e=Ft();return t={current:t},e.memoizedState=t},useState:function(t){t=oc(t);var e=t.queue,l=wo.bind(null,lt,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:dc,useDeferredValue:function(t,e){var l=Ft();return hc(l,t,e)},useTransition:function(){var t=oc(!1);return t=zo.bind(null,lt,t.queue,!0,!1),Ft().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=lt,u=Ft();if(ot){if(l===void 0)throw Error(r(407));l=l()}else{if(l=e(),pt===null)throw Error(r(349));(ct&124)!==0||uo(a,e,l)}u.memoizedState=l;var n={value:l,getSnapshot:e};return u.queue=n,Eo(io.bind(null,a,n,t),[t]),a.flags|=2048,sa(9,hn(),no.bind(null,a,n,l,e),null),l},useId:function(){var t=Ft(),e=pt.identifierPrefix;if(ot){var l=Le,a=we;l=(a&~(1<<32-le(a)-1)).toString(32)+l,e="«"+e+"R"+l,l=on++,0W?(qt=Z,Z=null):qt=Z.sibling;var rt=x(S,Z,b[W],z);if(rt===null){Z===null&&(Z=qt);break}t&&Z&&rt.alternate===null&&e(S,Z),g=n(rt,g,W),at===null?V=rt:at.sibling=rt,at=rt,Z=qt}if(W===b.length)return l(S,Z),ot&&zl(S,W),V;if(Z===null){for(;WW?(qt=Z,Z=null):qt=Z.sibling;var Sl=x(S,Z,rt.value,z);if(Sl===null){Z===null&&(Z=qt);break}t&&Z&&Sl.alternate===null&&e(S,Z),g=n(Sl,g,W),at===null?V=Sl:at.sibling=Sl,at=Sl,Z=qt}if(rt.done)return l(S,Z),ot&&zl(S,W),V;if(Z===null){for(;!rt.done;W++,rt=b.next())rt=U(S,rt.value,z),rt!==null&&(g=n(rt,g,W),at===null?V=rt:at.sibling=rt,at=rt);return ot&&zl(S,W),V}for(Z=a(Z);!rt.done;W++,rt=b.next())rt=A(Z,S,W,rt.value,z),rt!==null&&(t&&rt.alternate!==null&&Z.delete(rt.key===null?W:rt.key),g=n(rt,g,W),at===null?V=rt:at.sibling=rt,at=rt);return t&&Z.forEach(function(C1){return e(S,C1)}),ot&&zl(S,W),V}function vt(S,g,b,z){if(typeof b=="object"&&b!==null&&b.type===H&&b.key===null&&(b=b.props.children),typeof b=="object"&&b!==null){switch(b.$$typeof){case C:t:{for(var V=b.key;g!==null;){if(g.key===V){if(V=b.type,V===H){if(g.tag===7){l(S,g.sibling),z=u(g,b.props.children),z.return=S,S=z;break t}}else if(g.elementType===V||typeof V=="object"&&V!==null&&V.$$typeof===Ot&&Yo(V)===g.type){l(S,g.sibling),z=u(g,b.props),iu(z,b),z.return=S,S=z;break t}l(S,g);break}else e(S,g);g=g.sibling}b.type===H?(z=Dl(b.props.children,S.mode,z,b.key),z.return=S,S=z):(z=Iu(b.type,b.key,b.props,null,S.mode,z),iu(z,b),z.return=S,S=z)}return i(S);case B:t:{for(V=b.key;g!==null;){if(g.key===V)if(g.tag===4&&g.stateNode.containerInfo===b.containerInfo&&g.stateNode.implementation===b.implementation){l(S,g.sibling),z=u(g,b.children||[]),z.return=S,S=z;break t}else{l(S,g);break}else e(S,g);g=g.sibling}z=qi(b,S.mode,z),z.return=S,S=z}return i(S);case Ot:return V=b._init,b=V(b._payload),vt(S,g,b,z)}if(Vt(b))return P(S,g,b,z);if(Xt(b)){if(V=Xt(b),typeof V!="function")throw Error(r(150));return b=V.call(b),k(S,g,b,z)}if(typeof b.then=="function")return vt(S,g,gn(b),z);if(b.$$typeof===$)return vt(S,g,an(S,b),z);pn(S,b)}return typeof b=="string"&&b!==""||typeof b=="number"||typeof b=="bigint"?(b=""+b,g!==null&&g.tag===6?(l(S,g.sibling),z=u(g,b),z.return=S,S=z):(l(S,g),z=Bi(b,S.mode,z),z.return=S,S=z),i(S)):l(S,g)}return function(S,g,b,z){try{nu=0;var V=vt(S,g,b,z);return da=null,V}catch(Z){if(Z===Wa||Z===nn)throw Z;var at=ue(29,Z,null,S.mode);return at.lanes=z,at.return=S,at}finally{}}}var ha=Go(!0),Xo=Go(!1),ge=N(null),Oe=null;function ul(t){var e=t.alternate;q(Ht,Ht.current&1),q(ge,t),Oe===null&&(e===null||fa.current!==null||e.memoizedState!==null)&&(Oe=t)}function Vo(t){if(t.tag===22){if(q(Ht,Ht.current),q(ge,t),Oe===null){var e=t.alternate;e!==null&&e.memoizedState!==null&&(Oe=t)}}else nl()}function nl(){q(Ht,Ht.current),q(ge,ge.current)}function Ye(t){X(ge),Oe===t&&(Oe=null),X(Ht)}var Ht=N(0);function Sn(t){for(var e=t;e!==null;){if(e.tag===13){var l=e.memoizedState;if(l!==null&&(l=l.dehydrated,l===null||l.data==="$?"||cf(l)))return e}else if(e.tag===19&&e.memoizedProps.revealOrder!==void 0){if((e.flags&128)!==0)return e}else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break;for(;e.sibling===null;){if(e.return===null||e.return===t)return null;e=e.return}e.sibling.return=e.return,e=e.sibling}return null}function gc(t,e,l,a){e=t.memoizedState,l=l(a,e),l=l==null?e:R({},e,l),t.memoizedState=l,t.lanes===0&&(t.updateQueue.baseState=l)}var pc={enqueueSetState:function(t,e,l){t=t._reactInternals;var a=fe(),u=el(a);u.payload=e,l!=null&&(u.callback=l),e=ll(t,u,a),e!==null&&(re(e,t,a),Pa(e,t,a))},enqueueReplaceState:function(t,e,l){t=t._reactInternals;var a=fe(),u=el(a);u.tag=1,u.payload=e,l!=null&&(u.callback=l),e=ll(t,u,a),e!==null&&(re(e,t,a),Pa(e,t,a))},enqueueForceUpdate:function(t,e){t=t._reactInternals;var l=fe(),a=el(l);a.tag=2,e!=null&&(a.callback=e),e=ll(t,a,l),e!==null&&(re(e,t,l),Pa(e,t,l))}};function Qo(t,e,l,a,u,n,i){return t=t.stateNode,typeof t.shouldComponentUpdate=="function"?t.shouldComponentUpdate(a,n,i):e.prototype&&e.prototype.isPureReactComponent?!Xa(l,a)||!Xa(u,n):!0}function Zo(t,e,l,a){t=e.state,typeof e.componentWillReceiveProps=="function"&&e.componentWillReceiveProps(l,a),typeof e.UNSAFE_componentWillReceiveProps=="function"&&e.UNSAFE_componentWillReceiveProps(l,a),e.state!==t&&pc.enqueueReplaceState(e,e.state,null)}function Bl(t,e){var l=e;if("ref"in e){l={};for(var a in e)a!=="ref"&&(l[a]=e[a])}if(t=t.defaultProps){l===e&&(l=R({},l));for(var u in t)l[u]===void 0&&(l[u]=t[u])}return l}var bn=typeof reportError=="function"?reportError:function(t){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var e=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof t=="object"&&t!==null&&typeof t.message=="string"?String(t.message):String(t),error:t});if(!window.dispatchEvent(e))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",t);return}console.error(t)};function Ko(t){bn(t)}function Jo(t){console.error(t)}function ko(t){bn(t)}function En(t,e){try{var l=t.onUncaughtError;l(e.value,{componentStack:e.stack})}catch(a){setTimeout(function(){throw a})}}function $o(t,e,l){try{var a=t.onCaughtError;a(l.value,{componentStack:l.stack,errorBoundary:e.tag===1?e.stateNode:null})}catch(u){setTimeout(function(){throw u})}}function Sc(t,e,l){return l=el(l),l.tag=3,l.payload={element:null},l.callback=function(){En(t,e)},l}function Wo(t){return t=el(t),t.tag=3,t}function Fo(t,e,l,a){var u=l.type.getDerivedStateFromError;if(typeof u=="function"){var n=a.value;t.payload=function(){return u(n)},t.callback=function(){$o(e,l,a)}}var i=l.stateNode;i!==null&&typeof i.componentDidCatch=="function"&&(t.callback=function(){$o(e,l,a),typeof u!="function"&&(sl===null?sl=new Set([this]):sl.add(this));var f=a.stack;this.componentDidCatch(a.value,{componentStack:f!==null?f:""})})}function Ch(t,e,l,a,u){if(l.flags|=32768,a!==null&&typeof a=="object"&&typeof a.then=="function"){if(e=l.alternate,e!==null&&Ja(e,l,u,!0),l=ge.current,l!==null){switch(l.tag){case 13:return Oe===null?Vc():l.alternate===null&&_t===0&&(_t=3),l.flags&=-257,l.flags|=65536,l.lanes=u,a===ki?l.flags|=16384:(e=l.updateQueue,e===null?l.updateQueue=new Set([a]):e.add(a),Zc(t,a,u)),!1;case 22:return l.flags|=65536,a===ki?l.flags|=16384:(e=l.updateQueue,e===null?(e={transitions:null,markerInstances:null,retryQueue:new Set([a])},l.updateQueue=e):(l=e.retryQueue,l===null?e.retryQueue=new Set([a]):l.add(a)),Zc(t,a,u)),!1}throw Error(r(435,l.tag))}return Zc(t,a,u),Vc(),!1}if(ot)return e=ge.current,e!==null?((e.flags&65536)===0&&(e.flags|=256),e.flags|=65536,e.lanes=u,a!==Gi&&(t=Error(r(422),{cause:a}),Ka(he(t,l)))):(a!==Gi&&(e=Error(r(423),{cause:a}),Ka(he(e,l))),t=t.current.alternate,t.flags|=65536,u&=-u,t.lanes|=u,a=he(a,l),u=Sc(t.stateNode,a,u),Fi(t,u),_t!==4&&(_t=2)),!1;var n=Error(r(520),{cause:a});if(n=he(n,l),hu===null?hu=[n]:hu.push(n),_t!==4&&(_t=2),e===null)return!0;a=he(a,l),l=e;do{switch(l.tag){case 3:return l.flags|=65536,t=u&-u,l.lanes|=t,t=Sc(l.stateNode,a,t),Fi(l,t),!1;case 1:if(e=l.type,n=l.stateNode,(l.flags&128)===0&&(typeof e.getDerivedStateFromError=="function"||n!==null&&typeof n.componentDidCatch=="function"&&(sl===null||!sl.has(n))))return l.flags|=65536,u&=-u,l.lanes|=u,u=Wo(u),Fo(u,t,l,a),Fi(l,u),!1}l=l.return}while(l!==null);return!1}var Po=Error(r(461)),Lt=!1;function jt(t,e,l,a){e.child=t===null?Xo(e,null,l,a):ha(e,t.child,l,a)}function Io(t,e,l,a,u){l=l.render;var n=e.ref;if("ref"in a){var i={};for(var f in a)f!=="ref"&&(i[f]=a[f])}else i=a;return Hl(e),a=lc(t,e,l,i,n,u),f=ac(),t!==null&&!Lt?(uc(t,e,u),Ge(t,e,u)):(ot&&f&&ji(e),e.flags|=1,jt(t,e,a,u),e.child)}function ts(t,e,l,a,u){if(t===null){var n=l.type;return typeof n=="function"&&!Li(n)&&n.defaultProps===void 0&&l.compare===null?(e.tag=15,e.type=n,es(t,e,n,a,u)):(t=Iu(l.type,null,a,e,e.mode,u),t.ref=e.ref,t.return=e,e.child=t)}if(n=t.child,!Oc(t,u)){var i=n.memoizedProps;if(l=l.compare,l=l!==null?l:Xa,l(i,a)&&t.ref===e.ref)return Ge(t,e,u)}return e.flags|=1,t=He(n,a),t.ref=e.ref,t.return=e,e.child=t}function es(t,e,l,a,u){if(t!==null){var n=t.memoizedProps;if(Xa(n,a)&&t.ref===e.ref)if(Lt=!1,e.pendingProps=a=n,Oc(t,u))(t.flags&131072)!==0&&(Lt=!0);else return e.lanes=t.lanes,Ge(t,e,u)}return bc(t,e,l,a,u)}function ls(t,e,l){var a=e.pendingProps,u=a.children,n=t!==null?t.memoizedState:null;if(a.mode==="hidden"){if((e.flags&128)!==0){if(a=n!==null?n.baseLanes|l:l,t!==null){for(u=e.child=t.child,n=0;u!==null;)n=n|u.lanes|u.childLanes,u=u.sibling;e.childLanes=n&~a}else e.childLanes=0,e.child=null;return as(t,e,a,l)}if((l&536870912)!==0)e.memoizedState={baseLanes:0,cachePool:null},t!==null&&un(e,n!==null?n.cachePool:null),n!==null?to(e,n):Ii(),Vo(e);else return e.lanes=e.childLanes=536870912,as(t,e,n!==null?n.baseLanes|l:l,l)}else n!==null?(un(e,n.cachePool),to(e,n),nl(),e.memoizedState=null):(t!==null&&un(e,null),Ii(),nl());return jt(t,e,u,l),e.child}function as(t,e,l,a){var u=Ji();return u=u===null?null:{parent:Nt._currentValue,pool:u},e.memoizedState={baseLanes:l,cachePool:u},t!==null&&un(e,null),Ii(),Vo(e),t!==null&&Ja(t,e,a,!0),null}function Tn(t,e){var l=e.ref;if(l===null)t!==null&&t.ref!==null&&(e.flags|=4194816);else{if(typeof l!="function"&&typeof l!="object")throw Error(r(284));(t===null||t.ref!==l)&&(e.flags|=4194816)}}function bc(t,e,l,a,u){return Hl(e),l=lc(t,e,l,a,void 0,u),a=ac(),t!==null&&!Lt?(uc(t,e,u),Ge(t,e,u)):(ot&&a&&ji(e),e.flags|=1,jt(t,e,l,u),e.child)}function us(t,e,l,a,u,n){return Hl(e),e.updateQueue=null,l=lo(e,a,l,u),eo(t),a=ac(),t!==null&&!Lt?(uc(t,e,n),Ge(t,e,n)):(ot&&a&&ji(e),e.flags|=1,jt(t,e,l,n),e.child)}function ns(t,e,l,a,u){if(Hl(e),e.stateNode===null){var n=aa,i=l.contextType;typeof i=="object"&&i!==null&&(n=Zt(i)),n=new l(a,n),e.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,n.updater=pc,e.stateNode=n,n._reactInternals=e,n=e.stateNode,n.props=a,n.state=e.memoizedState,n.refs={},$i(e),i=l.contextType,n.context=typeof i=="object"&&i!==null?Zt(i):aa,n.state=e.memoizedState,i=l.getDerivedStateFromProps,typeof i=="function"&&(gc(e,l,i,a),n.state=e.memoizedState),typeof l.getDerivedStateFromProps=="function"||typeof n.getSnapshotBeforeUpdate=="function"||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(i=n.state,typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount(),i!==n.state&&pc.enqueueReplaceState(n,n.state,null),tu(e,a,n,u),Ia(),n.state=e.memoizedState),typeof n.componentDidMount=="function"&&(e.flags|=4194308),a=!0}else if(t===null){n=e.stateNode;var f=e.memoizedProps,m=Bl(l,f);n.props=m;var E=n.context,D=l.contextType;i=aa,typeof D=="object"&&D!==null&&(i=Zt(D));var U=l.getDerivedStateFromProps;D=typeof U=="function"||typeof n.getSnapshotBeforeUpdate=="function",f=e.pendingProps!==f,D||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(f||E!==i)&&Zo(e,n,a,i),tl=!1;var x=e.memoizedState;n.state=x,tu(e,a,n,u),Ia(),E=e.memoizedState,f||x!==E||tl?(typeof U=="function"&&(gc(e,l,U,a),E=e.memoizedState),(m=tl||Qo(e,l,m,a,x,E,i))?(D||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount()),typeof n.componentDidMount=="function"&&(e.flags|=4194308)):(typeof n.componentDidMount=="function"&&(e.flags|=4194308),e.memoizedProps=a,e.memoizedState=E),n.props=a,n.state=E,n.context=i,a=m):(typeof n.componentDidMount=="function"&&(e.flags|=4194308),a=!1)}else{n=e.stateNode,Wi(t,e),i=e.memoizedProps,D=Bl(l,i),n.props=D,U=e.pendingProps,x=n.context,E=l.contextType,m=aa,typeof E=="object"&&E!==null&&(m=Zt(E)),f=l.getDerivedStateFromProps,(E=typeof f=="function"||typeof n.getSnapshotBeforeUpdate=="function")||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(i!==U||x!==m)&&Zo(e,n,a,m),tl=!1,x=e.memoizedState,n.state=x,tu(e,a,n,u),Ia();var A=e.memoizedState;i!==U||x!==A||tl||t!==null&&t.dependencies!==null&&ln(t.dependencies)?(typeof f=="function"&&(gc(e,l,f,a),A=e.memoizedState),(D=tl||Qo(e,l,D,a,x,A,m)||t!==null&&t.dependencies!==null&&ln(t.dependencies))?(E||typeof n.UNSAFE_componentWillUpdate!="function"&&typeof n.componentWillUpdate!="function"||(typeof n.componentWillUpdate=="function"&&n.componentWillUpdate(a,A,m),typeof n.UNSAFE_componentWillUpdate=="function"&&n.UNSAFE_componentWillUpdate(a,A,m)),typeof n.componentDidUpdate=="function"&&(e.flags|=4),typeof n.getSnapshotBeforeUpdate=="function"&&(e.flags|=1024)):(typeof n.componentDidUpdate!="function"||i===t.memoizedProps&&x===t.memoizedState||(e.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||i===t.memoizedProps&&x===t.memoizedState||(e.flags|=1024),e.memoizedProps=a,e.memoizedState=A),n.props=a,n.state=A,n.context=m,a=D):(typeof n.componentDidUpdate!="function"||i===t.memoizedProps&&x===t.memoizedState||(e.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||i===t.memoizedProps&&x===t.memoizedState||(e.flags|=1024),a=!1)}return n=a,Tn(t,e),a=(e.flags&128)!==0,n||a?(n=e.stateNode,l=a&&typeof l.getDerivedStateFromError!="function"?null:n.render(),e.flags|=1,t!==null&&a?(e.child=ha(e,t.child,null,u),e.child=ha(e,null,l,u)):jt(t,e,l,u),e.memoizedState=n.state,t=e.child):t=Ge(t,e,u),t}function is(t,e,l,a){return Za(),e.flags|=256,jt(t,e,l,a),e.child}var Ec={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Tc(t){return{baseLanes:t,cachePool:Kr()}}function xc(t,e,l){return t=t!==null?t.childLanes&~l:0,e&&(t|=pe),t}function cs(t,e,l){var a=e.pendingProps,u=!1,n=(e.flags&128)!==0,i;if((i=n)||(i=t!==null&&t.memoizedState===null?!1:(Ht.current&2)!==0),i&&(u=!0,e.flags&=-129),i=(e.flags&32)!==0,e.flags&=-33,t===null){if(ot){if(u?ul(e):nl(),ot){var f=At,m;if(m=f){t:{for(m=f,f=_e;m.nodeType!==8;){if(!f){f=null;break t}if(m=xe(m.nextSibling),m===null){f=null;break t}}f=m}f!==null?(e.memoizedState={dehydrated:f,treeContext:Ml!==null?{id:we,overflow:Le}:null,retryLane:536870912,hydrationErrors:null},m=ue(18,null,null,0),m.stateNode=f,m.return=e,e.child=m,kt=e,At=null,m=!0):m=!1}m||Ul(e)}if(f=e.memoizedState,f!==null&&(f=f.dehydrated,f!==null))return cf(f)?e.lanes=32:e.lanes=536870912,null;Ye(e)}return f=a.children,a=a.fallback,u?(nl(),u=e.mode,f=xn({mode:"hidden",children:f},u),a=Dl(a,u,l,null),f.return=e,a.return=e,f.sibling=a,e.child=f,u=e.child,u.memoizedState=Tc(l),u.childLanes=xc(t,i,l),e.memoizedState=Ec,a):(ul(e),Rc(e,f))}if(m=t.memoizedState,m!==null&&(f=m.dehydrated,f!==null)){if(n)e.flags&256?(ul(e),e.flags&=-257,e=Ac(t,e,l)):e.memoizedState!==null?(nl(),e.child=t.child,e.flags|=128,e=null):(nl(),u=a.fallback,f=e.mode,a=xn({mode:"visible",children:a.children},f),u=Dl(u,f,l,null),u.flags|=2,a.return=e,u.return=e,a.sibling=u,e.child=a,ha(e,t.child,null,l),a=e.child,a.memoizedState=Tc(l),a.childLanes=xc(t,i,l),e.memoizedState=Ec,e=u);else if(ul(e),cf(f)){if(i=f.nextSibling&&f.nextSibling.dataset,i)var E=i.dgst;i=E,a=Error(r(419)),a.stack="",a.digest=i,Ka({value:a,source:null,stack:null}),e=Ac(t,e,l)}else if(Lt||Ja(t,e,l,!1),i=(l&t.childLanes)!==0,Lt||i){if(i=pt,i!==null&&(a=l&-l,a=(a&42)!==0?1:ci(a),a=(a&(i.suspendedLanes|l))!==0?0:a,a!==0&&a!==m.retryLane))throw m.retryLane=a,la(t,a),re(i,t,a),Po;f.data==="$?"||Vc(),e=Ac(t,e,l)}else f.data==="$?"?(e.flags|=192,e.child=t.child,e=null):(t=m.treeContext,At=xe(f.nextSibling),kt=e,ot=!0,Cl=null,_e=!1,t!==null&&(ve[ye++]=we,ve[ye++]=Le,ve[ye++]=Ml,we=t.id,Le=t.overflow,Ml=e),e=Rc(e,a.children),e.flags|=4096);return e}return u?(nl(),u=a.fallback,f=e.mode,m=t.child,E=m.sibling,a=He(m,{mode:"hidden",children:a.children}),a.subtreeFlags=m.subtreeFlags&65011712,E!==null?u=He(E,u):(u=Dl(u,f,l,null),u.flags|=2),u.return=e,a.return=e,a.sibling=u,e.child=a,a=u,u=e.child,f=t.child.memoizedState,f===null?f=Tc(l):(m=f.cachePool,m!==null?(E=Nt._currentValue,m=m.parent!==E?{parent:E,pool:E}:m):m=Kr(),f={baseLanes:f.baseLanes|l,cachePool:m}),u.memoizedState=f,u.childLanes=xc(t,i,l),e.memoizedState=Ec,a):(ul(e),l=t.child,t=l.sibling,l=He(l,{mode:"visible",children:a.children}),l.return=e,l.sibling=null,t!==null&&(i=e.deletions,i===null?(e.deletions=[t],e.flags|=16):i.push(t)),e.child=l,e.memoizedState=null,l)}function Rc(t,e){return e=xn({mode:"visible",children:e},t.mode),e.return=t,t.child=e}function xn(t,e){return t=ue(22,t,null,e),t.lanes=0,t.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},t}function Ac(t,e,l){return ha(e,t.child,null,l),t=Rc(e,e.pendingProps.children),t.flags|=2,e.memoizedState=null,t}function fs(t,e,l){t.lanes|=e;var a=t.alternate;a!==null&&(a.lanes|=e),Vi(t.return,e,l)}function _c(t,e,l,a,u){var n=t.memoizedState;n===null?t.memoizedState={isBackwards:e,rendering:null,renderingStartTime:0,last:a,tail:l,tailMode:u}:(n.isBackwards=e,n.rendering=null,n.renderingStartTime=0,n.last=a,n.tail=l,n.tailMode=u)}function rs(t,e,l){var a=e.pendingProps,u=a.revealOrder,n=a.tail;if(jt(t,e,a.children,l),a=Ht.current,(a&2)!==0)a=a&1|2,e.flags|=128;else{if(t!==null&&(t.flags&128)!==0)t:for(t=e.child;t!==null;){if(t.tag===13)t.memoizedState!==null&&fs(t,l,e);else if(t.tag===19)fs(t,l,e);else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break t;for(;t.sibling===null;){if(t.return===null||t.return===e)break t;t=t.return}t.sibling.return=t.return,t=t.sibling}a&=1}switch(q(Ht,a),u){case"forwards":for(l=e.child,u=null;l!==null;)t=l.alternate,t!==null&&Sn(t)===null&&(u=l),l=l.sibling;l=u,l===null?(u=e.child,e.child=null):(u=l.sibling,l.sibling=null),_c(e,!1,u,l,n);break;case"backwards":for(l=null,u=e.child,e.child=null;u!==null;){if(t=u.alternate,t!==null&&Sn(t)===null){e.child=u;break}t=u.sibling,u.sibling=l,l=u,u=t}_c(e,!0,l,null,n);break;case"together":_c(e,!1,null,null,void 0);break;default:e.memoizedState=null}return e.child}function Ge(t,e,l){if(t!==null&&(e.dependencies=t.dependencies),ol|=e.lanes,(l&e.childLanes)===0)if(t!==null){if(Ja(t,e,l,!1),(l&e.childLanes)===0)return null}else return null;if(t!==null&&e.child!==t.child)throw Error(r(153));if(e.child!==null){for(t=e.child,l=He(t,t.pendingProps),e.child=l,l.return=e;t.sibling!==null;)t=t.sibling,l=l.sibling=He(t,t.pendingProps),l.return=e;l.sibling=null}return e.child}function Oc(t,e){return(t.lanes&e)!==0?!0:(t=t.dependencies,!!(t!==null&&ln(t)))}function Uh(t,e,l){switch(e.tag){case 3:bt(e,e.stateNode.containerInfo),Ie(e,Nt,t.memoizedState.cache),Za();break;case 27:case 5:li(e);break;case 4:bt(e,e.stateNode.containerInfo);break;case 10:Ie(e,e.type,e.memoizedProps.value);break;case 13:var a=e.memoizedState;if(a!==null)return a.dehydrated!==null?(ul(e),e.flags|=128,null):(l&e.child.childLanes)!==0?cs(t,e,l):(ul(e),t=Ge(t,e,l),t!==null?t.sibling:null);ul(e);break;case 19:var u=(t.flags&128)!==0;if(a=(l&e.childLanes)!==0,a||(Ja(t,e,l,!1),a=(l&e.childLanes)!==0),u){if(a)return rs(t,e,l);e.flags|=128}if(u=e.memoizedState,u!==null&&(u.rendering=null,u.tail=null,u.lastEffect=null),q(Ht,Ht.current),a)break;return null;case 22:case 23:return e.lanes=0,ls(t,e,l);case 24:Ie(e,Nt,t.memoizedState.cache)}return Ge(t,e,l)}function os(t,e,l){if(t!==null)if(t.memoizedProps!==e.pendingProps)Lt=!0;else{if(!Oc(t,l)&&(e.flags&128)===0)return Lt=!1,Uh(t,e,l);Lt=(t.flags&131072)!==0}else Lt=!1,ot&&(e.flags&1048576)!==0&&jr(e,en,e.index);switch(e.lanes=0,e.tag){case 16:t:{t=e.pendingProps;var a=e.elementType,u=a._init;if(a=u(a._payload),e.type=a,typeof a=="function")Li(a)?(t=Bl(a,t),e.tag=1,e=ns(null,e,a,t,l)):(e.tag=0,e=bc(null,e,a,t,l));else{if(a!=null){if(u=a.$$typeof,u===it){e.tag=11,e=Io(null,e,a,t,l);break t}else if(u===Rt){e.tag=14,e=ts(null,e,a,t,l);break t}}throw e=Tl(a)||a,Error(r(306,e,""))}}return e;case 0:return bc(t,e,e.type,e.pendingProps,l);case 1:return a=e.type,u=Bl(a,e.pendingProps),ns(t,e,a,u,l);case 3:t:{if(bt(e,e.stateNode.containerInfo),t===null)throw Error(r(387));a=e.pendingProps;var n=e.memoizedState;u=n.element,Wi(t,e),tu(e,a,null,l);var i=e.memoizedState;if(a=i.cache,Ie(e,Nt,a),a!==n.cache&&Qi(e,[Nt],l,!0),Ia(),a=i.element,n.isDehydrated)if(n={element:a,isDehydrated:!1,cache:i.cache},e.updateQueue.baseState=n,e.memoizedState=n,e.flags&256){e=is(t,e,a,l);break t}else if(a!==u){u=he(Error(r(424)),e),Ka(u),e=is(t,e,a,l);break t}else{switch(t=e.stateNode.containerInfo,t.nodeType){case 9:t=t.body;break;default:t=t.nodeName==="HTML"?t.ownerDocument.body:t}for(At=xe(t.firstChild),kt=e,ot=!0,Cl=null,_e=!0,l=Xo(e,null,a,l),e.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling}else{if(Za(),a===u){e=Ge(t,e,l);break t}jt(t,e,a,l)}e=e.child}return e;case 26:return Tn(t,e),t===null?(l=m0(e.type,null,e.pendingProps,null))?e.memoizedState=l:ot||(l=e.type,t=e.pendingProps,a=Bn(tt.current).createElement(l),a[Qt]=e,a[$t]=t,Gt(a,l,t),wt(a),e.stateNode=a):e.memoizedState=m0(e.type,t.memoizedProps,e.pendingProps,t.memoizedState),null;case 27:return li(e),t===null&&ot&&(a=e.stateNode=s0(e.type,e.pendingProps,tt.current),kt=e,_e=!0,u=At,ml(e.type)?(ff=u,At=xe(a.firstChild)):At=u),jt(t,e,e.pendingProps.children,l),Tn(t,e),t===null&&(e.flags|=4194304),e.child;case 5:return t===null&&ot&&((u=a=At)&&(a=i1(a,e.type,e.pendingProps,_e),a!==null?(e.stateNode=a,kt=e,At=xe(a.firstChild),_e=!1,u=!0):u=!1),u||Ul(e)),li(e),u=e.type,n=e.pendingProps,i=t!==null?t.memoizedProps:null,a=n.children,af(u,n)?a=null:i!==null&&af(u,i)&&(e.flags|=32),e.memoizedState!==null&&(u=lc(t,e,Rh,null,null,l),Tu._currentValue=u),Tn(t,e),jt(t,e,a,l),e.child;case 6:return t===null&&ot&&((t=l=At)&&(l=c1(l,e.pendingProps,_e),l!==null?(e.stateNode=l,kt=e,At=null,t=!0):t=!1),t||Ul(e)),null;case 13:return cs(t,e,l);case 4:return bt(e,e.stateNode.containerInfo),a=e.pendingProps,t===null?e.child=ha(e,null,a,l):jt(t,e,a,l),e.child;case 11:return Io(t,e,e.type,e.pendingProps,l);case 7:return jt(t,e,e.pendingProps,l),e.child;case 8:return jt(t,e,e.pendingProps.children,l),e.child;case 12:return jt(t,e,e.pendingProps.children,l),e.child;case 10:return a=e.pendingProps,Ie(e,e.type,a.value),jt(t,e,a.children,l),e.child;case 9:return u=e.type._context,a=e.pendingProps.children,Hl(e),u=Zt(u),a=a(u),e.flags|=1,jt(t,e,a,l),e.child;case 14:return ts(t,e,e.type,e.pendingProps,l);case 15:return es(t,e,e.type,e.pendingProps,l);case 19:return rs(t,e,l);case 31:return a=e.pendingProps,l=e.mode,a={mode:a.mode,children:a.children},t===null?(l=xn(a,l),l.ref=e.ref,e.child=l,l.return=e,e=l):(l=He(t.child,a),l.ref=e.ref,e.child=l,l.return=e,e=l),e;case 22:return ls(t,e,l);case 24:return Hl(e),a=Zt(Nt),t===null?(u=Ji(),u===null&&(u=pt,n=Zi(),u.pooledCache=n,n.refCount++,n!==null&&(u.pooledCacheLanes|=l),u=n),e.memoizedState={parent:a,cache:u},$i(e),Ie(e,Nt,u)):((t.lanes&l)!==0&&(Wi(t,e),tu(e,null,null,l),Ia()),u=t.memoizedState,n=e.memoizedState,u.parent!==a?(u={parent:a,cache:a},e.memoizedState=u,e.lanes===0&&(e.memoizedState=e.updateQueue.baseState=u),Ie(e,Nt,a)):(a=n.cache,Ie(e,Nt,a),a!==u.cache&&Qi(e,[Nt],l,!0))),jt(t,e,e.pendingProps.children,l),e.child;case 29:throw e.pendingProps}throw Error(r(156,e.tag))}function Xe(t){t.flags|=4}function ss(t,e){if(e.type!=="stylesheet"||(e.state.loading&4)!==0)t.flags&=-16777217;else if(t.flags|=16777216,!S0(e)){if(e=ge.current,e!==null&&((ct&4194048)===ct?Oe!==null:(ct&62914560)!==ct&&(ct&536870912)===0||e!==Oe))throw Fa=ki,Jr;t.flags|=8192}}function Rn(t,e){e!==null&&(t.flags|=4),t.flags&16384&&(e=t.tag!==22?Xf():536870912,t.lanes|=e,ga|=e)}function cu(t,e){if(!ot)switch(t.tailMode){case"hidden":e=t.tail;for(var l=null;e!==null;)e.alternate!==null&&(l=e),e=e.sibling;l===null?t.tail=null:l.sibling=null;break;case"collapsed":l=t.tail;for(var a=null;l!==null;)l.alternate!==null&&(a=l),l=l.sibling;a===null?e||t.tail===null?t.tail=null:t.tail.sibling=null:a.sibling=null}}function xt(t){var e=t.alternate!==null&&t.alternate.child===t.child,l=0,a=0;if(e)for(var u=t.child;u!==null;)l|=u.lanes|u.childLanes,a|=u.subtreeFlags&65011712,a|=u.flags&65011712,u.return=t,u=u.sibling;else for(u=t.child;u!==null;)l|=u.lanes|u.childLanes,a|=u.subtreeFlags,a|=u.flags,u.return=t,u=u.sibling;return t.subtreeFlags|=a,t.childLanes=l,e}function Nh(t,e,l){var a=e.pendingProps;switch(Yi(e),e.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return xt(e),null;case 1:return xt(e),null;case 3:return l=e.stateNode,a=null,t!==null&&(a=t.memoizedState.cache),e.memoizedState.cache!==a&&(e.flags|=2048),qe(Nt),$e(),l.pendingContext&&(l.context=l.pendingContext,l.pendingContext=null),(t===null||t.child===null)&&(Qa(e)?Xe(e):t===null||t.memoizedState.isDehydrated&&(e.flags&256)===0||(e.flags|=1024,Xr())),xt(e),null;case 26:return l=e.memoizedState,t===null?(Xe(e),l!==null?(xt(e),ss(e,l)):(xt(e),e.flags&=-16777217)):l?l!==t.memoizedState?(Xe(e),xt(e),ss(e,l)):(xt(e),e.flags&=-16777217):(t.memoizedProps!==a&&Xe(e),xt(e),e.flags&=-16777217),null;case 27:Hu(e),l=tt.current;var u=e.type;if(t!==null&&e.stateNode!=null)t.memoizedProps!==a&&Xe(e);else{if(!a){if(e.stateNode===null)throw Error(r(166));return xt(e),null}t=J.current,Qa(e)?Yr(e):(t=s0(u,a,l),e.stateNode=t,Xe(e))}return xt(e),null;case 5:if(Hu(e),l=e.type,t!==null&&e.stateNode!=null)t.memoizedProps!==a&&Xe(e);else{if(!a){if(e.stateNode===null)throw Error(r(166));return xt(e),null}if(t=J.current,Qa(e))Yr(e);else{switch(u=Bn(tt.current),t){case 1:t=u.createElementNS("http://www.w3.org/2000/svg",l);break;case 2:t=u.createElementNS("http://www.w3.org/1998/Math/MathML",l);break;default:switch(l){case"svg":t=u.createElementNS("http://www.w3.org/2000/svg",l);break;case"math":t=u.createElementNS("http://www.w3.org/1998/Math/MathML",l);break;case"script":t=u.createElement("div"),t.innerHTML="
-
-
-
-
-
-
diff --git a/background.js b/src/background.js
similarity index 98%
rename from background.js
rename to src/background.js
index 331927d..bb1e2be 100644
--- a/background.js
+++ b/src/background.js
@@ -1,7 +1,7 @@
// Open popout window when the extension icon is clicked
chrome.browserAction.onClicked.addListener(() => {
chrome.windows.create({
- url: chrome.runtime.getURL("react/index.html"),
+ url: chrome.runtime.getURL("index.html"),
type: "popup", // opens as a floating window
width: 800,
height: 600,
diff --git a/content.js b/src/content.js
similarity index 100%
rename from content.js
rename to src/content.js
diff --git a/inject.js b/src/inject.js
similarity index 100%
rename from inject.js
rename to src/inject.js
diff --git a/manifest.json b/src/manifest.json
similarity index 100%
rename from manifest.json
rename to src/manifest.json
--
2.43.0
From 53aa7d66e3c73771093f7c6613d03e575a7fd24a Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 14:24:03 +0700
Subject: [PATCH 03/26] remove leftover dist folder
---
frontend/dist/index.html | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 frontend/dist/index.html
diff --git a/frontend/dist/index.html b/frontend/dist/index.html
deleted file mode 100644
index 7d51312..0000000
--- a/frontend/dist/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- CDRM Decryption Extension
-
-
-
-
-
-
-
--
2.43.0
From 9c738d8a3eff4b6352bb3aff5cfbe8fcf078492c Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 15:03:43 +0700
Subject: [PATCH 04/26] dynamically add version to extension title bar and
manifest.json, add readme
---
README.md | 49 ++++++++++++++++++++++++
buildext.js | 15 +++++---
frontend/index.html | 2 +-
frontend/package.json | 58 ++++++++++++++--------------
frontend/vite.config.js | 18 +++++++--
package.json | 2 +-
src/manifest.json | 84 ++++++++++++++++++++++-------------------
syncVersion.js | 46 ++++++++++++++++++++++
8 files changed, 196 insertions(+), 78 deletions(-)
create mode 100644 README.md
create mode 100644 syncVersion.js
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..16ce2fc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,49 @@
+# CDRM Extension
+
+An extension to show keys from DRM protected content, which are used to decrypt content.
+
+## Notes
+
+Keep these extension core files inside `src`:
+
+- `background.js`
+- `content.js`
+- `inject.js`
+- `manifest.json`
+
+Frontend React source stays in `frontend`.
+
+The build process will take care of everything into `extension-release`.
+
+To update the version across the entire project, simply change the version number in the root `package.json`. The build script will handle version sync automatically to both the extension's version and the frontend's title bar.
+
+## Build instructions
+
+### Prerequisites
+
+- Node.js v21 or higher. [Download Node.js here](https://nodejs.org/en/download).
+
+### How to build by yourself
+
+- Open terminal at the project root
+
+- Run the build script:
+
+```bash
+npm run buildext
+```
+
+This will:
+
+- Sync the version number from the root `package.json` to `src/manifest.json` and `frontend/package.json`
+- Install frontend dependencies if needed
+- Build the React frontend
+- Clean and prepare the `extension-release` folder
+- Copy extension files in `src`, built frontend assets, and icons into `extension-release`
+
+### How to load the extension in Google Chrome or Chromium browsers
+
+1. Go to `chrome://extensions/`
+2. Enable **Developer mode**
+3. Click **Load unpacked** and select the `extension-release` folder
+4. Verify the extension is working by clicking its icon or opening the developer console (F12) to check for any logs or errors.
diff --git a/buildext.js b/buildext.js
index de5beb0..632d6fb 100644
--- a/buildext.js
+++ b/buildext.js
@@ -2,6 +2,7 @@ import { execSync } from "child_process";
import fs from "fs";
import path from "path";
import url from "url";
+import syncVersion from "./syncVersion.js";
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const frontendDir = path.join(__dirname, "frontend");
@@ -10,21 +11,23 @@ const srcDir = path.join(__dirname, "src");
const iconDir = path.join(__dirname, "icons");
const releaseDir = path.join(__dirname, "extension-release");
-function run(cmd, cwd) {
+const run = (cmd, cwd) => {
console.log(`🛠️ Running: ${cmd}`);
execSync(cmd, { cwd, stdio: "inherit" });
-}
+};
-async function copyDir(src, dest) {
+const copyDir = async (src, dest) => {
await fs.promises.mkdir(dest, { recursive: true });
await fs.promises.cp(src, dest, {
recursive: true,
force: true,
filter: (src) => !src.endsWith(".map"),
});
-}
+};
+
+const main = async () => {
+ await syncVersion();
-async function main() {
console.log("🚀 Starting extension build...");
// 1. Install frontend deps if needed
@@ -57,7 +60,7 @@ async function main() {
await copyDir(iconDir, path.join(releaseDir, "icons"));
console.log("✅ Build complete! extension-release ready.");
-}
+};
main().catch((e) => {
console.error("❌ Build failed:", e);
diff --git a/frontend/index.html b/frontend/index.html
index e830ac7..cb4ef3c 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -3,7 +3,7 @@
- CDRM Decryption Extension
+ CDRM Decryption Extension v%APPVERSION%
diff --git a/frontend/package.json b/frontend/package.json
index b4df8fd..326d96a 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,30 +1,30 @@
{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "eslint .",
- "preview": "vite preview"
- },
- "dependencies": {
- "@tailwindcss/vite": "^4.1.11",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-router-dom": "^7.7.0",
- "tailwindcss": "^4.1.11"
- },
- "devDependencies": {
- "@eslint/js": "^9.31.0",
- "@types/react": "^19.1.8",
- "@types/react-dom": "^19.1.6",
- "@vitejs/plugin-react": "^4.7.0",
- "eslint": "^9.31.0",
- "eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.20",
- "globals": "^16.3.0",
- "vite": "^7.0.5"
- }
-}
+ "name": "frontend",
+ "private": true,
+ "version": "2.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tailwindcss/vite": "^4.1.11",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.7.0",
+ "tailwindcss": "^4.1.11"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.31.0",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@vitejs/plugin-react": "^4.7.0",
+ "eslint": "^9.31.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^7.0.5"
+ }
+}
\ No newline at end of file
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index a4c9f4d..01889a6 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -1,9 +1,21 @@
-import { defineConfig } from "vite";
-import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
+import react from "@vitejs/plugin-react";
+import { readFileSync } from "fs";
+import { defineConfig } from "vite";
+
+const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
+
+const replaceVersionPlugin = () => {
+ return {
+ name: "replace-version",
+ transformIndexHtml(html) {
+ return html.replace("%APPVERSION%", packageJson.version);
+ },
+ };
+};
// https://vite.dev/config/
export default defineConfig({
base: "./",
- plugins: [react(), tailwindcss()],
+ plugins: [react(), tailwindcss(), replaceVersionPlugin()],
});
diff --git a/package.json b/package.json
index 74ba2f6..2372915 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cdrm-extension",
- "version": "1.0.0",
+ "version": "2.1.0",
"description": "",
"main": "background.js",
"scripts": {
diff --git a/src/manifest.json b/src/manifest.json
index 5c54ba4..00a5ab7 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,41 +1,49 @@
{
- "manifest_version": 2,
- "name": "CDRM Extension 2.0",
- "version": "2.0",
- "description": "Decrypt DRM Protected content",
- "permissions": [
- "webRequest",
- "webRequestBlocking",
- "",
- "activeTab",
- "storage",
- "tabs",
- "contextMenus"
+ "manifest_version": 2,
+ "name": "CDRM Extension",
+ "version": "2.1.0",
+ "description": "Decrypt DRM protected content",
+ "permissions": [
+ "webRequest",
+ "webRequestBlocking",
+ "",
+ "activeTab",
+ "storage",
+ "tabs",
+ "contextMenus"
+ ],
+ "background": {
+ "scripts": [
+ "background.js"
],
- "background": {
- "scripts": ["background.js"],
- "persistent": true
- },
- "content_scripts": [
- {
- "matches": [""],
- "js": ["content.js"],
- "run_at": "document_start",
- "all_frames": true
- }
- ],
- "web_accessible_resources": ["inject.js"],
- "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
- "browser_action": {
- "default_icon": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
- }
- },
- "icons": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
+ "persistent": true
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ ""
+ ],
+ "js": [
+ "content.js"
+ ],
+ "run_at": "document_start",
+ "all_frames": true
}
-}
+ ],
+ "web_accessible_resources": [
+ "inject.js"
+ ],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+ "browser_action": {
+ "default_icon": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+ },
+ "icons": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+}
\ No newline at end of file
diff --git a/syncVersion.js b/syncVersion.js
new file mode 100644
index 0000000..7acba5d
--- /dev/null
+++ b/syncVersion.js
@@ -0,0 +1,46 @@
+import fs from "fs/promises";
+import path from "path";
+import { fileURLToPath } from "url";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const syncVersion = async () => {
+ const rootPkgPath = path.join(__dirname, "package.json");
+ const frontendPkgPath = path.join(__dirname, "frontend", "package.json");
+ const manifestPath = path.join(__dirname, "src", "manifest.json");
+
+ // Read root package.json version
+ const rootPkgRaw = await fs.readFile(rootPkgPath, "utf-8");
+ const rootPkg = JSON.parse(rootPkgRaw);
+ const version = rootPkg.version;
+
+ if (!version) {
+ console.warn("⚠️ No version field found in root package.json, skipping sync.");
+ return;
+ }
+
+ // Update frontend/package.json if exists
+ try {
+ const frontendPkgRaw = await fs.readFile(frontendPkgPath, "utf-8");
+ const frontendPkg = JSON.parse(frontendPkgRaw);
+ frontendPkg.version = version;
+ await fs.writeFile(frontendPkgPath, JSON.stringify(frontendPkg, null, 2));
+ console.log(`🔄 Updated frontend/package.json version to ${version}`);
+ } catch {
+ console.log("ℹ️ frontend/package.json not found or unreadable, skipping version update.");
+ }
+
+ // Update src/manifest.json version
+ try {
+ const manifestRaw = await fs.readFile(manifestPath, "utf-8");
+ const manifest = JSON.parse(manifestRaw);
+ manifest.version = version;
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
+ console.log(`🔄 Updated src/manifest.json version to ${version}`);
+ } catch (err) {
+ console.error(`❌ Failed to update src/manifest.json version: ${err.message}`);
+ }
+};
+
+export default syncVersion;
--
2.43.0
From 5678c9b5da37f141f43a26c484bae010d06297d7 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 16:00:59 +0700
Subject: [PATCH 05/26] add manifest URL in frontend
---
frontend/index.html | 2 +-
frontend/src/components/results.jsx | 44 +++++++++++++++++++++++------
src/background.js | 5 ++++
3 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/frontend/index.html b/frontend/index.html
index cb4ef3c..8d5c386 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -2,7 +2,7 @@
-
+
CDRM Decryption Extension v%APPVERSION%
diff --git a/frontend/src/components/results.jsx b/frontend/src/components/results.jsx
index 1f57730..8339113 100644
--- a/frontend/src/components/results.jsx
+++ b/frontend/src/components/results.jsx
@@ -5,14 +5,23 @@ function Results() {
const [pssh, setPssh] = useState("");
const [licenseUrl, setLicenseUrl] = useState("");
const [keys, setKeys] = useState([]);
+ const [manifestUrl, setManifestUrl] = useState("");
useEffect(() => {
chrome.storage.local.get(
- ["drmType", "latestPSSH", "latestLicenseRequest", "latestKeys", "licenseURL"],
+ [
+ "drmType",
+ "latestPSSH",
+ "latestLicenseRequest",
+ "latestKeys",
+ "licenseURL",
+ "manifestURL",
+ ],
(result) => {
if (result.drmType) setDrmType(result.drmType);
if (result.latestPSSH) setPssh(result.latestPSSH);
if (result.licenseURL) setLicenseUrl(result.licenseURL);
+ if (result.manifestURL) setManifestUrl(result.manifestURL);
if (result.latestKeys) {
try {
const parsed = Array.isArray(result.latestKeys)
@@ -38,6 +47,9 @@ function Results() {
if (changes.licenseURL) {
setLicenseUrl(changes.licenseURL.newValue);
}
+ if (changes.manifestURL) {
+ setManifestUrl(changes.manifestURL.newValue);
+ }
if (changes.latestKeys) {
setKeys(changes.latestKeys.newValue);
}
@@ -54,6 +66,7 @@ function Results() {
drmType: "None",
latestPSSH: "None",
licenseURL: "None",
+ manifestURL: "None",
latestKeys: [],
});
@@ -97,39 +110,52 @@ function Results() {
>
Capture current tab
+
DRM Type
+
+ Manifest URL
+
+
PSSH
+
License URL
+
Keys
-
+
{Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0 ? (
keys
.filter((k) => k.type !== "SIGNING")
.map((k) => `${k.key_id || k.keyId}:${k.key}`)
.join("\n")
) : (
- None
+ [Not available]
)}
diff --git a/src/background.js b/src/background.js
index bb1e2be..da9c10f 100644
--- a/src/background.js
+++ b/src/background.js
@@ -33,6 +33,11 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
chrome.storage.local.set({ licenseURL: data });
break;
+ case "MANIFEST_URL_FOUND":
+ console.log("Storing Manifest URL:", data);
+ chrome.storage.local.set({ manifestURL: data });
+ break;
+
default:
console.warn("Unknown message type received:", type);
}
--
2.43.0
From 5949228d4f9e846ca10dbe586871e0d82a061392 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 16:27:13 +0700
Subject: [PATCH 06/26] update to manifest v3
---
README.md | 2 +
frontend/package.json | 58 +--
mv2/background.js | 89 ++++
mv2/content.js | 96 ++++
mv2/inject.js | 1122 +++++++++++++++++++++++++++++++++++++++++
mv2/manifest.json | 41 ++
src/background.js | 5 +-
src/manifest.json | 80 ++-
8 files changed, 1415 insertions(+), 78 deletions(-)
create mode 100644 mv2/background.js
create mode 100644 mv2/content.js
create mode 100644 mv2/inject.js
create mode 100644 mv2/manifest.json
diff --git a/README.md b/README.md
index 16ce2fc..4cb2211 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,8 @@ Keep these extension core files inside `src`:
- `inject.js`
- `manifest.json`
+The `mv2` folder is for Manifest v2 backup for legacy reasons.
+
Frontend React source stays in `frontend`.
The build process will take care of everything into `extension-release`.
diff --git a/frontend/package.json b/frontend/package.json
index 326d96a..bae1047 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,30 +1,30 @@
{
- "name": "frontend",
- "private": true,
- "version": "2.1.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "eslint .",
- "preview": "vite preview"
- },
- "dependencies": {
- "@tailwindcss/vite": "^4.1.11",
- "react": "^19.1.0",
- "react-dom": "^19.1.0",
- "react-router-dom": "^7.7.0",
- "tailwindcss": "^4.1.11"
- },
- "devDependencies": {
- "@eslint/js": "^9.31.0",
- "@types/react": "^19.1.8",
- "@types/react-dom": "^19.1.6",
- "@vitejs/plugin-react": "^4.7.0",
- "eslint": "^9.31.0",
- "eslint-plugin-react-hooks": "^5.2.0",
- "eslint-plugin-react-refresh": "^0.4.20",
- "globals": "^16.3.0",
- "vite": "^7.0.5"
- }
-}
\ No newline at end of file
+ "name": "frontend",
+ "private": true,
+ "version": "2.1.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tailwindcss/vite": "^4.1.11",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.7.0",
+ "tailwindcss": "^4.1.11"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.31.0",
+ "@types/react": "^19.1.8",
+ "@types/react-dom": "^19.1.6",
+ "@vitejs/plugin-react": "^4.7.0",
+ "eslint": "^9.31.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "vite": "^7.0.5"
+ }
+}
diff --git a/mv2/background.js b/mv2/background.js
new file mode 100644
index 0000000..da9c10f
--- /dev/null
+++ b/mv2/background.js
@@ -0,0 +1,89 @@
+// Open popout window when the extension icon is clicked
+chrome.browserAction.onClicked.addListener(() => {
+ chrome.windows.create({
+ url: chrome.runtime.getURL("index.html"),
+ type: "popup", // opens as a floating window
+ width: 800,
+ height: 600,
+ });
+});
+
+// Listen for messages and store data in chrome.storage.local
+chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
+ const { type, data } = message;
+
+ switch (type) {
+ case "DRM_TYPE":
+ console.log("DRM Type:", data);
+ chrome.storage.local.set({ drmType: data });
+ break;
+
+ case "PSSH_DATA":
+ console.log("Storing PSSH:", data);
+ chrome.storage.local.set({ latestPSSH: data });
+ break;
+
+ case "KEYS_DATA":
+ console.log("Storing Decryption Keys:", data);
+ chrome.storage.local.set({ latestKeys: data });
+ break;
+
+ case "LICENSE_URL":
+ console.log("Storling License URL " + data);
+ chrome.storage.local.set({ licenseURL: data });
+ break;
+
+ case "MANIFEST_URL_FOUND":
+ console.log("Storing Manifest URL:", data);
+ chrome.storage.local.set({ manifestURL: data });
+ break;
+
+ default:
+ console.warn("Unknown message type received:", type);
+ }
+});
+
+// Set initial config and injection type on install
+chrome.runtime.onInstalled.addListener((details) => {
+ if (details.reason === "install") {
+ chrome.storage.local.set({ valid_config: false }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting valid_config:", chrome.runtime.lastError);
+ } else {
+ console.log("valid_config set to false on first install.");
+ }
+ });
+
+ chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting Injection Type:", chrome.runtime.lastError);
+ } else {
+ console.log("Injection type set to LICENSE on first install.");
+ }
+ });
+
+ chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting DRM Override type:", chrome.runtime.lastError);
+ } else {
+ console.log("DRM Override type set to DISABLED on first install.");
+ }
+ });
+
+ chrome.storage.local.set({ cdrm_instance: null }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting CDRM instance:", chrome.runtime.lastError);
+ } else {
+ console.log("CDRM instance set to null.");
+ }
+ });
+
+ chrome.storage.local.set({ cdrm_api_key: null }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
+ } else {
+ console.log("CDRM API Key set.");
+ }
+ });
+ }
+});
diff --git a/mv2/content.js b/mv2/content.js
new file mode 100644
index 0000000..55b7891
--- /dev/null
+++ b/mv2/content.js
@@ -0,0 +1,96 @@
+// Inject `inject.js` into the page context
+(function injectScript() {
+ const script = document.createElement("script");
+ script.src = chrome.runtime.getURL("inject.js");
+ script.type = "text/javascript";
+ script.onload = () => script.remove(); // Clean up
+ // Inject directly into or
+ (document.documentElement || document.head || document.body).appendChild(script);
+})();
+
+// Listen for messages from the injected script
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
+
+ if (
+ ["__DRM_TYPE__", "__PSSH_DATA__", "__KEYS_DATA__", "__LICENSE_URL__"].includes(
+ event.data?.type
+ )
+ ) {
+ chrome.runtime.sendMessage({
+ type: event.data.type.replace("__", "").replace("__", ""),
+ data: event.data.data,
+ });
+ }
+
+ if (event.data.type === "__GET_CDM_DEVICES__") {
+ chrome.storage.local.get(["widevine_device", "playready_device"], (result) => {
+ const widevine_device = result.widevine_device || null;
+ const playready_device = result.playready_device || null;
+
+ window.postMessage(
+ {
+ type: "__CDM_DEVICES__",
+ widevine_device,
+ playready_device,
+ },
+ "*"
+ );
+ });
+ }
+
+ if (event.data.type === "__GET_INJECTION_TYPE__") {
+ chrome.storage.local.get("injection_type", (result) => {
+ const injectionType = result.injection_type || "LICENSE";
+
+ window.postMessage(
+ {
+ type: "__INJECTION_TYPE__",
+ injectionType,
+ },
+ "*"
+ );
+ });
+ }
+
+ if (event.data.type === "__GET_DRM_OVERRIDE__") {
+ chrome.storage.local.get("drm_override", (result) => {
+ const drmOverride = result.drm_override || "DISABLED";
+
+ window.postMessage(
+ {
+ type: "__DRM_OVERRIDE__",
+ drmOverride,
+ },
+ "*"
+ );
+ });
+ }
+
+ // Manifest header and URL
+
+ const seenManifestUrls = new Set();
+
+ if (event.data?.type === "__MANIFEST_URL__") {
+ const url = event.data.data;
+ if (seenManifestUrls.has(url)) return;
+ seenManifestUrls.add(url);
+ console.log("✅ [Content] Unique manifest URL:", url);
+
+ chrome.runtime.sendMessage({
+ type: "MANIFEST_URL_FOUND",
+ data: url,
+ });
+ }
+
+ if (event.data?.type === "__MANIFEST_HEADERS__") {
+ const { url, headers } = event.data;
+ console.log("[Content.js] Manifest Headers:", url, headers);
+
+ chrome.runtime.sendMessage({
+ type: "MANIFEST_HEADERS",
+ url,
+ headers,
+ });
+ }
+});
diff --git a/mv2/inject.js b/mv2/inject.js
new file mode 100644
index 0000000..fdcb029
--- /dev/null
+++ b/mv2/inject.js
@@ -0,0 +1,1122 @@
+let widevineDeviceInfo = null;
+let playreadyDeviceInfo = null;
+let originalChallenge = null;
+let serviceCertFound = false;
+let drmType = "NONE";
+let psshFound = false;
+let foundWidevinePssh = null;
+let foundPlayreadyPssh = null;
+let drmDecided = null;
+let drmOverride = "DISABLED";
+let interceptType = "DISABLED";
+let remoteCDM = null;
+let generateRequestCalled = false;
+let remoteListenerMounted = false;
+let injectionSuccess = false;
+let foundChallengeInBody = false;
+let licenseResponseCounter = 0;
+let keysRetrieved = false;
+
+// Post message to content.js to get DRM override
+window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
+
+// Add listener for DRM override messages
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
+ if (event.data.type === "__DRM_OVERRIDE__") {
+ drmOverride = event.data.drmOverride || "DISABLED";
+ console.log("DRM Override set to:", drmOverride);
+ }
+});
+
+// Post message to content.js to get injection type
+window.postMessage({ type: "__GET_INJECTION_TYPE__" }, "*");
+
+// Add listener for injection type messages
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
+
+ if (event.data.type === "__INJECTION_TYPE__") {
+ interceptType = event.data.injectionType || "DISABLED";
+ console.log("Injection type set to:", interceptType);
+ }
+});
+
+// Post message to get CDM devices
+window.postMessage({ type: "__GET_CDM_DEVICES__" }, "*");
+
+// Add listener for CDM device messages
+window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
+
+ if (event.data.type === "__CDM_DEVICES__") {
+ const { widevine_device, playready_device } = event.data;
+
+ console.log("Received device info:", widevine_device, playready_device);
+
+ widevineDeviceInfo = widevine_device;
+ playreadyDeviceInfo = playready_device;
+ }
+});
+
+function safeHeaderShellEscape(str) {
+ return str
+ .replace(/\\/g, "\\\\")
+ .replace(/"/g, '\\"')
+ .replace(/\$/g, "\\$") // escape shell expansion
+ .replace(/`/g, "\\`")
+ .replace(/\n/g, ""); // strip newlines
+}
+
+// Intercep network to find manifest
+function injectManifestInterceptor() {
+ const script = document.createElement("script");
+ script.textContent = `
+ (function() {
+ function isProbablyManifest(text = "", contentType = "") {
+ const lowerCT = contentType?.toLowerCase() ?? "";
+ const sample = text.slice(0, 2000);
+
+ const isHLSMime = lowerCT.includes("mpegurl");
+ const isDASHMime = lowerCT.includes("dash+xml");
+ const isSmoothMime = lowerCT.includes("sstr+xml");
+
+ const isHLSKeyword = sample.includes("#EXTM3U") || sample.includes("#EXT-X-STREAM-INF");
+ const isDASHKeyword = sample.includes(" {
+ headersObj[key] = value;
+ });
+
+ const headerFlags = Object.entries(headersObj)
+ .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
+ .join(" ");
+
+ window.postMessage({
+ type: "__MANIFEST_HEADERS__",
+ url,
+ headers: headerFlags
+ }, "*");
+ }
+ } catch (e) {}
+
+ return response;
+ };
+
+ const originalXHROpen = XMLHttpRequest.prototype.open;
+ const originalXHRSend = XMLHttpRequest.prototype.send;
+
+ XMLHttpRequest.prototype.open = function(method, url) {
+ this.__url = url;
+ return originalXHROpen.apply(this, arguments);
+ };
+
+ XMLHttpRequest.prototype.send = function(body) {
+ this.addEventListener("load", function () {
+ try {
+ const contentType = this.getResponseHeader("content-type") || "";
+ const text = this.responseText;
+
+ if (isProbablyManifest(text, contentType)) {
+ window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
+ console.log("[Manifest][xhr]", this.__url, contentType);
+
+ const xhrHeaders = {};
+ const rawHeaders = this.getAllResponseHeaders().trim().split(/\\r?\\n/);
+ rawHeaders.forEach(line => {
+ const parts = line.split(": ");
+ if (parts.length === 2) {
+ xhrHeaders[parts[0]] = parts[1];
+ }
+ });
+
+ const headerFlags = Object.entries(xhrHeaders)
+ .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
+ .join(" ");
+
+ window.postMessage({
+ type: "__MANIFEST_HEADERS__",
+ url: this.__url,
+ headers: headerFlags
+ }, "*");
+ }
+ } catch (e) {}
+ });
+ return originalXHRSend.apply(this, arguments);
+ };
+ })();
+ `;
+ document.documentElement.appendChild(script);
+ script.remove();
+}
+
+injectManifestInterceptor();
+
+// PlayReady Remote CDM Class
+class remotePlayReadyCDM {
+ constructor(security_level, host, secret, device_name) {
+ this.security_level = security_level;
+ this.host = host;
+ this.secret = secret;
+ this.device_name = device_name;
+ this.session_id = null;
+ this.challenge = null;
+ this.keys = null;
+ }
+
+ // Open PlayReady session
+ openSession() {
+ const url = `${this.host}/remotecdm/playready/${this.device_name}/open`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.send();
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.session_id) {
+ this.session_id = jsonData.data.session_id;
+ console.log("PlayReady session opened:", this.session_id);
+ } else {
+ console.error("Failed to open PlayReady session:", jsonData.message);
+ throw new Error("Failed to open PlayReady session");
+ }
+ }
+
+ // Get PlayReady challenge
+ getChallenge(init_data) {
+ const url = `${this.host}/remotecdm/playready/${this.device_name}/get_license_challenge`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ init_data: init_data,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.challenge) {
+ this.challenge = btoa(jsonData.data.challenge);
+ console.log("PlayReady challenge received:", this.challenge);
+ } else {
+ console.error("Failed to get PlayReady challenge:", jsonData.message);
+ throw new Error("Failed to get PlayReady challenge");
+ }
+ }
+
+ // Parse PlayReady license response
+ parseLicense(license_message) {
+ const url = `${this.host}/remotecdm/playready/${this.device_name}/parse_license`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ license_message: license_message,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (
+ jsonData.message === "Successfully parsed and loaded the Keys from the License message"
+ ) {
+ console.log("PlayReady license response parsed successfully");
+ return true;
+ } else {
+ console.error("Failed to parse PlayReady license response:", jsonData.message);
+ throw new Error("Failed to parse PlayReady license response");
+ }
+ }
+
+ // Get PlayReady keys
+ getKeys() {
+ const url = `${this.host}/remotecdm/playready/${this.device_name}/get_keys`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.keys) {
+ this.keys = jsonData.data.keys;
+ console.log("PlayReady keys received:", this.keys);
+ } else {
+ console.error("Failed to get PlayReady keys:", jsonData.message);
+ throw new Error("Failed to get PlayReady keys");
+ }
+ }
+
+ // Close PlayReady session
+ closeSession() {
+ const url = `${this.host}/remotecdm/playready/${this.device_name}/close/${this.session_id}`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.send();
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData) {
+ console.log("PlayReady session closed successfully");
+ } else {
+ console.error("Failed to close PlayReady session:", jsonData.message);
+ throw new Error("Failed to close PlayReady session");
+ }
+ }
+}
+
+// Widevine Remote CDM Class
+class remoteWidevineCDM {
+ constructor(device_type, system_id, security_level, host, secret, device_name) {
+ this.device_type = device_type;
+ this.system_id = system_id;
+ this.security_level = security_level;
+ this.host = host;
+ this.secret = secret;
+ this.device_name = device_name;
+ this.session_id = null;
+ this.challenge = null;
+ this.keys = null;
+ }
+
+ // Open Widevine session
+ openSession() {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/open`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.send();
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.session_id) {
+ this.session_id = jsonData.data.session_id;
+ console.log("Widevine session opened:", this.session_id);
+ } else {
+ console.error("Failed to open Widevine session:", jsonData.message);
+ throw new Error("Failed to open Widevine session");
+ }
+ }
+
+ // Set Widevine service certificate
+ setServiceCertificate(certificate) {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/set_service_certificate`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ certificate: certificate ?? null,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.status === 200) {
+ console.log("Service certificate set successfully");
+ } else {
+ console.error("Failed to set service certificate:", jsonData.message);
+ throw new Error("Failed to set service certificate");
+ }
+ }
+
+ // Get Widevine challenge
+ getChallenge(init_data, license_type = "STREAMING") {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_license_challenge/${license_type}`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ init_data: init_data,
+ privacy_mode: serviceCertFound,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.challenge_b64) {
+ this.challenge = jsonData.data.challenge_b64;
+ console.log("Widevine challenge received:", this.challenge);
+ } else {
+ console.error("Failed to get Widevine challenge:", jsonData.message);
+ throw new Error("Failed to get Widevine challenge");
+ }
+ }
+
+ // Parse Widevine license response
+ parseLicense(license_message) {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/parse_license`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ license_message: license_message,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.status === 200) {
+ console.log("Widevine license response parsed successfully");
+ return true;
+ } else {
+ console.error("Failed to parse Widevine license response:", jsonData.message);
+ throw new Error("Failed to parse Widevine license response");
+ }
+ }
+
+ // Get Widevine keys
+ getKeys() {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_keys/ALL`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ const body = {
+ session_id: this.session_id,
+ };
+ xhr.send(JSON.stringify(body));
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData.data?.keys) {
+ this.keys = jsonData.data.keys;
+ console.log("Widevine keys received:", this.keys);
+ } else {
+ console.error("Failed to get Widevine keys:", jsonData.message);
+ throw new Error("Failed to get Widevine keys");
+ }
+ }
+
+ // Close Widevine session
+ closeSession() {
+ const url = `${this.host}/remotecdm/widevine/${this.device_name}/close/${this.session_id}`;
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.send();
+ const jsonData = JSON.parse(xhr.responseText);
+ if (jsonData) {
+ console.log("Widevine session closed successfully");
+ } else {
+ console.error("Failed to close Widevine session:", jsonData.message);
+ throw new Error("Failed to close Widevine session");
+ }
+ }
+}
+
+// Utility functions
+function hexStrToU8(hexString) {
+ return Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
+}
+
+function u8ToHexStr(bytes) {
+ return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
+}
+
+function b64ToHexStr(b64) {
+ return [...atob(b64)].map((c) => c.charCodeAt(0).toString(16).padStart(2, "0")).join``;
+}
+
+function jsonContainsValue(obj, prefix = "CAES") {
+ if (typeof obj === "string") return obj.startsWith(prefix);
+ if (Array.isArray(obj)) return obj.some((val) => jsonContainsValue(val, prefix));
+ if (typeof obj === "object" && obj !== null) {
+ return Object.values(obj).some((val) => jsonContainsValue(val, prefix));
+ }
+ return false;
+}
+
+function jsonReplaceValue(obj, newValue) {
+ if (typeof obj === "string") {
+ return obj.startsWith("CAES") || obj.startsWith("PD94") ? newValue : obj;
+ }
+
+ if (Array.isArray(obj)) {
+ return obj.map((item) => jsonReplaceValue(item, newValue));
+ }
+
+ if (typeof obj === "object" && obj !== null) {
+ const newObj = {};
+ for (const key in obj) {
+ if (Object.hasOwn(obj, key)) {
+ newObj[key] = jsonReplaceValue(obj[key], newValue);
+ }
+ }
+ return newObj;
+ }
+
+ return obj;
+}
+
+function isJson(str) {
+ try {
+ JSON.parse(str);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+function getWidevinePssh(buffer) {
+ const hex = u8ToHexStr(new Uint8Array(buffer));
+ const match = hex.match(/000000(..)?70737368.*/);
+ if (!match) return null;
+
+ const boxHex = match[0];
+ const bytes = hexStrToU8(boxHex);
+ return window.btoa(String.fromCharCode(...bytes));
+}
+
+function getPlayReadyPssh(buffer) {
+ const u8 = new Uint8Array(buffer);
+ const systemId = "9a04f07998404286ab92e65be0885f95";
+ const hex = u8ToHexStr(u8);
+ const index = hex.indexOf(systemId);
+ if (index === -1) return null;
+ const psshBoxStart = hex.lastIndexOf("70737368", index);
+ if (psshBoxStart === -1) return null;
+ const lenStart = psshBoxStart - 8;
+ const boxLen = parseInt(hex.substr(lenStart, 8), 16) * 2;
+ const psshHex = hex.substr(lenStart, boxLen);
+ const psshBytes = hexStrToU8(psshHex);
+ return window.btoa(String.fromCharCode(...psshBytes));
+}
+
+function getClearkey(response) {
+ let obj = JSON.parse(new TextDecoder("utf-8").decode(response));
+ return obj["keys"].map((o) => ({
+ key_id: b64ToHexStr(o["kid"].replace(/-/g, "+").replace(/_/g, "/")),
+ key: b64ToHexStr(o["k"].replace(/-/g, "+").replace(/_/g, "/")),
+ }));
+}
+
+function base64ToUint8Array(base64) {
+ const binaryStr = atob(base64);
+ const len = binaryStr.length;
+ const bytes = new Uint8Array(len);
+ for (let i = 0; i < len; i++) {
+ bytes[i] = binaryStr.charCodeAt(i);
+ }
+ return bytes;
+}
+
+function arrayBufferToBase64(uint8array) {
+ let binary = "";
+ const len = uint8array.length;
+
+ for (let i = 0; i < len; i++) {
+ binary += String.fromCharCode(uint8array[i]);
+ }
+
+ return window.btoa(binary);
+}
+
+// Challenge generator interceptor
+const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
+MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
+ const session = this;
+ let playReadyPssh = getPlayReadyPssh(initData);
+ if (playReadyPssh) {
+ console.log("[DRM Detected] PlayReady");
+ foundPlayreadyPssh = playReadyPssh;
+ console.log("[PlayReady PSSH found] " + playReadyPssh);
+ }
+ let wideVinePssh = getWidevinePssh(initData);
+ if (wideVinePssh) {
+ // Widevine code
+ console.log("[DRM Detected] Widevine");
+ foundWidevinePssh = wideVinePssh;
+ console.log("[Widevine PSSH found] " + wideVinePssh);
+ }
+ // Challenge message interceptor
+ if (!remoteListenerMounted) {
+ remoteListenerMounted = true;
+ session.addEventListener("message", function messageInterceptor(event) {
+ event.stopImmediatePropagation();
+ const uint8Array = new Uint8Array(event.message);
+ const base64challenge = arrayBufferToBase64(uint8Array);
+ if (base64challenge === "CAQ=" && interceptType !== "DISABLED" && !serviceCertFound) {
+ const { device_type, system_id, security_level, host, secret, device_name } =
+ widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ }
+ if (!injectionSuccess && base64challenge !== "CAQ=" && interceptType !== "DISABLED") {
+ if (interceptType === "EME") {
+ injectionSuccess = true;
+ }
+ if (!originalChallenge) {
+ originalChallenge = base64challenge;
+ }
+ if (originalChallenge.startsWith("CAES")) {
+ window.postMessage({ type: "__DRM_TYPE__", data: "Widevine" }, "*");
+ window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
+ if (interceptType === "EME" && !remoteCDM) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ }
+ if (!originalChallenge.startsWith("CAES")) {
+ const buffer = event.message;
+ const decoder = new TextDecoder("utf-16");
+ const decodedText = decoder.decode(buffer);
+ const match = decodedText.match(
+ /([^<]+)<\/Challenge>/
+ );
+ if (match) {
+ window.postMessage({ type: "__DRM_TYPE__", data: "PlayReady" }, "*");
+ window.postMessage(
+ { type: "__PSSH_DATA__", data: foundPlayreadyPssh },
+ "*"
+ );
+ originalChallenge = match[1];
+ if (interceptType === "EME" && !remoteCDM) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ }
+ if (interceptType === "EME" && remoteCDM) {
+ const uint8challenge = base64ToUint8Array(remoteCDM.challenge);
+ const challengeBuffer = uint8challenge.buffer;
+ const syntheticEvent = new MessageEvent("message", {
+ data: event.data,
+ origin: event.origin,
+ lastEventId: event.lastEventId,
+ source: event.source,
+ ports: event.ports,
+ });
+ Object.defineProperty(syntheticEvent, "message", {
+ get: () => challengeBuffer,
+ });
+ console.log("Intercepted EME Challenge and injected custom one.");
+ session.dispatchEvent(syntheticEvent);
+ }
+ }
+ });
+ console.log("Message interceptor mounted.");
+ }
+ return originalGenerateRequest.call(session, initDataType, initData);
+};
+
+// Message update interceptors
+const originalUpdate = MediaKeySession.prototype.update;
+MediaKeySession.prototype.update = function (response) {
+ const uint8 = response instanceof Uint8Array ? response : new Uint8Array(response);
+ const base64Response = window.btoa(String.fromCharCode(...uint8));
+ if (base64Response.startsWith("CAUS") && foundWidevinePssh && remoteCDM && !serviceCertFound) {
+ remoteCDM.setServiceCertificate(base64Response);
+ if (interceptType === "EME" && !remoteCDM.challenge) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ window.postMessage({ type: "__DRM_TYPE__", data: "Widevine" }, "*");
+ window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
+ serviceCertFound = true;
+ }
+ if (
+ !base64Response.startsWith("CAUS") &&
+ (foundWidevinePssh || foundPlayreadyPssh) &&
+ !keysRetrieved
+ ) {
+ if (licenseResponseCounter === 1 || foundChallengeInBody) {
+ remoteCDM.parseLicense(base64Response);
+ remoteCDM.getKeys();
+ remoteCDM.closeSession();
+ keysRetrieved = true;
+ window.postMessage({ type: "__KEYS_DATA__", data: remoteCDM.keys }, "*");
+ }
+ licenseResponseCounter++;
+ }
+ const updatePromise = originalUpdate.call(this, response);
+ if (!foundPlayreadyPssh && !foundWidevinePssh) {
+ updatePromise
+ .then(() => {
+ let clearKeys = getClearkey(response);
+ if (clearKeys && clearKeys.length > 0) {
+ console.log("[CLEARKEY] ", clearKeys);
+ const drmType = {
+ type: "__DRM_TYPE__",
+ data: "ClearKey",
+ };
+ window.postMessage(drmType, "*");
+ const keysData = {
+ type: "__KEYS_DATA__",
+ data: clearKeys,
+ };
+ window.postMessage(keysData, "*");
+ }
+ })
+ .catch((e) => {
+ console.log("[CLEARKEY] Not found");
+ });
+ }
+
+ return updatePromise;
+};
+
+// fetch POST interceptor
+(function () {
+ const originalFetch = window.fetch;
+
+ window.fetch = async function (resource, config = {}) {
+ const method = (config.method || "GET").toUpperCase();
+
+ if (method === "POST") {
+ let body = config.body;
+ if (body) {
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
+ const base64Body = window.btoa(String.fromCharCode(...buffer));
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64Body !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (base64Body.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64Body.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = base64ToUint8Array(remoteCDM.challenge);
+ config.body = injectedBody;
+ return originalFetch(resource, config);
+ }
+ }
+ if (typeof body === "string" && !isJson(body)) {
+ const base64EncodedBody = btoa(body);
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64EncodedBody !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (base64EncodedBody.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64EncodedBody.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = atob(remoteCDM.challenge);
+ config.body = injectedBody;
+ return originalFetch(resource, config);
+ }
+ }
+ if (typeof body === "string" && isJson(body)) {
+ const jsonBody = JSON.parse(body);
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ (!remoteCDM || remoteCDM.challenge === null) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ interceptType === "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ if (!remoteCDM) {
+ if (jsonContainsValue(jsonBody, "CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (jsonContainsValue(jsonBody, "PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
+ config.body = JSON.stringify(injectedBody);
+ }
+ }
+ }
+ }
+
+ return originalFetch(resource, config);
+ };
+})();
+
+// XHR POST interceptor
+(function () {
+ const originalOpen = XMLHttpRequest.prototype.open;
+ const originalSend = XMLHttpRequest.prototype.send;
+
+ XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
+ this._method = method;
+ this._url = url;
+ return originalOpen.apply(this, arguments);
+ };
+
+ XMLHttpRequest.prototype.send = function (body) {
+ if (this._method && this._method.toUpperCase() === "POST") {
+ if (body) {
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
+ const base64Body = window.btoa(String.fromCharCode(...buffer));
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64Body !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (base64Body.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64Body.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = base64ToUint8Array(remoteCDM.challenge);
+ return originalSend.call(this, injectedBody);
+ }
+ }
+
+ if (typeof body === "string" && !isJson(body)) {
+ const base64EncodedBody = btoa(body);
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ base64EncodedBody !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+ if (
+ (base64EncodedBody.startsWith("CAES") ||
+ base64EncodedBody.startsWith("PD94")) &&
+ interceptType == "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (base64EncodedBody.startsWith("CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (base64EncodedBody.startsWith("PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = atob(remoteCDM.challenge);
+ return originalSend.call(this, injectedBody);
+ }
+ }
+
+ if (typeof body === "string" && isJson(body)) {
+ const jsonBody = JSON.parse(body);
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ (!remoteCDM || remoteCDM.challenge === null) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
+ }
+
+ if (
+ (jsonContainsValue(jsonBody, "CAES") ||
+ jsonContainsValue(jsonBody, "PD94")) &&
+ interceptType === "LICENSE" &&
+ !foundChallengeInBody
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ if (!remoteCDM) {
+ if (jsonContainsValue(jsonBody, "CAES")) {
+ const {
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name,
+ } = widevineDeviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ if (jsonContainsValue(jsonBody, "PD94")) {
+ const { security_level, host, secret, device_name } =
+ playreadyDeviceInfo;
+ remoteCDM = new remotePlayReadyCDM(
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(foundPlayreadyPssh);
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(foundWidevinePssh);
+ }
+ const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
+ return originalSend.call(this, JSON.stringify(injectedBody));
+ }
+ }
+ }
+ }
+ return originalSend.apply(this, arguments);
+ };
+})();
diff --git a/mv2/manifest.json b/mv2/manifest.json
new file mode 100644
index 0000000..fb34e80
--- /dev/null
+++ b/mv2/manifest.json
@@ -0,0 +1,41 @@
+{
+ "manifest_version": 2,
+ "name": "CDRM Extension",
+ "version": "2.1.0",
+ "description": "Decrypt DRM protected content",
+ "permissions": [
+ "webRequest",
+ "webRequestBlocking",
+ "",
+ "activeTab",
+ "storage",
+ "tabs",
+ "contextMenus"
+ ],
+ "background": {
+ "scripts": ["background.js"],
+ "persistent": true
+ },
+ "content_scripts": [
+ {
+ "matches": [""],
+ "js": ["content.js"],
+ "run_at": "document_start",
+ "all_frames": true
+ }
+ ],
+ "web_accessible_resources": ["inject.js"],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+ "browser_action": {
+ "default_icon": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+ },
+ "icons": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+}
diff --git a/src/background.js b/src/background.js
index da9c10f..3c0fc5d 100644
--- a/src/background.js
+++ b/src/background.js
@@ -1,8 +1,7 @@
-// Open popout window when the extension icon is clicked
-chrome.browserAction.onClicked.addListener(() => {
+chrome.action.onClicked.addListener(() => {
chrome.windows.create({
url: chrome.runtime.getURL("index.html"),
- type: "popup", // opens as a floating window
+ type: "popup",
width: 800,
height: 600,
});
diff --git a/src/manifest.json b/src/manifest.json
index 00a5ab7..a2a5d0a 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,49 +1,37 @@
{
- "manifest_version": 2,
- "name": "CDRM Extension",
- "version": "2.1.0",
- "description": "Decrypt DRM protected content",
- "permissions": [
- "webRequest",
- "webRequestBlocking",
- "",
- "activeTab",
- "storage",
- "tabs",
- "contextMenus"
- ],
- "background": {
- "scripts": [
- "background.js"
+ "manifest_version": 3,
+ "name": "CDRM Extension",
+ "version": "2.1.0",
+ "description": "Decrypt DRM protected content",
+ "permissions": ["storage", "activeTab", "contextMenus"],
+ "host_permissions": [""],
+ "background": {
+ "service_worker": "background.js"
+ },
+ "content_scripts": [
+ {
+ "matches": [""],
+ "js": ["content.js"],
+ "run_at": "document_start",
+ "all_frames": true
+ }
],
- "persistent": true
- },
- "content_scripts": [
- {
- "matches": [
- ""
- ],
- "js": [
- "content.js"
- ],
- "run_at": "document_start",
- "all_frames": true
+ "web_accessible_resources": [
+ {
+ "resources": ["inject.js"],
+ "matches": [""]
+ }
+ ],
+ "action": {
+ "default_icon": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
+ }
+ },
+ "icons": {
+ "16": "icons/icon16.png",
+ "32": "icons/icon32.png",
+ "128": "icons/icon128.png"
}
- ],
- "web_accessible_resources": [
- "inject.js"
- ],
- "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
- "browser_action": {
- "default_icon": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
- }
- },
- "icons": {
- "16": "icons/icon16.png",
- "32": "icons/icon32.png",
- "128": "icons/icon128.png"
- }
-}
\ No newline at end of file
+}
--
2.43.0
From 5cc68345328fa99452380215f707884cd20f9746 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 16:56:34 +0700
Subject: [PATCH 07/26] add export to json button
---
frontend/src/components/results.jsx | 78 +++++++++++++++++++++++------
1 file changed, 64 insertions(+), 14 deletions(-)
diff --git a/frontend/src/components/results.jsx b/frontend/src/components/results.jsx
index 8339113..fe9ffe7 100644
--- a/frontend/src/components/results.jsx
+++ b/frontend/src/components/results.jsx
@@ -18,10 +18,10 @@ function Results() {
"manifestURL",
],
(result) => {
- if (result.drmType) setDrmType(result.drmType);
- if (result.latestPSSH) setPssh(result.latestPSSH);
- if (result.licenseURL) setLicenseUrl(result.licenseURL);
- if (result.manifestURL) setManifestUrl(result.manifestURL);
+ if (result.drmType) setDrmType(result.drmType || "");
+ if (result.latestPSSH) setPssh(result.latestPSSH || "");
+ if (result.licenseURL) setLicenseUrl(result.licenseURL || "");
+ if (result.manifestURL) setManifestUrl(result.manifestURL || "");
if (result.latestKeys) {
try {
const parsed = Array.isArray(result.latestKeys)
@@ -39,19 +39,19 @@ function Results() {
const handleChange = (changes, area) => {
if (area === "local") {
if (changes.drmType) {
- setDrmType(changes.drmType.newValue);
+ setDrmType(changes.drmType.newValue || "");
}
if (changes.latestPSSH) {
- setPssh(changes.latestPSSH.newValue);
+ setPssh(changes.latestPSSH.newValue || "");
}
if (changes.licenseURL) {
- setLicenseUrl(changes.licenseURL.newValue);
+ setLicenseUrl(changes.licenseURL.newValue || "");
}
if (changes.manifestURL) {
- setManifestUrl(changes.manifestURL.newValue);
+ setManifestUrl(changes.manifestURL.newValue || "");
}
if (changes.latestKeys) {
- setKeys(changes.latestKeys.newValue);
+ setKeys(changes.latestKeys.newValue || []);
}
}
};
@@ -63,10 +63,10 @@ function Results() {
const handleCapture = () => {
// Reset stored values
chrome.storage.local.set({
- drmType: "None",
- latestPSSH: "None",
- licenseURL: "None",
- manifestURL: "None",
+ drmType: "",
+ latestPSSH: "",
+ licenseURL: "",
+ manifestURL: "",
latestKeys: [],
});
@@ -102,11 +102,52 @@ function Results() {
});
};
+ // Export to JSON file
+
+ const hasData = () => {
+ return (
+ drmType ||
+ pssh ||
+ licenseUrl ||
+ manifestUrl ||
+ (Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0)
+ );
+ };
+
+ const handleExportJSON = () => {
+ const exportData = {
+ drmType: drmType || null,
+ manifestUrl: manifestUrl || null,
+ pssh: pssh || null,
+ licenseUrl: licenseUrl || null,
+ keys:
+ Array.isArray(keys) && keys.length > 0
+ ? keys
+ .filter((k) => k.type !== "SIGNING")
+ .map((k) => `${k.key_id || k.keyId}:${k.key}`)
+ : null,
+ exportedAt: new Date().toISOString(),
+ };
+
+ const blob = new Blob([JSON.stringify(exportData, null, 2)], {
+ type: "application/json",
+ });
+
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `drm-data-${new Date().toISOString().slice(0, 19).replace(/:/g, "-")}.json`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ };
+
return (
@@ -158,6 +199,15 @@ function Results() {
[Not available]
)}
+
+ {hasData() && (
+
+ )}
);
}
--
2.43.0
From 918269f42e28a56583fb4646e95281622a8f63d7 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 17:16:40 +0700
Subject: [PATCH 08/26] update setting UI, showing current instance in a
separate line
---
frontend/src/components/settings.jsx | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/frontend/src/components/settings.jsx b/frontend/src/components/settings.jsx
index 7e7ba9a..ba5cd9c 100644
--- a/frontend/src/components/settings.jsx
+++ b/frontend/src/components/settings.jsx
@@ -104,25 +104,28 @@ function Settings({ onConfigSaved }) {
return (
+ {storedUrl && (
+
+ Current instance: {storedUrl}
+
+ )}
+
+
New instance URL:
setInstanceUrl(e.target.value)}
- placeholder={
- storedUrl
- ? `Current CDRM Instance: ${storedUrl}`
- : "CDRM Instance URL (e.g., https://cdrm-project.com/, http://127.0.0.1:5000/)"
- }
- className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4"
+ placeholder="https://cdrm-project.com/, http://127.0.0.1:5000/"
+ className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4 font-mono"
/>
{message && (
--
2.43.0
From 889a4c63f310e599ec2dbb20da1b0a2a55778c17 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 17:21:02 +0700
Subject: [PATCH 09/26] sync version: only update the "version" instead of
parsing whole file
---
syncVersion.js | 52 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 16 deletions(-)
diff --git a/syncVersion.js b/syncVersion.js
index 7acba5d..6faa01a 100644
--- a/syncVersion.js
+++ b/syncVersion.js
@@ -5,6 +5,32 @@ import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
+const updateVersionWithRegex = async (filePath, newVersion) => {
+ try {
+ const content = await fs.readFile(filePath, "utf-8");
+
+ // Regex to match "version": "any.version.number"
+ const versionRegex = /("version"\s*:\s*")([^"]+)(")/;
+
+ if (!versionRegex.test(content)) {
+ console.warn(`⚠️ No version field found in ${filePath}`);
+ return false;
+ }
+
+ const updatedContent = content.replace(versionRegex, `$1${newVersion}$3`);
+
+ if (content !== updatedContent) {
+ await fs.writeFile(filePath, updatedContent);
+ return true;
+ }
+
+ return false;
+ } catch (err) {
+ console.error(`❌ Failed to update ${filePath}: ${err.message}`);
+ return false;
+ }
+};
+
const syncVersion = async () => {
const rootPkgPath = path.join(__dirname, "package.json");
const frontendPkgPath = path.join(__dirname, "frontend", "package.json");
@@ -20,26 +46,20 @@ const syncVersion = async () => {
return;
}
- // Update frontend/package.json if exists
- try {
- const frontendPkgRaw = await fs.readFile(frontendPkgPath, "utf-8");
- const frontendPkg = JSON.parse(frontendPkgRaw);
- frontendPkg.version = version;
- await fs.writeFile(frontendPkgPath, JSON.stringify(frontendPkg, null, 2));
+ // Update frontend/package.json using regex
+ const frontendUpdated = await updateVersionWithRegex(frontendPkgPath, version);
+ if (frontendUpdated) {
console.log(`🔄 Updated frontend/package.json version to ${version}`);
- } catch {
- console.log("ℹ️ frontend/package.json not found or unreadable, skipping version update.");
+ } else {
+ console.log("ℹ️ frontend/package.json not found or no changes needed.");
}
- // Update src/manifest.json version
- try {
- const manifestRaw = await fs.readFile(manifestPath, "utf-8");
- const manifest = JSON.parse(manifestRaw);
- manifest.version = version;
- await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
+ // Update src/manifest.json using regex
+ const manifestUpdated = await updateVersionWithRegex(manifestPath, version);
+ if (manifestUpdated) {
console.log(`🔄 Updated src/manifest.json version to ${version}`);
- } catch (err) {
- console.error(`❌ Failed to update src/manifest.json version: ${err.message}`);
+ } else {
+ console.log("ℹ️ src/manifest.json not found or no changes needed.");
}
};
--
2.43.0
From 6e2283704704b4f9d6518220ecf4341ff14956c9 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 17:43:13 +0700
Subject: [PATCH 10/26] Fix Trusted Types violation in manifest interceptor
injection, which fixes data not showing for YouTube DRM
---
mv2/inject.js | 181 ++++++++++++++++++++++++++++----------------------
src/inject.js | 181 ++++++++++++++++++++++++++++----------------------
2 files changed, 202 insertions(+), 160 deletions(-)
diff --git a/mv2/inject.js b/mv2/inject.js
index fdcb029..e549c96 100644
--- a/mv2/inject.js
+++ b/mv2/inject.js
@@ -70,108 +70,129 @@ function safeHeaderShellEscape(str) {
// Intercep network to find manifest
function injectManifestInterceptor() {
- const script = document.createElement("script");
- script.textContent = `
- (function() {
- function isProbablyManifest(text = "", contentType = "") {
- const lowerCT = contentType?.toLowerCase() ?? "";
- const sample = text.slice(0, 2000);
+ // Execute the interceptor code directly instead of injecting a script
+ (function () {
+ function isProbablyManifest(text = "", contentType = "") {
+ const lowerCT = contentType?.toLowerCase() ?? "";
+ const sample = text.slice(0, 2000);
- const isHLSMime = lowerCT.includes("mpegurl");
- const isDASHMime = lowerCT.includes("dash+xml");
- const isSmoothMime = lowerCT.includes("sstr+xml");
+ const isHLSMime = lowerCT.includes("mpegurl");
+ const isDASHMime = lowerCT.includes("dash+xml");
+ const isSmoothMime = lowerCT.includes("sstr+xml");
- const isHLSKeyword = sample.includes("#EXTM3U") || sample.includes("#EXT-X-STREAM-INF");
- const isDASHKeyword = sample.includes("
{
- headersObj[key] = value;
- });
+ const headersObj = {};
+ clone.headers.forEach((value, key) => {
+ headersObj[key] = value;
+ });
- const headerFlags = Object.entries(headersObj)
- .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
- .join(" ");
+ const headerFlags = Object.entries(headersObj)
+ .map(
+ ([key, val]) =>
+ '--add-headers "' +
+ safeHeaderShellEscape(key) +
+ ": " +
+ safeHeaderShellEscape(val) +
+ '"'
+ )
+ .join(" ");
- window.postMessage({
+ window.postMessage(
+ {
type: "__MANIFEST_HEADERS__",
url,
- headers: headerFlags
- }, "*");
- }
- } catch (e) {}
+ headers: headerFlags,
+ },
+ "*"
+ );
+ }
+ } catch (e) {}
- return response;
- };
+ return response;
+ };
- const originalXHROpen = XMLHttpRequest.prototype.open;
- const originalXHRSend = XMLHttpRequest.prototype.send;
+ const originalXHROpen = XMLHttpRequest.prototype.open;
+ const originalXHRSend = XMLHttpRequest.prototype.send;
- XMLHttpRequest.prototype.open = function(method, url) {
- this.__url = url;
- return originalXHROpen.apply(this, arguments);
- };
+ XMLHttpRequest.prototype.open = function (method, url) {
+ this.__url = url;
+ return originalXHROpen.apply(this, arguments);
+ };
- XMLHttpRequest.prototype.send = function(body) {
- this.addEventListener("load", function () {
- try {
- const contentType = this.getResponseHeader("content-type") || "";
- const text = this.responseText;
+ XMLHttpRequest.prototype.send = function (body) {
+ this.addEventListener("load", function () {
+ try {
+ const contentType = this.getResponseHeader("content-type") || "";
+ const text = this.responseText;
- if (isProbablyManifest(text, contentType)) {
- window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
- console.log("[Manifest][xhr]", this.__url, contentType);
+ if (isProbablyManifest(text, contentType)) {
+ window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
+ console.log("[Manifest][xhr]", this.__url, contentType);
- const xhrHeaders = {};
- const rawHeaders = this.getAllResponseHeaders().trim().split(/\\r?\\n/);
- rawHeaders.forEach(line => {
- const parts = line.split(": ");
- if (parts.length === 2) {
- xhrHeaders[parts[0]] = parts[1];
- }
- });
+ const xhrHeaders = {};
+ const rawHeaders = this.getAllResponseHeaders().trim().split(/\r?\n/);
+ rawHeaders.forEach((line) => {
+ const parts = line.split(": ");
+ if (parts.length === 2) {
+ xhrHeaders[parts[0]] = parts[1];
+ }
+ });
- const headerFlags = Object.entries(xhrHeaders)
- .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
- .join(" ");
+ const headerFlags = Object.entries(xhrHeaders)
+ .map(
+ ([key, val]) =>
+ '--add-headers "' +
+ safeHeaderShellEscape(key) +
+ ": " +
+ safeHeaderShellEscape(val) +
+ '"'
+ )
+ .join(" ");
- window.postMessage({
+ window.postMessage(
+ {
type: "__MANIFEST_HEADERS__",
url: this.__url,
- headers: headerFlags
- }, "*");
- }
- } catch (e) {}
- });
- return originalXHRSend.apply(this, arguments);
- };
- })();
- `;
- document.documentElement.appendChild(script);
- script.remove();
+ headers: headerFlags,
+ },
+ "*"
+ );
+ }
+ } catch (e) {}
+ });
+ return originalXHRSend.apply(this, arguments);
+ };
+ })();
}
injectManifestInterceptor();
diff --git a/src/inject.js b/src/inject.js
index fdcb029..e549c96 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -70,108 +70,129 @@ function safeHeaderShellEscape(str) {
// Intercep network to find manifest
function injectManifestInterceptor() {
- const script = document.createElement("script");
- script.textContent = `
- (function() {
- function isProbablyManifest(text = "", contentType = "") {
- const lowerCT = contentType?.toLowerCase() ?? "";
- const sample = text.slice(0, 2000);
+ // Execute the interceptor code directly instead of injecting a script
+ (function () {
+ function isProbablyManifest(text = "", contentType = "") {
+ const lowerCT = contentType?.toLowerCase() ?? "";
+ const sample = text.slice(0, 2000);
- const isHLSMime = lowerCT.includes("mpegurl");
- const isDASHMime = lowerCT.includes("dash+xml");
- const isSmoothMime = lowerCT.includes("sstr+xml");
+ const isHLSMime = lowerCT.includes("mpegurl");
+ const isDASHMime = lowerCT.includes("dash+xml");
+ const isSmoothMime = lowerCT.includes("sstr+xml");
- const isHLSKeyword = sample.includes("#EXTM3U") || sample.includes("#EXT-X-STREAM-INF");
- const isDASHKeyword = sample.includes(" {
- headersObj[key] = value;
- });
+ const headersObj = {};
+ clone.headers.forEach((value, key) => {
+ headersObj[key] = value;
+ });
- const headerFlags = Object.entries(headersObj)
- .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
- .join(" ");
+ const headerFlags = Object.entries(headersObj)
+ .map(
+ ([key, val]) =>
+ '--add-headers "' +
+ safeHeaderShellEscape(key) +
+ ": " +
+ safeHeaderShellEscape(val) +
+ '"'
+ )
+ .join(" ");
- window.postMessage({
+ window.postMessage(
+ {
type: "__MANIFEST_HEADERS__",
url,
- headers: headerFlags
- }, "*");
- }
- } catch (e) {}
+ headers: headerFlags,
+ },
+ "*"
+ );
+ }
+ } catch (e) {}
- return response;
- };
+ return response;
+ };
- const originalXHROpen = XMLHttpRequest.prototype.open;
- const originalXHRSend = XMLHttpRequest.prototype.send;
+ const originalXHROpen = XMLHttpRequest.prototype.open;
+ const originalXHRSend = XMLHttpRequest.prototype.send;
- XMLHttpRequest.prototype.open = function(method, url) {
- this.__url = url;
- return originalXHROpen.apply(this, arguments);
- };
+ XMLHttpRequest.prototype.open = function (method, url) {
+ this.__url = url;
+ return originalXHROpen.apply(this, arguments);
+ };
- XMLHttpRequest.prototype.send = function(body) {
- this.addEventListener("load", function () {
- try {
- const contentType = this.getResponseHeader("content-type") || "";
- const text = this.responseText;
+ XMLHttpRequest.prototype.send = function (body) {
+ this.addEventListener("load", function () {
+ try {
+ const contentType = this.getResponseHeader("content-type") || "";
+ const text = this.responseText;
- if (isProbablyManifest(text, contentType)) {
- window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
- console.log("[Manifest][xhr]", this.__url, contentType);
+ if (isProbablyManifest(text, contentType)) {
+ window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
+ console.log("[Manifest][xhr]", this.__url, contentType);
- const xhrHeaders = {};
- const rawHeaders = this.getAllResponseHeaders().trim().split(/\\r?\\n/);
- rawHeaders.forEach(line => {
- const parts = line.split(": ");
- if (parts.length === 2) {
- xhrHeaders[parts[0]] = parts[1];
- }
- });
+ const xhrHeaders = {};
+ const rawHeaders = this.getAllResponseHeaders().trim().split(/\r?\n/);
+ rawHeaders.forEach((line) => {
+ const parts = line.split(": ");
+ if (parts.length === 2) {
+ xhrHeaders[parts[0]] = parts[1];
+ }
+ });
- const headerFlags = Object.entries(xhrHeaders)
- .map(([key, val]) => '--add-headers "' + safeHeaderShellEscape(key) + ': ' + safeHeaderShellEscape(val) + '"')
- .join(" ");
+ const headerFlags = Object.entries(xhrHeaders)
+ .map(
+ ([key, val]) =>
+ '--add-headers "' +
+ safeHeaderShellEscape(key) +
+ ": " +
+ safeHeaderShellEscape(val) +
+ '"'
+ )
+ .join(" ");
- window.postMessage({
+ window.postMessage(
+ {
type: "__MANIFEST_HEADERS__",
url: this.__url,
- headers: headerFlags
- }, "*");
- }
- } catch (e) {}
- });
- return originalXHRSend.apply(this, arguments);
- };
- })();
- `;
- document.documentElement.appendChild(script);
- script.remove();
+ headers: headerFlags,
+ },
+ "*"
+ );
+ }
+ } catch (e) {}
+ });
+ return originalXHRSend.apply(this, arguments);
+ };
+ })();
}
injectManifestInterceptor();
--
2.43.0
From 3fae8f296f9ae4dd499e90cab807152e9437094f Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Sun, 20 Jul 2025 20:10:47 +0700
Subject: [PATCH 11/26] show "use yt-dlp" in manifest for youtube, use
plugin-react-swc
---
frontend/package-lock.json | 245 +++++++++++++++++++++++++++-
frontend/package.json | 1 +
frontend/src/components/results.jsx | 49 +++++-
frontend/vite.config.js | 2 +-
4 files changed, 290 insertions(+), 7 deletions(-)
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c86a3ab..e1d1c23 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "frontend",
- "version": "0.0.0",
+ "version": "2.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
- "version": "0.0.0",
+ "version": "2.1.0",
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"react": "^19.1.0",
@@ -19,6 +19,7 @@
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.7.0",
+ "@vitejs/plugin-react-swc": "^3.11.0",
"eslint": "^9.31.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
@@ -1255,6 +1256,232 @@
"win32"
]
},
+ "node_modules/@swc/core": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.1.tgz",
+ "integrity": "sha512-jEKKErLC6uwSqA+p6bmZR08usZM5Fpc+HdEu5CAzvye0q43yf1si1kjhHEa9XMkz0A2SAaal3eKCg/YYmtOsCA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "@swc/types": "^0.1.23"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.13.1",
+ "@swc/core-darwin-x64": "1.13.1",
+ "@swc/core-linux-arm-gnueabihf": "1.13.1",
+ "@swc/core-linux-arm64-gnu": "1.13.1",
+ "@swc/core-linux-arm64-musl": "1.13.1",
+ "@swc/core-linux-x64-gnu": "1.13.1",
+ "@swc/core-linux-x64-musl": "1.13.1",
+ "@swc/core-win32-arm64-msvc": "1.13.1",
+ "@swc/core-win32-ia32-msvc": "1.13.1",
+ "@swc/core-win32-x64-msvc": "1.13.1"
+ },
+ "peerDependencies": {
+ "@swc/helpers": ">=0.5.17"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.1.tgz",
+ "integrity": "sha512-zO6SW/jSMTUORPm6dUZFPUwf+EFWZsaXWMGXadRG6akCofYpoQb8pcY2QZkVr43z8TMka6BtXpyoD/DJ0iOPHQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.1.tgz",
+ "integrity": "sha512-8RjaTZYxrlYKE5PgzZYWSOT4mAsyhIuh30Nu4dnn/2r0Ef68iNCbvX4ynGnFMhOIhqunjQbJf+mJKpwTwdHXhw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.1.tgz",
+ "integrity": "sha512-jEqK6pECs2m4BpL2JA/4CCkq04p6iFOEtVNXTisO+lJ3zwmxlnIEm9UfJZG6VSu8GS9MHRKGB0ieZ1tEdN1qDA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.1.tgz",
+ "integrity": "sha512-PbkuIOYXO/gQbWQ7NnYIwm59ygNqmUcF8LBeoKvxhx1VtOwE+9KiTfoplOikkPLhMiTzKsd8qentTslbITIg+Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.1.tgz",
+ "integrity": "sha512-JaqFdBCarIBKiMu5bbAp+kWPMNGg97ej+7KzbKOzWP5pRptqKi86kCDZT3WmjPe8hNG6dvBwbm7Y8JNry5LebQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.1.tgz",
+ "integrity": "sha512-t4cLkku10YECDaakWUH0452WJHIZtrLPRwezt6BdoMntVMwNjvXRX7C8bGuYcKC3YxRW7enZKFpozLhQIQ37oA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.1.tgz",
+ "integrity": "sha512-fSMwZOaG+3ukUucbEbzz9GhzGhUhXoCPqHe9qW0/Vc2IZRp538xalygKyZynYweH5d9EHux1aj3+IO8/xBaoiA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.1.tgz",
+ "integrity": "sha512-tweCXK/79vAwj1NhAsYgICy8T1z2QEairmN2BFEBYFBFNMEB1iI1YlXwBkBtuihRvgZrTh1ORusKa4jLYzLCZA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.1.tgz",
+ "integrity": "sha512-zi7hO9D+2R2yQN9D7T10/CAI9KhuXkNkz8tcJOW6+dVPtAk/gsIC5NoGPELjgrAlLL9CS38ZQpLDslLfpP15ng==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.1.tgz",
+ "integrity": "sha512-KubYjzqs/nz3H69ncX/XHKsC8c1xqc7UvonQAj26BhbL22HBsqdAaVutZ+Obho6RMpd3F5qQ95ldavUTWskRrw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@swc/types": {
+ "version": "0.1.23",
+ "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz",
+ "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/counter": "^0.1.3"
+ }
+ },
"node_modules/@tailwindcss/node": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz",
@@ -1616,6 +1843,20 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz",
+ "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "1.0.0-beta.27",
+ "@swc/core": "^1.12.11"
+ },
+ "peerDependencies": {
+ "vite": "^4 || ^5 || ^6 || ^7"
+ }
+ },
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index bae1047..3e0425e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -21,6 +21,7 @@
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.7.0",
+ "@vitejs/plugin-react-swc": "^3.11.0",
"eslint": "^9.31.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
diff --git a/frontend/src/components/results.jsx b/frontend/src/components/results.jsx
index fe9ffe7..7155419 100644
--- a/frontend/src/components/results.jsx
+++ b/frontend/src/components/results.jsx
@@ -6,6 +6,7 @@ function Results() {
const [licenseUrl, setLicenseUrl] = useState("");
const [keys, setKeys] = useState([]);
const [manifestUrl, setManifestUrl] = useState("");
+ const [currentTabUrl, setCurrentTabUrl] = useState("");
useEffect(() => {
chrome.storage.local.get(
@@ -36,6 +37,21 @@ function Results() {
}
);
+ // Get current tab URL when component mounts
+ chrome.windows.getAll({ populate: true, windowTypes: ["normal"] }, (windows) => {
+ if (windows && windows.length > 0) {
+ const lastFocusedWindow = windows.find((w) => w.focused) || windows[0];
+ if (lastFocusedWindow) {
+ const activeTab = lastFocusedWindow.tabs.find(
+ (tab) => tab.active && tab.url && /^https?:\/\//.test(tab.url)
+ );
+ if (activeTab?.url) {
+ setCurrentTabUrl(activeTab.url);
+ }
+ }
+ }
+ });
+
const handleChange = (changes, area) => {
if (area === "local") {
if (changes.drmType) {
@@ -102,8 +118,31 @@ function Results() {
});
};
- // Export to JSON file
+ // Check if current tab is YouTube
+ const isYouTube = () => {
+ return currentTabUrl.includes("youtube.com") || currentTabUrl.includes("youtu.be");
+ };
+ // Get manifest URL display value
+ const getManifestDisplayValue = () => {
+ if (manifestUrl) {
+ return manifestUrl;
+ }
+ if (isYouTube()) {
+ return "[Use yt-dlp to download video]";
+ }
+ return "";
+ };
+
+ // Get manifest URL placeholder
+ const getManifestPlaceholder = () => {
+ if (isYouTube() && !manifestUrl) {
+ return "[Use yt-dlp to download video]";
+ }
+ return "[Not available]";
+ };
+
+ // Export to JSON file
const hasData = () => {
return (
drmType ||
@@ -164,9 +203,11 @@ function Results() {
Manifest URL
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 01889a6..971ff39 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -1,5 +1,5 @@
import tailwindcss from "@tailwindcss/vite";
-import react from "@vitejs/plugin-react";
+import react from "@vitejs/plugin-react-swc";
import { readFileSync } from "fs";
import { defineConfig } from "vite";
--
2.43.0
From 9cff5b44bd295d64b51d5a597fa3ce1f34efd387 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 11:39:35 +0700
Subject: [PATCH 12/26] forgot to remove _FOUND in MANIFEST_URL
---
src/background.js | 2 +-
src/content.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/background.js b/src/background.js
index 3c0fc5d..bbd7fd6 100644
--- a/src/background.js
+++ b/src/background.js
@@ -32,7 +32,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
chrome.storage.local.set({ licenseURL: data });
break;
- case "MANIFEST_URL_FOUND":
+ case "MANIFEST_URL":
console.log("Storing Manifest URL:", data);
chrome.storage.local.set({ manifestURL: data });
break;
diff --git a/src/content.js b/src/content.js
index 55b7891..0e12c93 100644
--- a/src/content.js
+++ b/src/content.js
@@ -78,7 +78,7 @@ window.addEventListener("message", function (event) {
console.log("✅ [Content] Unique manifest URL:", url);
chrome.runtime.sendMessage({
- type: "MANIFEST_URL_FOUND",
+ type: "MANIFEST_URL",
data: url,
});
}
--
2.43.0
From 3bd2e0f4655dd29b4ceeaa6e4bfe3777811c1a1d Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 11:41:49 +0700
Subject: [PATCH 13/26] refactor: extract redundant code into helpers (part 1)
---
src/inject.js | 275 ++++++++++++++++++++------------------------------
1 file changed, 111 insertions(+), 164 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index e549c96..915083f 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -68,6 +68,35 @@ function safeHeaderShellEscape(str) {
.replace(/\n/g, ""); // strip newlines
}
+function headersToFlags(headersObj) {
+ return Object.entries(headersObj)
+ .map(
+ ([key, val]) =>
+ '--add-headers "' +
+ safeHeaderShellEscape(key) +
+ ": " +
+ safeHeaderShellEscape(val) +
+ '"'
+ )
+ .join(" ");
+}
+
+function handleManifestDetection(url, headersObj, contentType, source) {
+ window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
+ console.log(`[Manifest][${source}]`, url, contentType);
+
+ const headerFlags = headersToFlags(headersObj);
+
+ window.postMessage(
+ {
+ type: "__MANIFEST_HEADERS__",
+ url,
+ headers: headerFlags,
+ },
+ "*"
+ );
+}
+
// Intercep network to find manifest
function injectManifestInterceptor() {
// Execute the interceptor code directly instead of injecting a script
@@ -108,33 +137,11 @@ function injectManifestInterceptor() {
const url = typeof input === "string" ? input : input.url;
if (isProbablyManifest(text, contentType)) {
- window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
- console.log("[Manifest][fetch]", url, contentType);
-
const headersObj = {};
clone.headers.forEach((value, key) => {
headersObj[key] = value;
});
-
- const headerFlags = Object.entries(headersObj)
- .map(
- ([key, val]) =>
- '--add-headers "' +
- safeHeaderShellEscape(key) +
- ": " +
- safeHeaderShellEscape(val) +
- '"'
- )
- .join(" ");
-
- window.postMessage(
- {
- type: "__MANIFEST_HEADERS__",
- url,
- headers: headerFlags,
- },
- "*"
- );
+ handleManifestDetection(url, headersObj, contentType, "fetch");
}
} catch (e) {}
@@ -156,9 +163,6 @@ function injectManifestInterceptor() {
const text = this.responseText;
if (isProbablyManifest(text, contentType)) {
- window.postMessage({ type: "__MANIFEST_URL__", data: this.__url }, "*");
- console.log("[Manifest][xhr]", this.__url, contentType);
-
const xhrHeaders = {};
const rawHeaders = this.getAllResponseHeaders().trim().split(/\r?\n/);
rawHeaders.forEach((line) => {
@@ -167,26 +171,7 @@ function injectManifestInterceptor() {
xhrHeaders[parts[0]] = parts[1];
}
});
-
- const headerFlags = Object.entries(xhrHeaders)
- .map(
- ([key, val]) =>
- '--add-headers "' +
- safeHeaderShellEscape(key) +
- ": " +
- safeHeaderShellEscape(val) +
- '"'
- )
- .join(" ");
-
- window.postMessage(
- {
- type: "__MANIFEST_HEADERS__",
- url: this.__url,
- headers: headerFlags,
- },
- "*"
- );
+ handleManifestDetection(this.__url, xhrHeaders, contentType, "xhr");
}
} catch (e) {}
});
@@ -197,21 +182,19 @@ function injectManifestInterceptor() {
injectManifestInterceptor();
-// PlayReady Remote CDM Class
-class remotePlayReadyCDM {
- constructor(security_level, host, secret, device_name) {
- this.security_level = security_level;
+class RemoteCDMBase {
+ constructor({ host, secret, device_name, security_level }) {
this.host = host;
this.secret = secret;
this.device_name = device_name;
+ this.security_level = security_level;
this.session_id = null;
this.challenge = null;
this.keys = null;
}
- // Open PlayReady session
- openSession() {
- const url = `${this.host}/remotecdm/playready/${this.device_name}/open`;
+ openSession(path) {
+ const url = `${this.host}${path}/open`;
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
@@ -219,126 +202,127 @@ class remotePlayReadyCDM {
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.session_id) {
this.session_id = jsonData.data.session_id;
- console.log("PlayReady session opened:", this.session_id);
+ console.log("Session opened:", this.session_id);
} else {
- console.error("Failed to open PlayReady session:", jsonData.message);
- throw new Error("Failed to open PlayReady session");
+ console.error("Failed to open session:", jsonData.message);
+ throw new Error("Failed to open session");
}
}
- // Get PlayReady challenge
- getChallenge(init_data) {
- const url = `${this.host}/remotecdm/playready/${this.device_name}/get_license_challenge`;
+ getChallenge(path, body) {
+ const url = `${this.host}${path}/get_license_challenge`;
const xhr = new XMLHttpRequest();
xhr.open("POST", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
- const body = {
- session_id: this.session_id,
- init_data: init_data,
- };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.challenge) {
this.challenge = btoa(jsonData.data.challenge);
- console.log("PlayReady challenge received:", this.challenge);
+ console.log("Challenge received:", this.challenge);
+ } else if (jsonData.data?.challenge_b64) {
+ this.challenge = jsonData.data.challenge_b64;
+ console.log("Challenge received:", this.challenge);
} else {
- console.error("Failed to get PlayReady challenge:", jsonData.message);
- throw new Error("Failed to get PlayReady challenge");
+ console.error("Failed to get challenge:", jsonData.message);
+ throw new Error("Failed to get challenge");
}
}
- // Parse PlayReady license response
- parseLicense(license_message) {
- const url = `${this.host}/remotecdm/playready/${this.device_name}/parse_license`;
+ parseLicense(path, body) {
+ const url = `${this.host}${path}/parse_license`;
const xhr = new XMLHttpRequest();
xhr.open("POST", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
- const body = {
- session_id: this.session_id,
- license_message: license_message,
- };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
- if (
- jsonData.message === "Successfully parsed and loaded the Keys from the License message"
- ) {
- console.log("PlayReady license response parsed successfully");
+ if (jsonData.status === 200 || jsonData.message?.includes("parsed and loaded")) {
+ console.log("License response parsed successfully");
return true;
} else {
- console.error("Failed to parse PlayReady license response:", jsonData.message);
- throw new Error("Failed to parse PlayReady license response");
+ console.error("Failed to parse license response:", jsonData.message);
+ throw new Error("Failed to parse license response");
}
}
- // Get PlayReady keys
- getKeys() {
- const url = `${this.host}/remotecdm/playready/${this.device_name}/get_keys`;
+ getKeys(path, body, extraPath = "") {
+ const url = `${this.host}${path}/get_keys${extraPath}`;
const xhr = new XMLHttpRequest();
xhr.open("POST", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
- const body = {
- session_id: this.session_id,
- };
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.keys) {
this.keys = jsonData.data.keys;
- console.log("PlayReady keys received:", this.keys);
+ console.log("Keys received:", this.keys);
} else {
- console.error("Failed to get PlayReady keys:", jsonData.message);
- throw new Error("Failed to get PlayReady keys");
+ console.error("Failed to get keys:", jsonData.message);
+ throw new Error("Failed to get keys");
}
}
- // Close PlayReady session
- closeSession() {
- const url = `${this.host}/remotecdm/playready/${this.device_name}/close/${this.session_id}`;
+ closeSession(path) {
+ const url = `${this.host}${path}/close/${this.session_id}`;
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData) {
- console.log("PlayReady session closed successfully");
+ console.log("Session closed successfully");
} else {
- console.error("Failed to close PlayReady session:", jsonData.message);
- throw new Error("Failed to close PlayReady session");
+ console.error("Failed to close session:", jsonData.message);
+ throw new Error("Failed to close session");
}
}
}
+// PlayReady Remote CDM Class
+class remotePlayReadyCDM extends RemoteCDMBase {
+ constructor(security_level, host, secret, device_name) {
+ super({ host, secret, device_name, security_level });
+ }
+
+ openSession() {
+ super.openSession(`/remotecdm/playready/${this.device_name}`);
+ }
+
+ getChallenge(init_data) {
+ super.getChallenge(`/remotecdm/playready/${this.device_name}`, {
+ session_id: this.session_id,
+ init_data: init_data,
+ });
+ }
+
+ parseLicense(license_message) {
+ return super.parseLicense(`/remotecdm/playready/${this.device_name}`, {
+ session_id: this.session_id,
+ license_message: license_message,
+ });
+ }
+
+ getKeys() {
+ super.getKeys(`/remotecdm/playready/${this.device_name}`, {
+ session_id: this.session_id,
+ });
+ }
+
+ closeSession() {
+ super.closeSession(`/remotecdm/playready/${this.device_name}`);
+ }
+}
+
// Widevine Remote CDM Class
-class remoteWidevineCDM {
+class remoteWidevineCDM extends RemoteCDMBase {
constructor(device_type, system_id, security_level, host, secret, device_name) {
+ super({ host, secret, device_name, security_level });
this.device_type = device_type;
this.system_id = system_id;
- this.security_level = security_level;
- this.host = host;
- this.secret = secret;
- this.device_name = device_name;
- this.session_id = null;
- this.challenge = null;
- this.keys = null;
}
- // Open Widevine session
openSession() {
- const url = `${this.host}/remotecdm/widevine/${this.device_name}/open`;
- const xhr = new XMLHttpRequest();
- xhr.open("GET", url, false);
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.send();
- const jsonData = JSON.parse(xhr.responseText);
- if (jsonData.data?.session_id) {
- this.session_id = jsonData.data.session_id;
- console.log("Widevine session opened:", this.session_id);
- } else {
- console.error("Failed to open Widevine session:", jsonData.message);
- throw new Error("Failed to open Widevine session");
- }
+ super.openSession(`/remotecdm/widevine/${this.device_name}`);
}
- // Set Widevine service certificate
setServiceCertificate(certificate) {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/set_service_certificate`;
const xhr = new XMLHttpRequest();
@@ -358,7 +342,6 @@ class remoteWidevineCDM {
}
}
- // Get Widevine challenge
getChallenge(init_data, license_type = "STREAMING") {
const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_license_challenge/${license_type}`;
const xhr = new XMLHttpRequest();
@@ -380,61 +363,25 @@ class remoteWidevineCDM {
}
}
- // Parse Widevine license response
parseLicense(license_message) {
- const url = `${this.host}/remotecdm/widevine/${this.device_name}/parse_license`;
- const xhr = new XMLHttpRequest();
- xhr.open("POST", url, false);
- xhr.setRequestHeader("Content-Type", "application/json");
- const body = {
+ return super.parseLicense(`/remotecdm/widevine/${this.device_name}`, {
session_id: this.session_id,
license_message: license_message,
- };
- xhr.send(JSON.stringify(body));
- const jsonData = JSON.parse(xhr.responseText);
- if (jsonData.status === 200) {
- console.log("Widevine license response parsed successfully");
- return true;
- } else {
- console.error("Failed to parse Widevine license response:", jsonData.message);
- throw new Error("Failed to parse Widevine license response");
- }
+ });
}
- // Get Widevine keys
getKeys() {
- const url = `${this.host}/remotecdm/widevine/${this.device_name}/get_keys/ALL`;
- const xhr = new XMLHttpRequest();
- xhr.open("POST", url, false);
- xhr.setRequestHeader("Content-Type", "application/json");
- const body = {
- session_id: this.session_id,
- };
- xhr.send(JSON.stringify(body));
- const jsonData = JSON.parse(xhr.responseText);
- if (jsonData.data?.keys) {
- this.keys = jsonData.data.keys;
- console.log("Widevine keys received:", this.keys);
- } else {
- console.error("Failed to get Widevine keys:", jsonData.message);
- throw new Error("Failed to get Widevine keys");
- }
+ super.getKeys(
+ `/remotecdm/widevine/${this.device_name}`,
+ {
+ session_id: this.session_id,
+ },
+ "/ALL"
+ );
}
- // Close Widevine session
closeSession() {
- const url = `${this.host}/remotecdm/widevine/${this.device_name}/close/${this.session_id}`;
- const xhr = new XMLHttpRequest();
- xhr.open("GET", url, false);
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.send();
- const jsonData = JSON.parse(xhr.responseText);
- if (jsonData) {
- console.log("Widevine session closed successfully");
- } else {
- console.error("Failed to close Widevine session:", jsonData.message);
- throw new Error("Failed to close Widevine session");
- }
+ super.closeSession(`/remotecdm/widevine/${this.device_name}`);
}
}
--
2.43.0
From 30e797bc09d4d44dd53b20b5e6e1c8bbab17dede Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 11:54:40 +0700
Subject: [PATCH 14/26] use global `DRM_SIGNATURES` for readability
---
src/inject.js | 106 +++++++++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 40 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 915083f..3b16d9d 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -17,6 +17,13 @@ let foundChallengeInBody = false;
let licenseResponseCounter = 0;
let keysRetrieved = false;
+const DRM_SIGNATURES = {
+ WIDEVINE: "CAES",
+ PLAYREADY: "PD94",
+ SERVICE_CERT: "CAUS",
+ WIDEVINE_INIT: "CAQ=",
+};
+
// Post message to content.js to get DRM override
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
@@ -398,7 +405,7 @@ function b64ToHexStr(b64) {
return [...atob(b64)].map((c) => c.charCodeAt(0).toString(16).padStart(2, "0")).join``;
}
-function jsonContainsValue(obj, prefix = "CAES") {
+function jsonContainsValue(obj, prefix = DRM_SIGNATURES.WIDEVINE) {
if (typeof obj === "string") return obj.startsWith(prefix);
if (Array.isArray(obj)) return obj.some((val) => jsonContainsValue(val, prefix));
if (typeof obj === "object" && obj !== null) {
@@ -409,7 +416,9 @@ function jsonContainsValue(obj, prefix = "CAES") {
function jsonReplaceValue(obj, newValue) {
if (typeof obj === "string") {
- return obj.startsWith("CAES") || obj.startsWith("PD94") ? newValue : obj;
+ return obj.startsWith(DRM_SIGNATURES.WIDEVINE) || obj.startsWith(DRM_SIGNATURES.PLAYREADY)
+ ? newValue
+ : obj;
}
if (Array.isArray(obj)) {
@@ -516,7 +525,11 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
event.stopImmediatePropagation();
const uint8Array = new Uint8Array(event.message);
const base64challenge = arrayBufferToBase64(uint8Array);
- if (base64challenge === "CAQ=" && interceptType !== "DISABLED" && !serviceCertFound) {
+ if (
+ base64challenge === DRM_SIGNATURES.WIDEVINE_INIT &&
+ interceptType !== "DISABLED" &&
+ !serviceCertFound
+ ) {
const { device_type, system_id, security_level, host, secret, device_name } =
widevineDeviceInfo;
remoteCDM = new remoteWidevineCDM(
@@ -529,14 +542,18 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
);
remoteCDM.openSession();
}
- if (!injectionSuccess && base64challenge !== "CAQ=" && interceptType !== "DISABLED") {
+ if (
+ !injectionSuccess &&
+ base64challenge !== DRM_SIGNATURES.WIDEVINE_INIT &&
+ interceptType !== "DISABLED"
+ ) {
if (interceptType === "EME") {
injectionSuccess = true;
}
if (!originalChallenge) {
originalChallenge = base64challenge;
}
- if (originalChallenge.startsWith("CAES")) {
+ if (originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
window.postMessage({ type: "__DRM_TYPE__", data: "Widevine" }, "*");
window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
if (interceptType === "EME" && !remoteCDM) {
@@ -560,7 +577,7 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
remoteCDM.getChallenge(foundWidevinePssh);
}
}
- if (!originalChallenge.startsWith("CAES")) {
+ if (!originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
const buffer = event.message;
const decoder = new TextDecoder("utf-16");
const decodedText = decoder.decode(buffer);
@@ -616,7 +633,12 @@ const originalUpdate = MediaKeySession.prototype.update;
MediaKeySession.prototype.update = function (response) {
const uint8 = response instanceof Uint8Array ? response : new Uint8Array(response);
const base64Response = window.btoa(String.fromCharCode(...uint8));
- if (base64Response.startsWith("CAUS") && foundWidevinePssh && remoteCDM && !serviceCertFound) {
+ if (
+ base64Response.startsWith(DRM_SIGNATURES.SERVICE_CERT) &&
+ foundWidevinePssh &&
+ remoteCDM &&
+ !serviceCertFound
+ ) {
remoteCDM.setServiceCertificate(base64Response);
if (interceptType === "EME" && !remoteCDM.challenge) {
remoteCDM.getChallenge(foundWidevinePssh);
@@ -626,7 +648,7 @@ MediaKeySession.prototype.update = function (response) {
serviceCertFound = true;
}
if (
- !base64Response.startsWith("CAUS") &&
+ !base64Response.startsWith(DRM_SIGNATURES.SERVICE_CERT) &&
(foundWidevinePssh || foundPlayreadyPssh) &&
!keysRetrieved
) {
@@ -680,7 +702,8 @@ MediaKeySession.prototype.update = function (response) {
const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
const base64Body = window.btoa(String.fromCharCode(...buffer));
if (
- (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM ||
remoteCDM.challenge === null ||
base64Body !== remoteCDM.challenge) &&
@@ -692,14 +715,15 @@ MediaKeySession.prototype.update = function (response) {
return;
}
if (
- (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
interceptType == "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
- if (base64Body.startsWith("CAES")) {
+ if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -719,7 +743,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64Body.startsWith("PD94")) {
+ if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
@@ -743,8 +767,8 @@ MediaKeySession.prototype.update = function (response) {
if (typeof body === "string" && !isJson(body)) {
const base64EncodedBody = btoa(body);
if (
- (base64EncodedBody.startsWith("CAES") ||
- base64EncodedBody.startsWith("PD94")) &&
+ (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM ||
remoteCDM.challenge === null ||
base64EncodedBody !== remoteCDM.challenge) &&
@@ -756,15 +780,15 @@ MediaKeySession.prototype.update = function (response) {
return;
}
if (
- (base64EncodedBody.startsWith("CAES") ||
- base64EncodedBody.startsWith("PD94")) &&
+ (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
interceptType == "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
- if (base64EncodedBody.startsWith("CAES")) {
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -784,7 +808,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64EncodedBody.startsWith("PD94")) {
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
@@ -809,8 +833,8 @@ MediaKeySession.prototype.update = function (response) {
const jsonBody = JSON.parse(body);
if (
- (jsonContainsValue(jsonBody, "CAES") ||
- jsonContainsValue(jsonBody, "PD94")) &&
+ (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
+ jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM || remoteCDM.challenge === null) &&
interceptType === "EME"
) {
@@ -821,15 +845,15 @@ MediaKeySession.prototype.update = function (response) {
}
if (
- (jsonContainsValue(jsonBody, "CAES") ||
- jsonContainsValue(jsonBody, "PD94")) &&
+ (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
+ jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
interceptType === "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, "CAES")) {
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -849,7 +873,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (jsonContainsValue(jsonBody, "PD94")) {
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
@@ -894,7 +918,8 @@ MediaKeySession.prototype.update = function (response) {
const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
const base64Body = window.btoa(String.fromCharCode(...buffer));
if (
- (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM ||
remoteCDM.challenge === null ||
base64Body !== remoteCDM.challenge) &&
@@ -906,14 +931,15 @@ MediaKeySession.prototype.update = function (response) {
return;
}
if (
- (base64Body.startsWith("CAES") || base64Body.startsWith("PD94")) &&
+ (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
interceptType == "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
- if (base64Body.startsWith("CAES")) {
+ if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -933,7 +959,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64Body.startsWith("PD94")) {
+ if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
@@ -957,8 +983,8 @@ MediaKeySession.prototype.update = function (response) {
if (typeof body === "string" && !isJson(body)) {
const base64EncodedBody = btoa(body);
if (
- (base64EncodedBody.startsWith("CAES") ||
- base64EncodedBody.startsWith("PD94")) &&
+ (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM ||
remoteCDM.challenge === null ||
base64EncodedBody !== remoteCDM.challenge) &&
@@ -970,15 +996,15 @@ MediaKeySession.prototype.update = function (response) {
return;
}
if (
- (base64EncodedBody.startsWith("CAES") ||
- base64EncodedBody.startsWith("PD94")) &&
+ (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
+ base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
interceptType == "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
- if (base64EncodedBody.startsWith("CAES")) {
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -998,7 +1024,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (base64EncodedBody.startsWith("PD94")) {
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
@@ -1023,8 +1049,8 @@ MediaKeySession.prototype.update = function (response) {
const jsonBody = JSON.parse(body);
if (
- (jsonContainsValue(jsonBody, "CAES") ||
- jsonContainsValue(jsonBody, "PD94")) &&
+ (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
+ jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
(!remoteCDM || remoteCDM.challenge === null) &&
interceptType === "EME"
) {
@@ -1035,15 +1061,15 @@ MediaKeySession.prototype.update = function (response) {
}
if (
- (jsonContainsValue(jsonBody, "CAES") ||
- jsonContainsValue(jsonBody, "PD94")) &&
+ (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
+ jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
interceptType === "LICENSE" &&
!foundChallengeInBody
) {
foundChallengeInBody = true;
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, "CAES")) {
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
const {
device_type,
system_id,
@@ -1063,7 +1089,7 @@ MediaKeySession.prototype.update = function (response) {
remoteCDM.openSession();
remoteCDM.getChallenge(foundWidevinePssh);
}
- if (jsonContainsValue(jsonBody, "PD94")) {
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
const { security_level, host, secret, device_name } =
playreadyDeviceInfo;
remoteCDM = new remotePlayReadyCDM(
--
2.43.0
From 89f66b25be3daedb6919d09b5da7d3b2388ef334 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 16:05:35 +0700
Subject: [PATCH 15/26] add extension prefix and color for ease of debugging
and filtering
---
src/background.js | 35 +++++++----
src/content.js | 17 +++++-
src/inject.js | 149 +++++++++++++++++++++++++++-------------------
3 files changed, 128 insertions(+), 73 deletions(-)
diff --git a/src/background.js b/src/background.js
index bbd7fd6..b5f70fc 100644
--- a/src/background.js
+++ b/src/background.js
@@ -13,27 +13,27 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch (type) {
case "DRM_TYPE":
- console.log("DRM Type:", data);
+ logWithPrefix("DRM Type:", data);
chrome.storage.local.set({ drmType: data });
break;
case "PSSH_DATA":
- console.log("Storing PSSH:", data);
+ logWithPrefix("Storing PSSH:", data);
chrome.storage.local.set({ latestPSSH: data });
break;
case "KEYS_DATA":
- console.log("Storing Decryption Keys:", data);
+ logWithPrefix("Storing Decryption Keys:", data);
chrome.storage.local.set({ latestKeys: data });
break;
case "LICENSE_URL":
- console.log("Storling License URL " + data);
+ logWithPrefix("Storling License URL " + data);
chrome.storage.local.set({ licenseURL: data });
break;
case "MANIFEST_URL":
- console.log("Storing Manifest URL:", data);
+ logWithPrefix("Storing Manifest URL:", data);
chrome.storage.local.set({ manifestURL: data });
break;
@@ -44,12 +44,27 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Set initial config and injection type on install
chrome.runtime.onInstalled.addListener((details) => {
+ const EXTENSION_PREFIX = "[CDRM EXTENSION]";
+ const PREFIX_COLOR = "black";
+ const PREFIX_BACKGROUND_COLOR = "yellow";
+
+ const logWithPrefix = (...args) => {
+ const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
+ if (typeof args[0] === "string") {
+ // If the first arg is a string, prepend the prefix
+ console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
+ } else {
+ // If not, just log the prefix and the rest
+ console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
+ }
+ };
+
if (details.reason === "install") {
chrome.storage.local.set({ valid_config: false }, () => {
if (chrome.runtime.lastError) {
console.error("Error setting valid_config:", chrome.runtime.lastError);
} else {
- console.log("valid_config set to false on first install.");
+ logWithPrefix("valid_config set to false on first install.");
}
});
@@ -57,7 +72,7 @@ chrome.runtime.onInstalled.addListener((details) => {
if (chrome.runtime.lastError) {
console.error("Error setting Injection Type:", chrome.runtime.lastError);
} else {
- console.log("Injection type set to LICENSE on first install.");
+ logWithPrefix("Injection type set to LICENSE on first install.");
}
});
@@ -65,7 +80,7 @@ chrome.runtime.onInstalled.addListener((details) => {
if (chrome.runtime.lastError) {
console.error("Error setting DRM Override type:", chrome.runtime.lastError);
} else {
- console.log("DRM Override type set to DISABLED on first install.");
+ logWithPrefix("DRM Override type set to DISABLED on first install.");
}
});
@@ -73,7 +88,7 @@ chrome.runtime.onInstalled.addListener((details) => {
if (chrome.runtime.lastError) {
console.error("Error setting CDRM instance:", chrome.runtime.lastError);
} else {
- console.log("CDRM instance set to null.");
+ logWithPrefix("CDRM instance set to null.");
}
});
@@ -81,7 +96,7 @@ chrome.runtime.onInstalled.addListener((details) => {
if (chrome.runtime.lastError) {
console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
} else {
- console.log("CDRM API Key set.");
+ logWithPrefix("CDRM API Key set.");
}
});
}
diff --git a/src/content.js b/src/content.js
index 0e12c93..221035d 100644
--- a/src/content.js
+++ b/src/content.js
@@ -68,6 +68,19 @@ window.addEventListener("message", function (event) {
}
// Manifest header and URL
+ const EXTENSION_PREFIX = "[CDRM EXTENSION]";
+ const PREFIX_COLOR = "black";
+ const PREFIX_BACKGROUND_COLOR = "yellow";
+ const logWithPrefix = (...args) => {
+ const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
+ if (typeof args[0] === "string") {
+ // If the first arg is a string, prepend the prefix
+ console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
+ } else {
+ // If not, just log the prefix and the rest
+ console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
+ }
+ };
const seenManifestUrls = new Set();
@@ -75,7 +88,7 @@ window.addEventListener("message", function (event) {
const url = event.data.data;
if (seenManifestUrls.has(url)) return;
seenManifestUrls.add(url);
- console.log("✅ [Content] Unique manifest URL:", url);
+ logWithPrefix("✅ [Content] Unique manifest URL:", url);
chrome.runtime.sendMessage({
type: "MANIFEST_URL",
@@ -85,7 +98,7 @@ window.addEventListener("message", function (event) {
if (event.data?.type === "__MANIFEST_HEADERS__") {
const { url, headers } = event.data;
- console.log("[Content.js] Manifest Headers:", url, headers);
+ logWithPrefix("[Content.js] Manifest Headers:", url, headers);
chrome.runtime.sendMessage({
type: "MANIFEST_HEADERS",
diff --git a/src/inject.js b/src/inject.js
index 3b16d9d..3b463bc 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -24,6 +24,21 @@ const DRM_SIGNATURES = {
WIDEVINE_INIT: "CAQ=",
};
+const EXTENSION_PREFIX = "[CDRM EXTENSION]";
+const PREFIX_COLOR = "black";
+const PREFIX_BACKGROUND_COLOR = "yellow";
+
+const logWithPrefix = (...args) => {
+ const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
+ if (typeof args[0] === "string") {
+ // If the first arg is a string, prepend the prefix
+ console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
+ } else {
+ // If not, just log the prefix and the rest
+ console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
+ }
+};
+
// Post message to content.js to get DRM override
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
@@ -32,7 +47,7 @@ window.addEventListener("message", function (event) {
if (event.source !== window) return;
if (event.data.type === "__DRM_OVERRIDE__") {
drmOverride = event.data.drmOverride || "DISABLED";
- console.log("DRM Override set to:", drmOverride);
+ logWithPrefix("DRM Override set to:", drmOverride);
}
});
@@ -45,7 +60,7 @@ window.addEventListener("message", function (event) {
if (event.data.type === "__INJECTION_TYPE__") {
interceptType = event.data.injectionType || "DISABLED";
- console.log("Injection type set to:", interceptType);
+ logWithPrefix("Injection type set to:", interceptType);
}
});
@@ -59,7 +74,7 @@ window.addEventListener("message", function (event) {
if (event.data.type === "__CDM_DEVICES__") {
const { widevine_device, playready_device } = event.data;
- console.log("Received device info:", widevine_device, playready_device);
+ logWithPrefix("Received device info:", widevine_device, playready_device);
widevineDeviceInfo = widevine_device;
playreadyDeviceInfo = playready_device;
@@ -90,7 +105,7 @@ function headersToFlags(headersObj) {
function handleManifestDetection(url, headersObj, contentType, source) {
window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
- console.log(`[Manifest][${source}]`, url, contentType);
+ logWithPrefix(`[Manifest][${source}]`, url, contentType);
const headerFlags = headersToFlags(headersObj);
@@ -209,7 +224,7 @@ class RemoteCDMBase {
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.session_id) {
this.session_id = jsonData.data.session_id;
- console.log("Session opened:", this.session_id);
+ logWithPrefix("Session opened:", this.session_id);
} else {
console.error("Failed to open session:", jsonData.message);
throw new Error("Failed to open session");
@@ -225,10 +240,10 @@ class RemoteCDMBase {
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.challenge) {
this.challenge = btoa(jsonData.data.challenge);
- console.log("Challenge received:", this.challenge);
+ logWithPrefix("Challenge received:", this.challenge);
} else if (jsonData.data?.challenge_b64) {
this.challenge = jsonData.data.challenge_b64;
- console.log("Challenge received:", this.challenge);
+ logWithPrefix("Challenge received:", this.challenge);
} else {
console.error("Failed to get challenge:", jsonData.message);
throw new Error("Failed to get challenge");
@@ -243,7 +258,7 @@ class RemoteCDMBase {
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.status === 200 || jsonData.message?.includes("parsed and loaded")) {
- console.log("License response parsed successfully");
+ logWithPrefix("License response parsed successfully");
return true;
} else {
console.error("Failed to parse license response:", jsonData.message);
@@ -260,7 +275,7 @@ class RemoteCDMBase {
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.keys) {
this.keys = jsonData.data.keys;
- console.log("Keys received:", this.keys);
+ logWithPrefix("Keys received:", this.keys);
} else {
console.error("Failed to get keys:", jsonData.message);
throw new Error("Failed to get keys");
@@ -275,7 +290,7 @@ class RemoteCDMBase {
xhr.send();
const jsonData = JSON.parse(xhr.responseText);
if (jsonData) {
- console.log("Session closed successfully");
+ logWithPrefix("Session closed successfully");
} else {
console.error("Failed to close session:", jsonData.message);
throw new Error("Failed to close session");
@@ -342,7 +357,7 @@ class remoteWidevineCDM extends RemoteCDMBase {
xhr.send(JSON.stringify(body));
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.status === 200) {
- console.log("Service certificate set successfully");
+ logWithPrefix("Service certificate set successfully");
} else {
console.error("Failed to set service certificate:", jsonData.message);
throw new Error("Failed to set service certificate");
@@ -363,7 +378,7 @@ class remoteWidevineCDM extends RemoteCDMBase {
const jsonData = JSON.parse(xhr.responseText);
if (jsonData.data?.challenge_b64) {
this.challenge = jsonData.data.challenge_b64;
- console.log("Widevine challenge received:", this.challenge);
+ logWithPrefix("Widevine challenge received:", this.challenge);
} else {
console.error("Failed to get Widevine challenge:", jsonData.message);
throw new Error("Failed to get Widevine challenge");
@@ -501,30 +516,74 @@ function arrayBufferToBase64(uint8array) {
return window.btoa(binary);
}
+function bufferToBase64(buffer) {
+ const uint8 = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
+ return window.btoa(String.fromCharCode(...uint8));
+}
+
+// DRM type detection
+function isWidevine(base64str) {
+ return base64str.startsWith(DRM_SIGNATURES.WIDEVINE);
+}
+function isPlayReady(base64str) {
+ return base64str.startsWith(DRM_SIGNATURES.PLAYREADY);
+}
+function isServiceCertificate(base64str) {
+ return base64str.startsWith(DRM_SIGNATURES.SERVICE_CERT);
+}
+
+function postDRMTypeAndPssh(type, pssh) {
+ window.postMessage({ type: "__DRM_TYPE__", data: type }, "*");
+ window.postMessage({ type: "__PSSH_DATA__", data: pssh }, "*");
+}
+
+function ensureRemoteCDM(type, deviceInfo, pssh) {
+ if (!remoteCDM) {
+ if (type === "Widevine") {
+ const { device_type, system_id, security_level, host, secret, device_name } =
+ deviceInfo;
+ remoteCDM = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(pssh);
+ } else if (type === "PlayReady") {
+ const { security_level, host, secret, device_name } = deviceInfo;
+ remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
+ remoteCDM.openSession();
+ remoteCDM.getChallenge(pssh);
+ }
+ }
+}
+
// Challenge generator interceptor
const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
const session = this;
let playReadyPssh = getPlayReadyPssh(initData);
if (playReadyPssh) {
- console.log("[DRM Detected] PlayReady");
+ logWithPrefix("[DRM Detected] PlayReady");
foundPlayreadyPssh = playReadyPssh;
- console.log("[PlayReady PSSH found] " + playReadyPssh);
+ logWithPrefix("[PlayReady PSSH found] " + playReadyPssh);
}
let wideVinePssh = getWidevinePssh(initData);
if (wideVinePssh) {
// Widevine code
- console.log("[DRM Detected] Widevine");
+ logWithPrefix("[DRM Detected] Widevine");
foundWidevinePssh = wideVinePssh;
- console.log("[Widevine PSSH found] " + wideVinePssh);
+ logWithPrefix("[Widevine PSSH found] " + wideVinePssh);
}
// Challenge message interceptor
if (!remoteListenerMounted) {
remoteListenerMounted = true;
session.addEventListener("message", function messageInterceptor(event) {
event.stopImmediatePropagation();
- const uint8Array = new Uint8Array(event.message);
- const base64challenge = arrayBufferToBase64(uint8Array);
+ const base64challenge = bufferToBase64(event.message);
if (
base64challenge === DRM_SIGNATURES.WIDEVINE_INIT &&
interceptType !== "DISABLED" &&
@@ -554,27 +613,9 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
originalChallenge = base64challenge;
}
if (originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- window.postMessage({ type: "__DRM_TYPE__", data: "Widevine" }, "*");
- window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
- if (interceptType === "EME" && !remoteCDM) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
- );
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
+ postDRMTypeAndPssh("Widevine", foundWidevinePssh);
+ if (interceptType === "EME") {
+ ensureRemoteCDM("Widevine", widevineDeviceInfo, foundWidevinePssh);
}
}
if (!originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
@@ -585,23 +626,10 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
/([^<]+)<\/Challenge>/
);
if (match) {
- window.postMessage({ type: "__DRM_TYPE__", data: "PlayReady" }, "*");
- window.postMessage(
- { type: "__PSSH_DATA__", data: foundPlayreadyPssh },
- "*"
- );
+ postDRMTypeAndPssh("PlayReady", foundPlayreadyPssh);
originalChallenge = match[1];
- if (interceptType === "EME" && !remoteCDM) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
- );
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
+ if (interceptType === "EME") {
+ ensureRemoteCDM("PlayReady", playreadyDeviceInfo, foundPlayreadyPssh);
}
}
}
@@ -618,12 +646,12 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
Object.defineProperty(syntheticEvent, "message", {
get: () => challengeBuffer,
});
- console.log("Intercepted EME Challenge and injected custom one.");
+ logWithPrefix("Intercepted EME Challenge and injected custom one.");
session.dispatchEvent(syntheticEvent);
}
}
});
- console.log("Message interceptor mounted.");
+ logWithPrefix("Message interceptor mounted.");
}
return originalGenerateRequest.call(session, initDataType, initData);
};
@@ -631,8 +659,7 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
// Message update interceptors
const originalUpdate = MediaKeySession.prototype.update;
MediaKeySession.prototype.update = function (response) {
- const uint8 = response instanceof Uint8Array ? response : new Uint8Array(response);
- const base64Response = window.btoa(String.fromCharCode(...uint8));
+ const base64Response = bufferToBase64(response);
if (
base64Response.startsWith(DRM_SIGNATURES.SERVICE_CERT) &&
foundWidevinePssh &&
@@ -667,7 +694,7 @@ MediaKeySession.prototype.update = function (response) {
.then(() => {
let clearKeys = getClearkey(response);
if (clearKeys && clearKeys.length > 0) {
- console.log("[CLEARKEY] ", clearKeys);
+ logWithPrefix("[CLEARKEY] ", clearKeys);
const drmType = {
type: "__DRM_TYPE__",
data: "ClearKey",
@@ -681,7 +708,7 @@ MediaKeySession.prototype.update = function (response) {
}
})
.catch((e) => {
- console.log("[CLEARKEY] Not found");
+ logWithPrefix("[CLEARKEY] Not found");
});
}
--
2.43.0
From 9e071365e372dda6424041f37eff597be50819cb Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 17:18:18 +0700
Subject: [PATCH 16/26] use regular prefix instead of adding color. fixes not
storing to `chrome.storage.local`
---
src/background.js | 47 ++++++++++++++++-------------------------------
src/content.js | 19 +++----------------
2 files changed, 19 insertions(+), 47 deletions(-)
diff --git a/src/background.js b/src/background.js
index b5f70fc..03c5e12 100644
--- a/src/background.js
+++ b/src/background.js
@@ -13,90 +13,75 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch (type) {
case "DRM_TYPE":
- logWithPrefix("DRM Type:", data);
+ console.log("[CDRM-Extension] DRM Type:", data);
chrome.storage.local.set({ drmType: data });
break;
case "PSSH_DATA":
- logWithPrefix("Storing PSSH:", data);
+ console.log("[CDRM-Extension] Storing PSSH:", data);
chrome.storage.local.set({ latestPSSH: data });
break;
case "KEYS_DATA":
- logWithPrefix("Storing Decryption Keys:", data);
+ console.log("[CDRM-Extension] Storing Decryption Keys:", data);
chrome.storage.local.set({ latestKeys: data });
break;
case "LICENSE_URL":
- logWithPrefix("Storling License URL " + data);
+ console.log("[CDRM-Extension] Storing License URL " + data);
chrome.storage.local.set({ licenseURL: data });
break;
case "MANIFEST_URL":
- logWithPrefix("Storing Manifest URL:", data);
+ console.log("[CDRM-Extension] Storing Manifest URL:", data);
chrome.storage.local.set({ manifestURL: data });
break;
default:
- console.warn("Unknown message type received:", type);
+ console.warn("[CDRM-Extension] Unknown message type received:", type);
}
});
// Set initial config and injection type on install
chrome.runtime.onInstalled.addListener((details) => {
- const EXTENSION_PREFIX = "[CDRM EXTENSION]";
- const PREFIX_COLOR = "black";
- const PREFIX_BACKGROUND_COLOR = "yellow";
-
- const logWithPrefix = (...args) => {
- const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
- if (typeof args[0] === "string") {
- // If the first arg is a string, prepend the prefix
- console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
- } else {
- // If not, just log the prefix and the rest
- console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
- }
- };
-
if (details.reason === "install") {
chrome.storage.local.set({ valid_config: false }, () => {
if (chrome.runtime.lastError) {
- console.error("Error setting valid_config:", chrome.runtime.lastError);
+ console.error("[CDRM-Extension] Error setting valid_config:", chrome.runtime.lastError);
} else {
- logWithPrefix("valid_config set to false on first install.");
+ console.log("[CDRM-Extension] valid_config set to false on first install.");
}
});
chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
if (chrome.runtime.lastError) {
- console.error("Error setting Injection Type:", chrome.runtime.lastError);
+ console.error("[CDRM-Extension] Error setting Injection Type:", chrome.runtime.lastError);
} else {
- logWithPrefix("Injection type set to LICENSE on first install.");
+ console.log("[CDRM-Extension] Injection type set to LICENSE on first install.");
}
});
chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
if (chrome.runtime.lastError) {
- console.error("Error setting DRM Override type:", chrome.runtime.lastError);
+ console.error("[CDRM-Extension] Error setting DRM Override type:", chrome.runtime.lastError);
} else {
- logWithPrefix("DRM Override type set to DISABLED on first install.");
+ console.log("[CDRM-Extension] DRM Override type set to DISABLED on first install.");
}
});
chrome.storage.local.set({ cdrm_instance: null }, () => {
if (chrome.runtime.lastError) {
- console.error("Error setting CDRM instance:", chrome.runtime.lastError);
+ console.error("[CDRM-Extension] Error setting CDRM instance:", chrome.runtime.lastError);
} else {
- logWithPrefix("CDRM instance set to null.");
+ console.log("[CDRM-Extension] CDRM instance set to null.");
}
});
chrome.storage.local.set({ cdrm_api_key: null }, () => {
if (chrome.runtime.lastError) {
- console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
+ console.error("[CDRM-Extension] Error setting CDRM API Key:", chrome.runtime.lastError);
} else {
- logWithPrefix("CDRM API Key set.");
+ console.log("[CDRM-Extension] CDRM API Key set.");
}
});
}
diff --git a/src/content.js b/src/content.js
index 221035d..85e397e 100644
--- a/src/content.js
+++ b/src/content.js
@@ -68,19 +68,6 @@ window.addEventListener("message", function (event) {
}
// Manifest header and URL
- const EXTENSION_PREFIX = "[CDRM EXTENSION]";
- const PREFIX_COLOR = "black";
- const PREFIX_BACKGROUND_COLOR = "yellow";
- const logWithPrefix = (...args) => {
- const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
- if (typeof args[0] === "string") {
- // If the first arg is a string, prepend the prefix
- console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
- } else {
- // If not, just log the prefix and the rest
- console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
- }
- };
const seenManifestUrls = new Set();
@@ -88,17 +75,17 @@ window.addEventListener("message", function (event) {
const url = event.data.data;
if (seenManifestUrls.has(url)) return;
seenManifestUrls.add(url);
- logWithPrefix("✅ [Content] Unique manifest URL:", url);
+ console.log("[CDRM-Extension] ✅ [content.js] Unique manifest URL:", url);
chrome.runtime.sendMessage({
- type: "MANIFEST_URL",
+ type: "MANIFEST_URL_FOUND",
data: url,
});
}
if (event.data?.type === "__MANIFEST_HEADERS__") {
const { url, headers } = event.data;
- logWithPrefix("[Content.js] Manifest Headers:", url, headers);
+ console.log("[CDRM-Extension] [content.js] Manifest headers:", url, headers);
chrome.runtime.sendMessage({
type: "MANIFEST_HEADERS",
--
2.43.0
From f8712d7726dcd70e299bda396f1660fcfb6923c0 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 18:28:59 +0700
Subject: [PATCH 17/26] refactor: consolidate remote cdm initialization into a
helper function
---
src/inject.js | 261 +++++++++++++++-----------------------------------
1 file changed, 76 insertions(+), 185 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 3b463bc..3156ae5 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -537,27 +537,32 @@ function postDRMTypeAndPssh(type, pssh) {
window.postMessage({ type: "__PSSH_DATA__", data: pssh }, "*");
}
+function createAndOpenRemoteCDM(type, deviceInfo, pssh) {
+ let cdm;
+ if (type === "Widevine") {
+ const { device_type, system_id, security_level, host, secret, device_name } = deviceInfo;
+ cdm = new remoteWidevineCDM(
+ device_type,
+ system_id,
+ security_level,
+ host,
+ secret,
+ device_name
+ );
+ cdm.openSession();
+ cdm.getChallenge(pssh);
+ } else if (type === "PlayReady") {
+ const { security_level, host, secret, device_name } = deviceInfo;
+ cdm = new remotePlayReadyCDM(security_level, host, secret, device_name);
+ cdm.openSession();
+ cdm.getChallenge(pssh);
+ }
+ return cdm;
+}
+
function ensureRemoteCDM(type, deviceInfo, pssh) {
if (!remoteCDM) {
- if (type === "Widevine") {
- const { device_type, system_id, security_level, host, secret, device_name } =
- deviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
- );
- remoteCDM.openSession();
- remoteCDM.getChallenge(pssh);
- } else if (type === "PlayReady") {
- const { security_level, host, secret, device_name } = deviceInfo;
- remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
- remoteCDM.openSession();
- remoteCDM.getChallenge(pssh);
- }
+ remoteCDM = createAndOpenRemoteCDM(type, deviceInfo, pssh);
}
}
@@ -589,17 +594,11 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
interceptType !== "DISABLED" &&
!serviceCertFound
) {
- const { device_type, system_id, security_level, host, secret, device_name } =
- widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
}
if (
!injectionSuccess &&
@@ -751,36 +750,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
@@ -816,36 +797,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
@@ -881,36 +844,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
if (!remoteCDM) {
if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
@@ -967,36 +912,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
@@ -1032,36 +959,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
@@ -1097,36 +1006,18 @@ MediaKeySession.prototype.update = function (response) {
window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
if (!remoteCDM) {
if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
- const {
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name,
- } = widevineDeviceInfo;
- remoteCDM = new remoteWidevineCDM(
- device_type,
- system_id,
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "Widevine",
+ widevineDeviceInfo,
+ foundWidevinePssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundWidevinePssh);
}
if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
- const { security_level, host, secret, device_name } =
- playreadyDeviceInfo;
- remoteCDM = new remotePlayReadyCDM(
- security_level,
- host,
- secret,
- device_name
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ foundPlayreadyPssh
);
- remoteCDM.openSession();
- remoteCDM.getChallenge(foundPlayreadyPssh);
}
}
if (remoteCDM && remoteCDM.challenge === null) {
--
2.43.0
From 867294f7f60135ae89d896bb01d809243dc3908b Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 20:25:47 +0700
Subject: [PATCH 18/26] refactor: extract DRM challenge detection and handling
for fetch and XHR requests
---
src/inject.js | 406 ++++++++++++++++----------------------------------
1 file changed, 130 insertions(+), 276 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 3156ae5..678a607 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -714,6 +714,81 @@ MediaKeySession.prototype.update = function (response) {
return updatePromise;
};
+// Helpers
+function detectDRMChallenge(body) {
+ // Handles ArrayBuffer, Uint8Array, string, and JSON string
+ // Returns: { type: "Widevine"|"PlayReady"|null, base64: string|null, bodyType: "buffer"|"string"|"json"|null }
+ if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
+ const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
+ const base64Body = window.btoa(String.fromCharCode(...buffer));
+ if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
+ return { type: "Widevine", base64: base64Body, bodyType: "buffer" };
+ }
+ if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
+ return { type: "PlayReady", base64: base64Body, bodyType: "buffer" };
+ }
+ } else if (typeof body === "string" && !isJson(body)) {
+ const base64EncodedBody = btoa(body);
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
+ return { type: "Widevine", base64: base64EncodedBody, bodyType: "string" };
+ }
+ if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
+ return { type: "PlayReady", base64: base64EncodedBody, bodyType: "string" };
+ }
+ } else if (typeof body === "string" && isJson(body)) {
+ const jsonBody = JSON.parse(body);
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
+ return { type: "Widevine", base64: null, bodyType: "json" };
+ }
+ if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
+ return { type: "PlayReady", base64: null, bodyType: "json" };
+ }
+ }
+ return { type: null, base64: null, bodyType: null };
+}
+
+function handleLicenseMode({
+ drmInfo,
+ body,
+ setBody, // function to set the new body (for fetch: (b) => config.body = b, for XHR: (b) => originalSend.call(this, b))
+ urlOrResource,
+ getWidevinePssh,
+ getPlayreadyPssh,
+ widevineDeviceInfo,
+ playreadyDeviceInfo,
+}) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: urlOrResource }, "*");
+
+ // Create remoteCDM if needed
+ if (!remoteCDM) {
+ if (drmInfo.type === "Widevine") {
+ remoteCDM = createAndOpenRemoteCDM("Widevine", widevineDeviceInfo, getWidevinePssh());
+ }
+ if (drmInfo.type === "PlayReady") {
+ remoteCDM = createAndOpenRemoteCDM(
+ "PlayReady",
+ playreadyDeviceInfo,
+ getPlayreadyPssh()
+ );
+ }
+ }
+ if (remoteCDM && remoteCDM.challenge === null) {
+ remoteCDM.getChallenge(getWidevinePssh());
+ }
+
+ // Inject the new challenge into the request body
+ if (drmInfo.bodyType === "json") {
+ const jsonBody = JSON.parse(body);
+ const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
+ setBody(JSON.stringify(injectedBody));
+ } else if (drmInfo.bodyType === "buffer") {
+ setBody(base64ToUint8Array(remoteCDM.challenge));
+ } else {
+ setBody(atob(remoteCDM.challenge));
+ }
+}
+
// fetch POST interceptor
(function () {
const originalFetch = window.fetch;
@@ -724,146 +799,37 @@ MediaKeySession.prototype.update = function (response) {
if (method === "POST") {
let body = config.body;
if (body) {
- if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
- const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
- const base64Body = window.btoa(String.fromCharCode(...buffer));
- if (
- (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- base64Body !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
- if (
- (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- interceptType == "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = base64ToUint8Array(remoteCDM.challenge);
- config.body = injectedBody;
- return originalFetch(resource, config);
- }
- }
- if (typeof body === "string" && !isJson(body)) {
- const base64EncodedBody = btoa(body);
- if (
- (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- base64EncodedBody !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
- if (
- (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- interceptType == "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = atob(remoteCDM.challenge);
- config.body = injectedBody;
- return originalFetch(resource, config);
- }
- }
- if (typeof body === "string" && isJson(body)) {
- const jsonBody = JSON.parse(body);
+ const drmInfo = detectDRMChallenge(body);
- if (
- (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
- jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM || remoteCDM.challenge === null) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
+ // EME mode: block the request if a DRM challenge is detected
+ if (
+ drmInfo.type &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ drmInfo.base64 !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
+ // Block the request
+ return;
+ }
- if (
- (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
- jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
- interceptType === "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
- config.body = JSON.stringify(injectedBody);
- }
+ // LICENSE mode: replace the challenge in the request
+ if (drmInfo.type && interceptType === "LICENSE" && !foundChallengeInBody) {
+ handleLicenseMode({
+ drmInfo,
+ body,
+ setBody: (b) => {
+ config.body = b;
+ },
+ urlOrResource: resource,
+ getWidevinePssh: () => foundWidevinePssh,
+ getPlayreadyPssh: () => foundPlayreadyPssh,
+ widevineDeviceInfo,
+ playreadyDeviceInfo,
+ });
+ return originalFetch(resource, config);
}
}
}
@@ -886,146 +852,34 @@ MediaKeySession.prototype.update = function (response) {
XMLHttpRequest.prototype.send = function (body) {
if (this._method && this._method.toUpperCase() === "POST") {
if (body) {
- if (body instanceof ArrayBuffer || body instanceof Uint8Array) {
- const buffer = body instanceof Uint8Array ? body : new Uint8Array(body);
- const base64Body = window.btoa(String.fromCharCode(...buffer));
- if (
- (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- base64Body !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
- if (
- (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- interceptType == "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (base64Body.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (base64Body.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = base64ToUint8Array(remoteCDM.challenge);
- return originalSend.call(this, injectedBody);
- }
+ const drmInfo = detectDRMChallenge(body);
+
+ // EME mode: block the request if a DRM challenge is detected
+ if (
+ drmInfo.type &&
+ (!remoteCDM ||
+ remoteCDM.challenge === null ||
+ drmInfo.base64 !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
+ // Block the request
+ return;
}
- if (typeof body === "string" && !isJson(body)) {
- const base64EncodedBody = btoa(body);
- if (
- (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- base64EncodedBody !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
- if (
- (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE) ||
- base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) &&
- interceptType == "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (base64EncodedBody.startsWith(DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (base64EncodedBody.startsWith(DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = atob(remoteCDM.challenge);
- return originalSend.call(this, injectedBody);
- }
- }
-
- if (typeof body === "string" && isJson(body)) {
- const jsonBody = JSON.parse(body);
-
- if (
- (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
- jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
- (!remoteCDM || remoteCDM.challenge === null) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
-
- if (
- (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE) ||
- jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) &&
- interceptType === "LICENSE" &&
- !foundChallengeInBody
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- if (!remoteCDM) {
- if (jsonContainsValue(jsonBody, DRM_SIGNATURES.WIDEVINE)) {
- remoteCDM = createAndOpenRemoteCDM(
- "Widevine",
- widevineDeviceInfo,
- foundWidevinePssh
- );
- }
- if (jsonContainsValue(jsonBody, DRM_SIGNATURES.PLAYREADY)) {
- remoteCDM = createAndOpenRemoteCDM(
- "PlayReady",
- playreadyDeviceInfo,
- foundPlayreadyPssh
- );
- }
- }
- if (remoteCDM && remoteCDM.challenge === null) {
- remoteCDM.getChallenge(foundWidevinePssh);
- }
- const injectedBody = jsonReplaceValue(jsonBody, remoteCDM.challenge);
- return originalSend.call(this, JSON.stringify(injectedBody));
- }
+ // LICENSE mode: replace the challenge in the request
+ if (drmInfo.type && interceptType === "LICENSE" && !foundChallengeInBody) {
+ return handleLicenseMode({
+ drmInfo,
+ body,
+ setBody: (b) => originalSend.call(this, b),
+ urlOrResource: this._url,
+ getWidevinePssh: () => foundWidevinePssh,
+ getPlayreadyPssh: () => foundPlayreadyPssh,
+ widevineDeviceInfo,
+ playreadyDeviceInfo,
+ });
}
}
}
--
2.43.0
From d0154fd6c12220b25613f69ea329ef6e39460256 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 22:57:28 +0700
Subject: [PATCH 19/26] change MANIFEST_URL_FOUND to MANIFEST_URL
---
src/content.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content.js b/src/content.js
index 85e397e..35c0497 100644
--- a/src/content.js
+++ b/src/content.js
@@ -78,7 +78,7 @@ window.addEventListener("message", function (event) {
console.log("[CDRM-Extension] ✅ [content.js] Unique manifest URL:", url);
chrome.runtime.sendMessage({
- type: "MANIFEST_URL_FOUND",
+ type: "MANIFEST_URL",
data: url,
});
}
--
2.43.0
From e03ca633de3236220d53a5100f844a324684054e Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Mon, 21 Jul 2025 23:29:40 +0700
Subject: [PATCH 20/26] do not show export if keys are not present
---
frontend/src/components/results.jsx | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/frontend/src/components/results.jsx b/frontend/src/components/results.jsx
index 7155419..4b60d67 100644
--- a/frontend/src/components/results.jsx
+++ b/frontend/src/components/results.jsx
@@ -144,13 +144,7 @@ function Results() {
// Export to JSON file
const hasData = () => {
- return (
- drmType ||
- pssh ||
- licenseUrl ||
- manifestUrl ||
- (Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0)
- );
+ return Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0;
};
const handleExportJSON = () => {
--
2.43.0
From 81f44b2f0ed7f1da9d3ec5b63abf25f83391d22e Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 09:52:12 +0700
Subject: [PATCH 21/26] concatenate message handling for DRM, injection type,
and CDM devices
---
src/inject.js | 52 +++++++++++++++++++++------------------------------
1 file changed, 21 insertions(+), 31 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 678a607..0dbedd9 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -39,46 +39,36 @@ const logWithPrefix = (...args) => {
}
};
-// Post message to content.js to get DRM override
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
-
-// Add listener for DRM override messages
-window.addEventListener("message", function (event) {
- if (event.source !== window) return;
- if (event.data.type === "__DRM_OVERRIDE__") {
- drmOverride = event.data.drmOverride || "DISABLED";
- logWithPrefix("DRM Override set to:", drmOverride);
- }
-});
-
-// Post message to content.js to get injection type
window.postMessage({ type: "__GET_INJECTION_TYPE__" }, "*");
-
-// Add listener for injection type messages
-window.addEventListener("message", function (event) {
- if (event.source !== window) return;
-
- if (event.data.type === "__INJECTION_TYPE__") {
- interceptType = event.data.injectionType || "DISABLED";
- logWithPrefix("Injection type set to:", interceptType);
- }
-});
-
-// Post message to get CDM devices
window.postMessage({ type: "__GET_CDM_DEVICES__" }, "*");
-// Add listener for CDM device messages
-window.addEventListener("message", function (event) {
- if (event.source !== window) return;
+function createMessageHandler(handlers) {
+ window.addEventListener("message", function (event) {
+ if (event.source !== window) return;
- if (event.data.type === "__CDM_DEVICES__") {
- const { widevine_device, playready_device } = event.data;
+ const handler = handlers[event.data.type];
+ if (handler) {
+ handler(event.data);
+ }
+ });
+}
+createMessageHandler({
+ __DRM_OVERRIDE__: (data) => {
+ drmOverride = data.drmOverride || "DISABLED";
+ logWithPrefix("DRM Override set to:", drmOverride);
+ },
+ __INJECTION_TYPE__: (data) => {
+ interceptType = data.injectionType || "DISABLED";
+ logWithPrefix("Injection type set to:", interceptType);
+ },
+ __CDM_DEVICES__: (data) => {
+ const { widevine_device, playready_device } = data;
logWithPrefix("Received device info:", widevine_device, playready_device);
-
widevineDeviceInfo = widevine_device;
playreadyDeviceInfo = playready_device;
- }
+ },
});
function safeHeaderShellEscape(str) {
--
2.43.0
From a40a6abaf76dea228c2aba8f9d2909b8910e6d9a Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 09:56:05 +0700
Subject: [PATCH 22/26] extract DRM PSSH detection and storage into a separate
function
---
src/inject.js | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 0dbedd9..652b2a9 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -556,23 +556,32 @@ function ensureRemoteCDM(type, deviceInfo, pssh) {
}
}
+function detectAndStorePssh(initData) {
+ const detections = [
+ {
+ type: "PlayReady",
+ getter: getPlayReadyPssh,
+ store: (pssh) => (foundPlayreadyPssh = pssh),
+ },
+ { type: "Widevine", getter: getWidevinePssh, store: (pssh) => (foundWidevinePssh = pssh) },
+ ];
+
+ detections.forEach(({ type, getter, store }) => {
+ const pssh = getter(initData);
+ if (pssh) {
+ logWithPrefix(`[DRM Detected] ${type}`);
+ store(pssh);
+ logWithPrefix(`[${type} PSSH found] ${pssh}`);
+ }
+ });
+}
+
// Challenge generator interceptor
const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
const session = this;
- let playReadyPssh = getPlayReadyPssh(initData);
- if (playReadyPssh) {
- logWithPrefix("[DRM Detected] PlayReady");
- foundPlayreadyPssh = playReadyPssh;
- logWithPrefix("[PlayReady PSSH found] " + playReadyPssh);
- }
- let wideVinePssh = getWidevinePssh(initData);
- if (wideVinePssh) {
- // Widevine code
- logWithPrefix("[DRM Detected] Widevine");
- foundWidevinePssh = wideVinePssh;
- logWithPrefix("[Widevine PSSH found] " + wideVinePssh);
- }
+ detectAndStorePssh(initData);
+
// Challenge message interceptor
if (!remoteListenerMounted) {
remoteListenerMounted = true;
--
2.43.0
From 8d4cd89a025382d3606c93c0da8239ae83564f25 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 10:04:17 +0700
Subject: [PATCH 23/26] consolidate DRM interception handling for fetch and XHR
requests
---
src/inject.js | 120 +++++++++++++++++++++++---------------------------
1 file changed, 56 insertions(+), 64 deletions(-)
diff --git a/src/inject.js b/src/inject.js
index 652b2a9..0793cd1 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -788,6 +788,37 @@ function handleLicenseMode({
}
}
+function handleDRMInterception(drmInfo, body, url, setBodyCallback, continueRequestCallback) {
+ // EME mode: block the request if a DRM challenge is detected
+ if (
+ drmInfo.type &&
+ (!remoteCDM || remoteCDM.challenge === null || drmInfo.base64 !== remoteCDM.challenge) &&
+ interceptType === "EME"
+ ) {
+ foundChallengeInBody = true;
+ window.postMessage({ type: "__LICENSE_URL__", data: url }, "*");
+ // Block the request
+ return { shouldBlock: true };
+ }
+
+ // LICENSE mode: replace the challenge in the request
+ if (drmInfo.type && interceptType === "LICENSE" && !foundChallengeInBody) {
+ handleLicenseMode({
+ drmInfo,
+ body,
+ setBody: setBodyCallback,
+ urlOrResource: url,
+ getWidevinePssh: () => foundWidevinePssh,
+ getPlayreadyPssh: () => foundPlayreadyPssh,
+ widevineDeviceInfo,
+ playreadyDeviceInfo,
+ });
+ return { shouldIntercept: true, result: continueRequestCallback() };
+ }
+
+ return { shouldContinue: true };
+}
+
// fetch POST interceptor
(function () {
const originalFetch = window.fetch;
@@ -795,42 +826,21 @@ function handleLicenseMode({
window.fetch = async function (resource, config = {}) {
const method = (config.method || "GET").toUpperCase();
- if (method === "POST") {
- let body = config.body;
- if (body) {
- const drmInfo = detectDRMChallenge(body);
+ if (method === "POST" && config.body) {
+ const drmInfo = detectDRMChallenge(config.body);
- // EME mode: block the request if a DRM challenge is detected
- if (
- drmInfo.type &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- drmInfo.base64 !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: resource }, "*");
- // Block the request
- return;
- }
+ const result = handleDRMInterception(
+ drmInfo,
+ config.body,
+ resource,
+ (b) => {
+ config.body = b;
+ },
+ () => originalFetch(resource, config)
+ );
- // LICENSE mode: replace the challenge in the request
- if (drmInfo.type && interceptType === "LICENSE" && !foundChallengeInBody) {
- handleLicenseMode({
- drmInfo,
- body,
- setBody: (b) => {
- config.body = b;
- },
- urlOrResource: resource,
- getWidevinePssh: () => foundWidevinePssh,
- getPlayreadyPssh: () => foundPlayreadyPssh,
- widevineDeviceInfo,
- playreadyDeviceInfo,
- });
- return originalFetch(resource, config);
- }
- }
+ if (result.shouldBlock) return;
+ if (result.shouldIntercept) return result.result;
}
return originalFetch(resource, config);
@@ -849,39 +859,21 @@ function handleLicenseMode({
};
XMLHttpRequest.prototype.send = function (body) {
- if (this._method && this._method.toUpperCase() === "POST") {
- if (body) {
- const drmInfo = detectDRMChallenge(body);
+ if (this._method && this._method.toUpperCase() === "POST" && body) {
+ const drmInfo = detectDRMChallenge(body);
- // EME mode: block the request if a DRM challenge is detected
- if (
- drmInfo.type &&
- (!remoteCDM ||
- remoteCDM.challenge === null ||
- drmInfo.base64 !== remoteCDM.challenge) &&
- interceptType === "EME"
- ) {
- foundChallengeInBody = true;
- window.postMessage({ type: "__LICENSE_URL__", data: this._url }, "*");
- // Block the request
- return;
- }
+ const result = handleDRMInterception(
+ drmInfo,
+ body,
+ this._url,
+ (b) => originalSend.call(this, b),
+ () => {} // XHR doesn't need continuation callback
+ );
- // LICENSE mode: replace the challenge in the request
- if (drmInfo.type && interceptType === "LICENSE" && !foundChallengeInBody) {
- return handleLicenseMode({
- drmInfo,
- body,
- setBody: (b) => originalSend.call(this, b),
- urlOrResource: this._url,
- getWidevinePssh: () => foundWidevinePssh,
- getPlayreadyPssh: () => foundPlayreadyPssh,
- widevineDeviceInfo,
- playreadyDeviceInfo,
- });
- }
- }
+ if (result.shouldBlock) return;
+ if (result.shouldIntercept) return result.result;
}
+
return originalSend.apply(this, arguments);
};
})();
--
2.43.0
From f40e1880d6ec45ac657fba0889f2bfb32d0aa4bd Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 10:13:17 +0700
Subject: [PATCH 24/26] add logging for POST request interception in DRM
handling
---
src/inject.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/inject.js b/src/inject.js
index 0793cd1..982c312 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -827,6 +827,7 @@ function handleDRMInterception(drmInfo, body, url, setBodyCallback, continueRequ
const method = (config.method || "GET").toUpperCase();
if (method === "POST" && config.body) {
+ logWithPrefix("[FETCH] Intercepting POST request to:", resource);
const drmInfo = detectDRMChallenge(config.body);
const result = handleDRMInterception(
@@ -860,6 +861,7 @@ function handleDRMInterception(drmInfo, body, url, setBodyCallback, continueRequ
XMLHttpRequest.prototype.send = function (body) {
if (this._method && this._method.toUpperCase() === "POST" && body) {
+ logWithPrefix("[XHR] Intercepting POST request to:", this._url);
const drmInfo = detectDRMChallenge(body);
const result = handleDRMInterception(
--
2.43.0
From 0b59c6b0d6090a5e54d3e840f9bbc09eb4da9109 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 10:28:25 +0700
Subject: [PATCH 25/26] feat: implement `resetDRMState` to clear state and
session on new manifest detection
---
src/inject.js | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/src/inject.js b/src/inject.js
index 982c312..a759d62 100644
--- a/src/inject.js
+++ b/src/inject.js
@@ -39,6 +39,47 @@ const logWithPrefix = (...args) => {
}
};
+function resetDRMState() {
+ logWithPrefix("Resetting DRM state for new manifest...");
+
+ // Reset DRM detection state
+ originalChallenge = null;
+ serviceCertFound = false;
+ drmType = "NONE";
+ psshFound = false;
+ foundWidevinePssh = null;
+ foundPlayreadyPssh = null;
+ drmDecided = null;
+
+ // Reset CDM and session state
+ if (remoteCDM) {
+ try {
+ // Try to close the existing session if it exists
+ if (remoteCDM.session_id) {
+ remoteCDM.closeSession();
+ }
+ } catch (e) {
+ // Ignore errors when closing session
+ logWithPrefix("Error closing previous CDM session:", e.message);
+ }
+ remoteCDM = null;
+ }
+
+ // Reset interceptor state
+ generateRequestCalled = false;
+ remoteListenerMounted = false;
+ injectionSuccess = false;
+ foundChallengeInBody = false;
+ licenseResponseCounter = 0;
+ keysRetrieved = false;
+
+ // Post reset messages to clear UI state
+ window.postMessage({ type: "__DRM_TYPE__", data: "" }, "*");
+ window.postMessage({ type: "__PSSH_DATA__", data: "" }, "*");
+ window.postMessage({ type: "__KEYS_DATA__", data: "" }, "*");
+ window.postMessage({ type: "__LICENSE_URL__", data: "" }, "*");
+}
+
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
window.postMessage({ type: "__GET_INJECTION_TYPE__" }, "*");
window.postMessage({ type: "__GET_CDM_DEVICES__" }, "*");
@@ -94,6 +135,9 @@ function headersToFlags(headersObj) {
}
function handleManifestDetection(url, headersObj, contentType, source) {
+ // Reset DRM state when new manifest is detected
+ resetDRMState();
+
window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
logWithPrefix(`[Manifest][${source}]`, url, contentType);
--
2.43.0
From ee9eeb30ea42661f89a7c194c4cec932cd1de024 Mon Sep 17 00:00:00 2001
From: voldemort <5692900+yell0wsuit@users.noreply.github.com>
Date: Tue, 22 Jul 2025 10:55:02 +0700
Subject: [PATCH 26/26] feat: add js minification during file copy in build
process
---
README.md | 1 +
buildext.js | 57 ++++++++++++++++++-
package-lock.json | 136 ++++++++++++++++++++++++++++++++++++++++++++++
package.json | 3 +
4 files changed, 194 insertions(+), 3 deletions(-)
create mode 100644 package-lock.json
diff --git a/README.md b/README.md
index 4cb2211..48c514f 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ To update the version across the entire project, simply change the version numbe
- Run the build script:
```bash
+npm install
npm run buildext
```
diff --git a/buildext.js b/buildext.js
index 632d6fb..c6b7bcb 100644
--- a/buildext.js
+++ b/buildext.js
@@ -1,6 +1,7 @@
import { execSync } from "child_process";
import fs from "fs";
import path from "path";
+import { minify } from "terser";
import url from "url";
import syncVersion from "./syncVersion.js";
@@ -25,6 +26,56 @@ const copyDir = async (src, dest) => {
});
};
+const minifyJS = async (jsContent) => {
+ try {
+ const result = await minify(jsContent, {
+ compress: {
+ drop_console: false, // Keep console logs for debugging
+ drop_debugger: true,
+ pure_funcs: ["console.debug"],
+ },
+ mangle: {
+ reserved: ["chrome"], // Don't mangle chrome API
+ },
+ });
+ return result.code;
+ } catch (error) {
+ console.warn("⚠️ Minification failed, using original:", error.message);
+ return jsContent;
+ }
+};
+
+// Copy and minify JavaScript files from src directory
+const copyAndMinifySrcFiles = async (src, dest) => {
+ await fs.promises.mkdir(dest, { recursive: true });
+
+ const entries = await fs.promises.readdir(src, { withFileTypes: true });
+
+ for (const entry of entries) {
+ const srcPath = path.join(src, entry.name);
+ const destPath = path.join(dest, entry.name);
+
+ if (entry.isDirectory()) {
+ await copyAndMinifySrcFiles(srcPath, destPath);
+ } else if (entry.name.endsWith(".js")) {
+ // Minify JavaScript files
+ console.log(`🗜️ Minifying ${entry.name}...`);
+ const content = await fs.promises.readFile(srcPath, "utf8");
+ const originalSize = Buffer.byteLength(content, "utf8");
+ const minified = await minifyJS(content, entry.name);
+ const minifiedSize = Buffer.byteLength(minified, "utf8");
+ const savings = (((originalSize - minifiedSize) / originalSize) * 100).toFixed(1);
+ console.log(
+ ` 📊 ${entry.name}: ${originalSize} → ${minifiedSize} bytes (${savings}% smaller)`
+ );
+ await fs.promises.writeFile(destPath, minified, "utf8");
+ } else {
+ // Copy other files as-is
+ await fs.promises.copyFile(srcPath, destPath);
+ }
+ }
+};
+
const main = async () => {
await syncVersion();
@@ -47,9 +98,9 @@ const main = async () => {
}
await fs.promises.mkdir(releaseDir);
- // 4. Copy src files (manifest, background, etc) to release
- console.log("📦 Copying src files to extension-release...");
- await copyDir(srcDir, releaseDir);
+ // 4. Copy and minify src files
+ console.log("📦 Copying and minifying src files...");
+ await copyAndMinifySrcFiles(srcDir, releaseDir);
// 5. Copy frontend dist files to release (merged at root)
console.log("📦 Copying frontend dist files to extension-release...");
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..df2901f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,136 @@
+{
+ "name": "cdrm-extension",
+ "version": "2.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "cdrm-extension",
+ "version": "2.1.0",
+ "license": "ISC",
+ "devDependencies": {
+ "terser": "^5.43.1"
+ },
+ "engines": {
+ "node": ">=21.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz",
+ "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
+ "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.29",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.43.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
+ "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.14.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 2372915..2288e3a 100644
--- a/package.json
+++ b/package.json
@@ -17,5 +17,8 @@
"type": "module",
"engines": {
"node": ">=21.0.0"
+ },
+ "devDependencies": {
+ "terser": "^5.43.1"
}
}
--
2.43.0