diff options
-rw-r--r-- | README.md | 49 | ||||
-rw-r--r-- | assets/images/logo-off.png | bin | 0 -> 8466 bytes | |||
-rw-r--r-- | assets/images/logo-off_48.png | bin | 0 -> 1324 bytes | |||
-rw-r--r-- | assets/images/logo-off_96.png | bin | 0 -> 2554 bytes | |||
-rw-r--r-- | assets/images/logo.png | bin | 168763 -> 21411 bytes | |||
-rw-r--r-- | assets/images/logo_48.png | bin | 4984 -> 3054 bytes | |||
-rw-r--r-- | assets/images/logo_96.png | bin | 13741 -> 6333 bytes | |||
-rw-r--r-- | background.js | 846 | ||||
-rw-r--r-- | content-script.js | 85 | ||||
-rw-r--r-- | data-viewer/data-viewer.css | 234 | ||||
-rw-r--r-- | data-viewer/data-viewer.html | 116 | ||||
-rw-r--r-- | data-viewer/data-viewer.js | 605 | ||||
-rw-r--r-- | logo.psd | bin | 0 -> 621307 bytes | |||
-rw-r--r-- | manifest.json | 12 | ||||
-rw-r--r-- | package-lock.json | 4626 | ||||
-rw-r--r-- | package.json | 17 | ||||
-rw-r--r-- | popup/popup.css | 104 | ||||
-rw-r--r-- | popup/popup.html | 105 | ||||
-rw-r--r-- | popup/popup.js | 346 | ||||
-rw-r--r-- | shared/constants.js | 1 | ||||
-rw-r--r-- | shared/defaults.js | 34 | ||||
-rw-r--r-- | styling/README.md | 4 | ||||
-rw-r--r-- | web-ext-config.mjs | 19 |
23 files changed, 2089 insertions, 5114 deletions
@@ -1,47 +1,22 @@ -# Transparent Zen
+# Zen internet
-Transparent Zen is a browser extension specifically designed for Zen Browser. This extension injects styles into supported websites to make them transparent, providing a new experience.
+A prettier Internet in Zen and Firefox.
+
+> Since I need to focus some time on work and on my fyp, I might throttle the development and do any updates only if bugs arise. But will try to continue adding themes whenever I am chill :)
<a href="https://addons.mozilla.org/en-US/firefox/addon/zen-internet/">
<img alt="Firefox Add-Ons" src="https://blog.mozilla.org/addons/files/2015/11/get-the-addon.png" height="40">
</a>
<br>
-<img width="379" alt="image" src="https://github.com/user-attachments/assets/18134c23-6a8a-4598-987d-9fdfa29b09b2" />
-
-https://github.com/user-attachments/assets/03ce72fc-e5b0-48fc-b0ae-40c6671b187d
-
-## Supported Websites
-Checkout the [repository](https://github.com/sameerasw/my-internet) for website css styling which are used in this addon.
-
-### Unsupported websites now can be forced!
-
-https://github.com/user-attachments/assets/85f795cc-049f-4338-a74b-8f5d2a9eb5bd
-
-
-#### To Do
-- [x] Feature specific toggles for each website
-- [ ] Custom css by user
+
-## Prerequisites
-#### Transparent Zen
-- [Guide](https://sameerasw.notion.site/Zen-Transparency-1939c6099d4080468f02cf05ae50e827?pvs=4)
+
-## Installation
+<img width="1305" alt="image" src="https://github.com/user-attachments/assets/3086e330-df6e-4164-b4cd-ae102ebe7a4f" />
-To install the addon, you can either download it from the [Firefox Add-Ons Store](https://addons.mozilla.org/en-US/firefox/addon/zen-internet) or grab the latest release from github and manually install it through the Zen Browser settings.
-
-## Usage
-
-Once installed, Open the addon dialog, enable theming and click the refetch latest styles button to load the latest stylesheets from the repository
-
-<img width="334" alt="CleanShot 2025-02-25 at 11 19 49@2x" src="https://github.com/user-attachments/assets/573519aa-10de-4606-8c9f-30a21661bcf4" />
-
-Then reload the page and enjoy :D
-You can disable website specific theming from the pop-up.
-
-<img width="367" alt="CleanShot 2025-02-25 at 11 20 55@2x" src="https://github.com/user-attachments/assets/05645e1e-e83a-4f54-8895-6ea1744e9711" />
+## [Guide](https://www.sameerasw.com/zen)
If you would like to contribute to the addon, please follow these steps:
@@ -50,10 +25,10 @@ If you would like to contribute to the addon, please follow these steps: 3. Make your changes and commit them with a descriptive message.
4. Push your changes to your fork and create a pull request.
- > Thanks to [@YelehaUwU](https://github.com/YelehaUwU) for the contributions on the pop-up UI!
-
+Thanks:
+- to [@YelehaUwU](https://github.com/YelehaUwU) for the contributions on the pop-up UI!
+- to the [Transparent Zen ](https://github.com/frostybiscuit/transparent-zen) for the addon base and the inspiration <3
+
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
-
-Enjoy :D Huge thanks to the [Transparent Zen ](https://github.com/frostybiscuit/transparent-zen) for the addon base and the inspiration <3
diff --git a/assets/images/logo-off.png b/assets/images/logo-off.png Binary files differnew file mode 100644 index 0000000..3ee5eda --- /dev/null +++ b/assets/images/logo-off.png diff --git a/assets/images/logo-off_48.png b/assets/images/logo-off_48.png Binary files differnew file mode 100644 index 0000000..d502afc --- /dev/null +++ b/assets/images/logo-off_48.png diff --git a/assets/images/logo-off_96.png b/assets/images/logo-off_96.png Binary files differnew file mode 100644 index 0000000..095a910 --- /dev/null +++ b/assets/images/logo-off_96.png diff --git a/assets/images/logo.png b/assets/images/logo.png Binary files differindex 1e56728..ad65e4f 100644 --- a/assets/images/logo.png +++ b/assets/images/logo.png diff --git a/assets/images/logo_48.png b/assets/images/logo_48.png Binary files differindex d083002..44a945f 100644 --- a/assets/images/logo_48.png +++ b/assets/images/logo_48.png diff --git a/assets/images/logo_96.png b/assets/images/logo_96.png Binary files differindex 9b402a6..d71f36c 100644 --- a/assets/images/logo_96.png +++ b/assets/images/logo_96.png diff --git a/background.js b/background.js index bc30678..3e809ff 100644 --- a/background.js +++ b/background.js @@ -1,23 +1,316 @@ let SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; +let SKIP_THEMING_KEY = "skipThemingList"; +let FALLBACK_BACKGROUND_KEY = "fallbackBackgroundList"; +let BROWSER_STORAGE_KEY = "transparentZenSettings"; let logging = true; // Enable logging for debugging // Create a cache for pre-processed CSS to speed up repeated visits const cssCache = new Map(); const activeTabs = new Map(); +// Cache for styling state to avoid repeated storage lookups +const stylingStateCache = new Map(); + +// Icon states for the browser action +const ICON_ON = { + 48: "assets/images/logo_48.png", + 96: "assets/images/logo_96.png", +}; +const ICON_OFF = { + 48: "assets/images/logo-off_48.png", + 96: "assets/images/logo-off_96.png", +}; + +// Default settings to use when values are missing +const DEFAULT_SETTINGS = { + enableStyling: true, // Enable styling globally + autoUpdate: true, // Auto-update styles + forceStyling: false, // Force styling on sites without themes + whitelistMode: false, // Use blacklist mode by default for force styling + whitelistStyleMode: false, // Use blacklist mode by default for regular styling + disableTransparency: false, // Don't disable transparency by default + disableHover: false, // Don't disable hover effects by default + disableFooter: false, // Don't disable footers by default + fallbackBackgroundList: [], // Empty array for fallback background sites +}; // Helper function to normalize hostnames by removing www. prefix function normalizeHostname(hostname) { return hostname.startsWith("www.") ? hostname.substring(4) : hostname; } +// Ensure all required settings exist +function ensureDefaultSettings(settings = {}) { + const result = { ...settings }; + + // Apply default values for any missing settings + for (const [key, defaultValue] of Object.entries(DEFAULT_SETTINGS)) { + if (result[key] === undefined) { + result[key] = defaultValue; + } + } + + return result; +} + +// Enhanced function to determine styling state with more detailed information +async function shouldApplyStyling(hostname) { + try { + // Check if we already have the answer cached + const cacheKey = `styling:${hostname}`; + if (stylingStateCache.has(cacheKey)) { + return stylingStateCache.get(cacheKey); + } + + const normalizedHostname = normalizeHostname(hostname); + + // Get global settings - this is an unavoidable storage lookup + const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const settings = ensureDefaultSettings( + settingsData[BROWSER_STORAGE_KEY] || {} + ); + + // If styling is globally disabled, return detailed state + if (!settings.enableStyling) { + const result = { + shouldApply: false, + reason: "globally_disabled", + shouldApplyMinimal: true, // Still apply background when globally disabled + }; + stylingStateCache.set(cacheKey, result); + return result; + } + + // Check if we have a specific style for this site + let hasSpecificStyle = false; + + // Check for exact match first + if ( + cssCache.has(normalizedHostname) || + cssCache.has(`www.${normalizedHostname}`) + ) { + hasSpecificStyle = true; + } else { + // Check for wildcard and TLD matches + for (const cachedSite of cssCache.keys()) { + // Wildcard match + if (cachedSite.startsWith("+")) { + const baseSite = cachedSite.slice(1); + if ( + normalizedHostname === baseSite || + normalizedHostname.endsWith(`.${baseSite}`) + ) { + hasSpecificStyle = true; + break; + } + } + // TLD suffix match + else if (cachedSite.startsWith("-")) { + const baseSite = cachedSite.slice(1); + const cachedDomain = baseSite.split(".").slice(0, -1).join("."); + const hostParts = normalizedHostname.split("."); + const hostDomain = + hostParts.length > 1 + ? hostParts.slice(0, -1).join(".") + : normalizedHostname; + + if (cachedDomain && hostDomain && hostDomain === cachedDomain) { + hasSpecificStyle = true; + break; + } + } + // Subdomain match + else if ( + normalizedHostname !== cachedSite && + normalizedHostname.endsWith(`.${cachedSite}`) && + !cachedSite.startsWith("-") + ) { + hasSpecificStyle = true; + break; + } + } + } + + // If we have a specific style, check blacklist/whitelist for regular styling + if (hasSpecificStyle) { + // Get skip styling list - only do this lookup if we have a specific style + const skipStyleListData = await browser.storage.local.get( + SKIP_THEMING_KEY + ); + const skipStyleList = skipStyleListData[SKIP_THEMING_KEY] || []; + + // In whitelist mode: only apply if site is in the list + // In blacklist mode: apply unless site is in the list + const styleMode = settings.whitelistStyleMode || false; + + if (styleMode) { + // Whitelist mode + const shouldApply = skipStyleList.includes(normalizedHostname); + const result = { + shouldApply, + reason: shouldApply ? "whitelisted" : "not_whitelisted", + shouldApplyMinimal: !shouldApply, // Apply minimal when not whitelisted + }; + stylingStateCache.set(cacheKey, result); + return result; + } else { + // Blacklist mode + const shouldApply = !skipStyleList.includes(normalizedHostname); + const result = { + shouldApply, + reason: shouldApply ? "not_blacklisted" : "blacklisted", + shouldApplyMinimal: !shouldApply, // Apply minimal when blacklisted + }; + stylingStateCache.set(cacheKey, result); + return result; + } + } + + // If no specific style, check if we should apply forced styling + if (settings.forceStyling) { + // Get skip force list - only do this lookup if force styling is enabled + const skipForceListData = await browser.storage.local.get( + SKIP_FORCE_THEMING_KEY + ); + const skipForceList = skipForceListData[SKIP_FORCE_THEMING_KEY] || []; + const isWhitelistMode = settings.whitelistMode || false; + + // In whitelist mode: only apply if site is in the list + // In blacklist mode: apply unless site is in the list + if (isWhitelistMode) { + const shouldApply = skipForceList.includes(normalizedHostname); + const result = { + shouldApply, + reason: shouldApply ? "force_whitelisted" : "force_not_whitelisted", + shouldApplyMinimal: !shouldApply, // Apply minimal when force not whitelisted + }; + stylingStateCache.set(cacheKey, result); + return result; + } else { + const shouldApply = !skipForceList.includes(normalizedHostname); + const result = { + shouldApply, + reason: shouldApply ? "force_not_blacklisted" : "force_blacklisted", + shouldApplyMinimal: !shouldApply, // Apply minimal when force blacklisted + }; + stylingStateCache.set(cacheKey, result); + return result; + } + } + + // No styling applies + const result = { + shouldApply: false, + reason: "no_styling_rules", + shouldApplyMinimal: false, + }; + stylingStateCache.set(cacheKey, result); + return result; + } catch (error) { + console.error("Error determining styling state:", error); + return { shouldApply: false, reason: "error", shouldApplyMinimal: false }; + } +} + +// New function to apply minimal styling (just background color) +async function applyMinimalCSS(tabId, hostname) { + console.log( + "DEBUG: applyMinimalCSS called for tab", + tabId, + "hostname", + hostname + ); + + const backgroundCSS = ` +/* ZenInternet: Minimal styling - background color when main styling is disabled/skipped */ +body { + background-color: light-dark(#fff, #111) !important; +} +`; + + try { + // Try to send via messaging first + console.log(`DEBUG: Sending minimal styles to tab ${tabId} via messaging`); + await browser.tabs.sendMessage(tabId, { + action: "applyStyles", + css: backgroundCSS, + }); + } catch (e) { + // Fallback to insertCSS if messaging fails + console.log( + `DEBUG: Messaging failed, falling back to insertCSS: ${e.message}` + ); + await browser.tabs.insertCSS(tabId, { + code: backgroundCSS, + runAt: "document_start", + }); + } + + console.log(`DEBUG: Successfully applied minimal CSS for ${hostname}`); +} + +// Update the icon based on whether styling is active for the current tab +async function updateIconForTab(tabId, url) { + try { + if (!url) { + const tab = await browser.tabs.get(tabId); + url = tab.url; + } + + // Non-HTTP URLs don't get styling + if (!url || !url.startsWith("http")) { + setIcon(tabId, false); + return; + } + + const urlObj = new URL(url); + const hostname = urlObj.hostname; + + // Determine styling state using the enhanced function + const stylingState = await shouldApplyStyling(hostname); + + // Update the icon based on whether full styling is enabled for this site + setIcon(tabId, stylingState.shouldApply); + + if (logging) + console.log( + `Icon updated for ${hostname}: styling ${ + stylingState.shouldApply ? "ON" : "OFF" + } (${stylingState.reason})` + ); + } catch (error) { + console.error("Error updating icon:", error); + setIcon(tabId, false); + } +} + +// Set the icon to either on or off state +function setIcon(tabId, isEnabled) { + const iconSet = isEnabled ? ICON_ON : ICON_OFF; + browser.browserAction.setIcon({ + path: iconSet, + tabId: tabId, + }); +} + // Preload styles for faster injection async function preloadStyles() { try { const data = await browser.storage.local.get([ "styles", - "transparentZenSettings", + BROWSER_STORAGE_KEY, ]); - const settings = data.transparentZenSettings || {}; + + // Ensure we have all required settings with defaults + const settings = ensureDefaultSettings(data[BROWSER_STORAGE_KEY] || {}); + + // Save the validated settings back to storage if any defaults were applied + if ( + JSON.stringify(settings) !== JSON.stringify(data[BROWSER_STORAGE_KEY]) + ) { + if (logging) + console.log("Missing settings detected, applying defaults:", settings); + await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); + } // No point in preloading if styling is disabled if (settings.enableStyling === false) return; @@ -52,6 +345,9 @@ browser.webNavigation.onBeforeNavigate.addListener((details) => { const url = new URL(details.url); const normalizedHostname = normalizeHostname(url.hostname); prepareStylesForUrl(normalizedHostname, details.tabId); + + // Update icon for this tab + updateIconForTab(details.tabId, details.url); } }); @@ -63,10 +359,10 @@ browser.runtime.onMessage.addListener(async (message, sender) => { const normalizedHostname = normalizeHostname(message.hostname); // Get settings to check if styling is enabled - const settingsData = await browser.storage.local.get( - "transparentZenSettings" + const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const settings = ensureDefaultSettings( + settingsData[BROWSER_STORAGE_KEY] || {} ); - const settings = settingsData.transparentZenSettings || {}; if (settings.enableStyling === false) return; @@ -94,11 +390,19 @@ browser.runtime.onMessage.addListener(async (message, sender) => { return true; } + // Update the icon when the content script reports ready + if (message.action === "contentScriptReady" && sender.tab) { + updateIconForTab(sender.tab.id, sender.tab.url); + } + return false; }); // Get appropriate styles for a hostname based on all rules async function getStylesForHostname(hostname, settings) { + // Ensure all required settings have defaults before proceeding + settings = ensureDefaultSettings(settings); + console.log("DEBUG: Finding styles for hostname:", hostname); // Check for exact matches first (highest priority) @@ -191,10 +495,12 @@ async function getStylesForHostname(hostname, settings) { // Prepare styles for a URL that's about to load async function prepareStylesForUrl(hostname, tabId) { try { - const settingsData = await browser.storage.local.get( - "transparentZenSettings" + const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY); + + // Ensure all required settings have defaults + const settings = ensureDefaultSettings( + settingsData[BROWSER_STORAGE_KEY] || {} ); - const settings = settingsData.transparentZenSettings || {}; if (settings.enableStyling === false) return; @@ -227,171 +533,154 @@ async function applyCSSToTab(tab) { ")" ); - const settings = await browser.storage.local.get("transparentZenSettings"); - const globalSettings = settings.transparentZenSettings || {}; - console.log("DEBUG: Global settings:", JSON.stringify(globalSettings)); + // Use the enhanced shouldApplyStyling function + const stylingState = await shouldApplyStyling(hostname); + console.log("DEBUG: Styling state:", stylingState); - if (globalSettings.enableStyling === false) { - console.log("DEBUG: Styling is globally disabled, exiting early"); - return; - } - - const data = await browser.storage.local.get("styles"); - console.log( - "DEBUG: Loaded styles count:", - Object.keys(data.styles?.website || {}).length - ); + // Update icon based on whether full styling is applied + setIcon(tab.id, stylingState.shouldApply); - const skipListData = await browser.storage.local.get( - SKIP_FORCE_THEMING_KEY - ); - const siteList = skipListData[SKIP_FORCE_THEMING_KEY] || []; - console.log("DEBUG: Skip/Whitelist contains", siteList.length, "sites"); - console.log("DEBUG: Current site in list:", siteList.includes(hostname)); - - const isWhitelistMode = globalSettings.whitelistMode || false; - console.log("DEBUG: Using whitelist mode:", isWhitelistMode); - - // Find the best matching CSS file - let bestMatch = null; - let bestMatchLength = 0; - let matchType = "none"; - - for (const key of Object.keys(data.styles?.website || {})) { - const siteName = key.replace(".css", ""); - - // For site names in the styles list, also normalize by removing www. if present - const normalizedSiteName = normalizeHostname(siteName); - - // Exact match has highest priority - compare normalized hostnames - if (hostname === normalizedSiteName) { - bestMatch = key; - matchType = "exact"; - console.log("DEBUG: Found exact match:", key); - break; - } + // If full styling should be applied, proceed with normal CSS application + if (stylingState.shouldApply) { + const settings = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const globalSettings = ensureDefaultSettings( + settings[BROWSER_STORAGE_KEY] || {} + ); - // Then check wildcard matches - if (siteName.startsWith("+")) { - const baseSite = siteName.slice(1); - // Ensure we're matching with proper domain boundary - if ( - (hostname === baseSite || hostname.endsWith(`.${baseSite}`)) && - baseSite.length > bestMatchLength - ) { - bestMatch = key; - bestMatchLength = baseSite.length; - matchType = "wildcard"; - console.log( - "DEBUG: Found wildcard match:", - key, - "with length", - baseSite.length - ); - } - } - // Check TLD suffix matches (-domain.com) - fixed implementation - else if (siteName.startsWith("-")) { - const baseSite = siteName.slice(1); + const data = await browser.storage.local.get("styles"); + console.log( + "DEBUG: Loaded styles count:", + Object.keys(data.styles?.website || {}).length + ); - // Extract domain name without the TLD - // For cached site: Use everything before the last dot(s) - const cachedDomain = baseSite.split(".").slice(0, -1).join("."); + // Find the best matching CSS file + let bestMatch = null; + let bestMatchLength = 0; + let matchType = "none"; - // For hostname: Similarly extract the domain without the TLD - const hostParts = hostname.split("."); - const hostDomain = - hostParts.length > 1 ? hostParts.slice(0, -1).join(".") : hostname; + for (const key of Object.keys(data.styles?.website || {})) { + const siteName = key.replace(".css", ""); + const normalizedSiteName = normalizeHostname(siteName); - console.log( - `DEBUG: Comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` - ); + // Exact match has highest priority - compare normalized hostnames + if (hostname === normalizedSiteName) { + bestMatch = key; + matchType = "exact"; + console.log("DEBUG: Found exact match:", key); + break; + } - // Match if the domain part (without TLD) matches - if (cachedDomain && hostDomain && hostDomain === cachedDomain) { - // Only update if it's a better match (longer domain name part) - if (cachedDomain.length > bestMatchLength) { + // Then check wildcard matches + if (siteName.startsWith("+")) { + const baseSite = siteName.slice(1); + // Ensure we're matching with proper domain boundary + if ( + (hostname === baseSite || hostname.endsWith(`.${baseSite}`)) && + baseSite.length > bestMatchLength + ) { bestMatch = key; - bestMatchLength = cachedDomain.length; - matchType = "suffix"; + bestMatchLength = baseSite.length; + matchType = "wildcard"; console.log( - "DEBUG: Found TLD suffix match:", + "DEBUG: Found wildcard match:", key, - "for", - hostname, - "with domain part:", - cachedDomain + "with length", + baseSite.length ); } } + // Check TLD suffix matches (-domain.com) - fixed implementation + else if (siteName.startsWith("-")) { + const baseSite = siteName.slice(1); + + // Extract domain name without the TLD + // For cached site: Use everything before the last dot(s) + const cachedDomain = baseSite.split(".").slice(0, -1).join("."); + + // For hostname: Similarly extract the domain without the TLD + const hostParts = hostname.split("."); + const hostDomain = + hostParts.length > 1 ? hostParts.slice(0, -1).join(".") : hostname; + + console.log( + `DEBUG: Comparing domains - cached: ${cachedDomain}, host: ${hostDomain}` + ); + + // Match if the domain part (without TLD) matches + if (cachedDomain && hostDomain && hostDomain === cachedDomain) { + // Only update if it's a better match (longer domain name part) + if (cachedDomain.length > bestMatchLength) { + bestMatch = key; + bestMatchLength = cachedDomain.length; + matchType = "suffix"; + console.log( + "DEBUG: Found TLD suffix match:", + key, + "for", + hostname, + "with domain part:", + cachedDomain + ); + } + } + } + // Last, check subdomain matches with proper domain boundary + else if ( + hostname !== normalizedSiteName && + hostname.endsWith(`.${normalizedSiteName}`) && + !siteName.startsWith("-") && + normalizedSiteName.length > bestMatchLength + ) { + bestMatch = key; + bestMatchLength = normalizedSiteName.length; + matchType = "subdomain"; + console.log( + "DEBUG: Found domain suffix match:", + key, + "with length", + normalizedSiteName.length + ); + } } - // Last, check subdomain matches with proper domain boundary - else if ( - hostname !== normalizedSiteName && - hostname.endsWith(`.${normalizedSiteName}`) && - !siteName.startsWith("-") && - normalizedSiteName.length > bestMatchLength + + // If we found a direct match, use it + if (bestMatch) { + console.log("DEBUG: Using match:", bestMatch, "of type:", matchType); + await applyCSS(tab.id, hostname, data.styles.website[bestMatch]); + return; + } else if ( + globalSettings.forceStyling && + data.styles.website["example.com.css"] ) { - bestMatch = key; - bestMatchLength = normalizedSiteName.length; - matchType = "subdomain"; - console.log( - "DEBUG: Found domain suffix match:", - key, - "with length", - normalizedSiteName.length + console.log("DEBUG: Applying forced styling with example.com.css"); + await applyCSS( + tab.id, + hostname, + data.styles.website["example.com.css"] ); + return; } } - // If we found a direct match, use it - if (bestMatch) { - console.log("DEBUG: Using match:", bestMatch, "of type:", matchType); - await applyCSS(tab.id, hostname, data.styles.website[bestMatch]); - return; - } else { - console.log("DEBUG: No direct style match found for:", hostname); - } - - // Otherwise, check if we should apply forced styling - console.log("DEBUG: Force styling enabled:", globalSettings.forceStyling); - if (globalSettings.forceStyling) { - const siteInList = siteList.includes(hostname); - console.log("DEBUG: Site in list:", siteInList); - - // In whitelist mode: apply only if site is in the list - // In blacklist mode: apply only if site is NOT in the list - const shouldApplyForcedStyling = - (isWhitelistMode && siteInList) || (!isWhitelistMode && !siteInList); + // If full styling is not applied but minimal styling should be applied + if (!stylingState.shouldApply && stylingState.shouldApplyMinimal) { console.log( - "DEBUG: Should apply forced styling:", - shouldApplyForcedStyling, - "(Whitelist mode:", - isWhitelistMode, - ", Site in list:", - siteInList, - ")" + "DEBUG: Applying minimal styling due to:", + stylingState.reason ); - - if (shouldApplyForcedStyling) { - if (data.styles.website["example.com.css"]) { - console.log("DEBUG: Applying forced styling with example.com.css"); - await applyCSS( - tab.id, - hostname, - data.styles.website["example.com.css"] - ); - } else { - console.log("DEBUG: example.com.css not found in styles"); - } - } else { - console.log("DEBUG: Skipping forced styling due to site list rules"); - } - } else { - console.log("DEBUG: Force styling is disabled, no styles applied"); + await applyMinimalCSS(tab.id, hostname); + return; } + + console.log( + "DEBUG: No styling applied for:", + hostname, + "Reason:", + stylingState.reason + ); } catch (error) { console.error(`DEBUG ERROR: Error applying CSS:`, error); + setIcon(tab.id, false); } } @@ -405,17 +694,26 @@ async function applyCSS(tabId, hostname, features) { console.log("DEBUG: Features count:", Object.keys(features).length); - const settingsData = await browser.storage.local.get( - "transparentZenSettings" + const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY); + + // Ensure defaults for any missing settings + const globalSettings = ensureDefaultSettings( + settingsData[BROWSER_STORAGE_KEY] || {} ); - const globalSettings = settingsData.transparentZenSettings || {}; + console.log( "DEBUG: Global settings in applyCSS:", JSON.stringify(globalSettings) ); - // UPDATED: Use normalized hostname for consistent settings retrieval + // Check if this site is in the fallback background list + const fallbackData = await browser.storage.local.get(FALLBACK_BACKGROUND_KEY); + const fallbackBackgroundList = fallbackData[FALLBACK_BACKGROUND_KEY] || []; const normalizedHostname = normalizeHostname(hostname); + const hasFallbackBackground = + fallbackBackgroundList.includes(normalizedHostname); + + // UPDATED: Use normalized hostname for consistent settings retrieval const siteKey = `transparentZenSettings.${normalizedHostname}`; const siteData = await browser.storage.local.get(siteKey); const featureSettings = siteData[siteKey] || {}; @@ -429,40 +727,120 @@ async function applyCSS(tabId, hostname, features) { let combinedCSS = ""; let includedFeatures = 0; let skippedTransparencyFeatures = 0; + let skippedHoverFeatures = 0; + let skippedFooterFeatures = 0; let skippedDisabledFeatures = 0; + let hasTransparencyFeature = false; + let transparencyDisabled = false; for (const [feature, css] of Object.entries(features)) { const isTransparencyFeature = feature .toLowerCase() .includes("transparency"); - // Skip any transparency feature if disableTransparency is enabled globally - if (globalSettings.disableTransparency && isTransparencyFeature) { - console.log(`DEBUG: Skipping transparency feature: ${feature}`); + const isHoverFeature = feature.toLowerCase().includes("hover"); + const isFooterFeature = feature.toLowerCase().includes("footer"); + + // Track if this site has transparency features + if (isTransparencyFeature) { + hasTransparencyFeature = true; + } + + // Skip transparency if globally disabled OR if this site has fallback background enabled + if ( + isTransparencyFeature && + (globalSettings.disableTransparency || hasFallbackBackground) + ) { + console.log( + `DEBUG: Skipping transparency feature ${feature} (${ + hasFallbackBackground + ? "fallback background enabled" + : "globally disabled" + })` + ); skippedTransparencyFeatures++; + transparencyDisabled = true; continue; } - const isFeatureEnabled = featureSettings[feature] !== false; - if (isFeatureEnabled) { - combinedCSS += css + "\n"; - includedFeatures++; - console.log(`DEBUG: Including feature: ${feature}`); - } else { - console.log(`DEBUG: Feature disabled in site settings: ${feature}`); + // Skip any hover feature if disableHover is enabled globally + if (isHoverFeature && globalSettings.disableHover) { + console.log( + `DEBUG: Skipping hover feature ${feature} (globally disabled)` + ); + skippedHoverFeatures++; + continue; + } + + // Skip any footer feature if disableFooter is enabled globally + if (isFooterFeature && globalSettings.disableFooter) { + console.log( + `DEBUG: Skipping footer feature ${feature} (globally disabled)` + ); + skippedFooterFeatures++; + continue; + } + + // Check if this specific feature is disabled by site settings + if (featureSettings[feature] === false) { + console.log( + `DEBUG: Skipping feature ${feature} (disabled by site settings)` + ); skippedDisabledFeatures++; + // Check if this is a transparency feature being disabled at site level + if (isTransparencyFeature) { + transparencyDisabled = true; + } + continue; } + + // Include this feature's CSS + combinedCSS += css + "\n"; + includedFeatures++; + console.log(`DEBUG: Including feature: ${feature}`); } - console.log( - `DEBUG: CSS Summary - included: ${includedFeatures}, skipped transparency: ${skippedTransparencyFeatures}, skipped disabled: ${skippedDisabledFeatures}` - ); + // If transparency is disabled (globally, by fallback background, or at site level) + // and this site has transparency features, add minimal background CSS + if (transparencyDisabled && hasTransparencyFeature) { + console.log( + "DEBUG: Adding minimal background CSS due to disabled transparency" + ); + const minimalBackgroundCSS = ` +/* ZenInternet: Minimal background when transparency is disabled */ +html { + background-color: light-dark(#fff, #111); +} +`; + combinedCSS += minimalBackgroundCSS; + } - if (combinedCSS) { + // If fallback background is enabled for this site, always add the fallback CSS + if (hasFallbackBackground) { + console.log("DEBUG: Adding fallback background CSS for this site"); + const fallbackBackgroundCSS = ` +/* ZenInternet: Fallback background for this site */ +html{ + background-color: light-dark(#fff, #111); +} +`; + combinedCSS += fallbackBackgroundCSS; + } + + console.log(`DEBUG: CSS application summary: + - Included features: ${includedFeatures} + - Skipped transparency (global): ${skippedTransparencyFeatures} + - Skipped hover (global): ${skippedHoverFeatures} + - Skipped footer (global): ${skippedFooterFeatures} + - Skipped (site disabled): ${skippedDisabledFeatures} + - Has transparency feature: ${hasTransparencyFeature} + - Transparency disabled: ${transparencyDisabled} + - Has fallback background: ${hasFallbackBackground} + - Final CSS length: ${combinedCSS.length} characters`); + + if (combinedCSS.trim()) { try { - // Try to send via messaging (most reliable for instant application) - console.log( - `DEBUG: Sending styles to tab ${tabId} via messaging (${combinedCSS.length} bytes)` - ); + // Try to send via messaging first + console.log(`DEBUG: Sending styles to tab ${tabId} via messaging`); await browser.tabs.sendMessage(tabId, { action: "applyStyles", css: combinedCSS, @@ -477,12 +855,42 @@ async function applyCSS(tabId, hostname, features) { runAt: "document_start", }); } - console.log(`DEBUG: Successfully injected custom CSS for ${hostname}`); + + console.log(`DEBUG: Successfully applied CSS for ${hostname}`); } else { - console.log(`DEBUG: No CSS to inject after filtering features`); + console.log(`DEBUG: No CSS to apply for ${hostname}`); } } +// Also update icons when tabs are updated +browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (changeInfo.status === "complete") { + updateIconForTab(tabId, tab.url); + } +}); + +// Update the icon when a tab becomes active +browser.tabs.onActivated.addListener((activeInfo) => { + updateIconForTab(activeInfo.tabId); +}); + +// Clear cache on settings changes +browser.storage.onChanged.addListener((changes, areaName) => { + if (areaName === "local") { + if ( + changes[BROWSER_STORAGE_KEY] || + changes[SKIP_THEMING_KEY] || + changes[SKIP_FORCE_THEMING_KEY] + ) { + // Clear the styling state cache when relevant settings change + stylingStateCache.clear(); + + if (logging) + console.log("Cleared styling state cache due to settings change"); + } + } +}); + let autoUpdateInterval; function startAutoUpdate() { @@ -499,14 +907,47 @@ function stopAutoUpdate() { async function refetchCSS() { if (logging) console.log("refetchCSS called"); try { - const response = await fetch( - "https://sameerasw.github.io/my-internet/styles.json", - { headers: { "Cache-Control": "no-cache" } } - ); - if (!response.ok) throw new Error("Failed to fetch styles.json"); - const styles = await browser.storage.local.set({ styles }); - await browser.storage.local.set({ lastFetchedTime: Date.now() }); - console.info("All styles refetched and updated from GitHub."); + // Get the repository URL from storage or use the default one + const DEFAULT_REPOSITORY_URL = + "https://sameerasw.github.io/my-internet/styles.json"; + const repoUrlData = await browser.storage.local.get("stylesRepositoryUrl"); + const repositoryUrl = + repoUrlData.stylesRepositoryUrl || DEFAULT_REPOSITORY_URL; + + console.log("Background: Fetching styles from:", repositoryUrl); + + const response = await fetch(repositoryUrl, { + headers: { "Cache-Control": "no-cache" }, + }); + if (!response.ok) + throw new Error(`Failed to fetch styles (Status: ${response.status})`); + const styles = await response.json(); + await browser.storage.local.set({ styles }); + + // Check if we need to initialize default settings + const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY); + if (!settingsData[BROWSER_STORAGE_KEY]) { + // Initialize default settings if none exist + const defaultSettings = { + enableStyling: true, + autoUpdate: true, + forceStyling: false, + whitelistMode: false, + whitelistStyleMode: false, + lastFetchedTime: Date.now(), + }; + + // Save default settings + await browser.storage.local.set({ + [BROWSER_STORAGE_KEY]: defaultSettings, + }); + console.info("Initialized default settings during first fetch"); + } else { + // Just update the lastFetchedTime + await browser.storage.local.set({ lastFetchedTime: Date.now() }); + } + + console.info(`All styles refetched and updated from ${repositoryUrl}`); // Preload the new styles preloadStyles(); @@ -517,14 +958,53 @@ async function refetchCSS() { // Create a directory to store CSS files async function initializeExtension() { + // Check and initialize default settings + const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const currentSettings = data[BROWSER_STORAGE_KEY] || {}; + const validatedSettings = ensureDefaultSettings(currentSettings); + + // If we had to apply any defaults, save them + if (JSON.stringify(validatedSettings) !== JSON.stringify(currentSettings)) { + console.info( + "Initializing missing settings with defaults:", + validatedSettings + ); + await browser.storage.local.set({ + [BROWSER_STORAGE_KEY]: validatedSettings, + }); + } + + // Ensure empty lists exist + const skipForceData = await browser.storage.local.get(SKIP_FORCE_THEMING_KEY); + if (!skipForceData[SKIP_FORCE_THEMING_KEY]) { + await browser.storage.local.set({ [SKIP_FORCE_THEMING_KEY]: [] }); + } + + const skipThemingData = await browser.storage.local.get(SKIP_THEMING_KEY); + if (!skipThemingData[SKIP_THEMING_KEY]) { + await browser.storage.local.set({ [SKIP_THEMING_KEY]: [] }); + } + + const fallbackBackgroundData = await browser.storage.local.get( + FALLBACK_BACKGROUND_KEY + ); + if (!fallbackBackgroundData[FALLBACK_BACKGROUND_KEY]) { + await browser.storage.local.set({ [FALLBACK_BACKGROUND_KEY]: [] }); + } + // Preload styles immediately await preloadStyles(); // Initialize auto-update based on stored settings - const settings = await browser.storage.local.get("transparentZenSettings"); - if (settings.transparentZenSettings?.autoUpdate) { + if (validatedSettings.autoUpdate) { startAutoUpdate(); } + + // Update icons for all tabs on extension startup + const tabs = await browser.tabs.query({}); + for (const tab of tabs) { + updateIconForTab(tab.id, tab.url); + } } // Listen for specific navigation events to apply CSS as early as possible diff --git a/content-script.js b/content-script.js index 4f02174..4e99e29 100644 --- a/content-script.js +++ b/content-script.js @@ -1,42 +1,51 @@ -(function() { - const stylesheetId = 'zeninternet-custom-styles'; - - // Create or get our stylesheet element - function getStylesheet() { - let stylesheet = document.getElementById(stylesheetId); - if (!stylesheet) { - stylesheet = document.createElement('style'); - stylesheet.id = stylesheetId; - stylesheet.type = 'text/css'; - document.head.appendChild(stylesheet); - } - return stylesheet; +(function () { + const stylesheetId = "zeninternet-custom-styles"; + + // Create or get our stylesheet element + function getStylesheet() { + let stylesheet = document.getElementById(stylesheetId); + if (!stylesheet) { + stylesheet = document.createElement("style"); + stylesheet.id = stylesheetId; + stylesheet.type = "text/css"; + document.head.appendChild(stylesheet); } - - // Update our stylesheet content - function updateStyles(css) { - const stylesheet = getStylesheet(); - stylesheet.textContent = css || ''; - console.log('ZenInternet: Styles were ' + (css ? 'updated' : 'removed')); - } - - // Announce content script is ready and provide current hostname - function announceReady() { - browser.runtime.sendMessage({ - action: 'contentScriptReady', - hostname: window.location.hostname, + return stylesheet; + } + + // Update our stylesheet content + function updateStyles(css) { + const stylesheet = getStylesheet(); + stylesheet.textContent = css || ""; + console.log("ZenInternet: Styles were " + (css ? "updated" : "removed")); + } + + // Announce content script is ready and provide current hostname + function announceReady() { + try { + browser.runtime + .sendMessage({ + action: "contentScriptReady", + hostname: window.location.hostname, + }) + .catch((err) => { + // Silent fail - background might not be ready yet + console.log("ZenInternet: Could not announce ready state"); }); + } catch (e) { + // Fail silently + } + } + + // Listen for messages from background script + browser.runtime.onMessage.addListener((message) => { + if (message.action === "applyStyles") { + updateStyles(message.css); + return Promise.resolve({ success: true }); } - - // Listen for messages from background script - browser.runtime.onMessage.addListener((message) => { - if (message.action === 'applyStyles') { - updateStyles(message.css); - return Promise.resolve({ success: true }); - } - return false; - }); - - // Announce content script is ready on load - announceReady(); + return false; + }); + + // Announce content script is ready on load + announceReady(); })(); diff --git a/data-viewer/data-viewer.css b/data-viewer/data-viewer.css index fd5c3e7..3add494 100644 --- a/data-viewer/data-viewer.css +++ b/data-viewer/data-viewer.css @@ -6,7 +6,7 @@ background-color: var(--secondary-bg); border-radius: var(--radius-md); padding: 16px; - margin-bottom: 24px; + margin-bottom: 4px; border-left: 3px solid var(--accent-color); } @@ -14,11 +14,12 @@ margin-top: 8px; color: var(--text-secondary); font-size: 13px; - padding-left: 58px; + /* padding-left: 58px; */ } /* General layout adjustments */ .app-content { + width: 90%; max-width: 960px; margin: 0 auto; padding: 20px; @@ -36,7 +37,7 @@ body { /* Data section styling */ .data-section { - margin-bottom: 24px; + margin-bottom: 4px; background-color: var(--secondary-bg); border-radius: var(--radius-md); padding: 16px; @@ -109,7 +110,7 @@ body { } .website-panel { - margin-bottom: 8px; + margin-bottom: 4px; background-color: var(--bg-color); border-radius: var(--radius-md); overflow: hidden; @@ -346,18 +347,7 @@ body { /* Clear list button styling */ .clear-list-button { - margin-top: 8px; - margin-bottom: 16px; - background-color: var(--secondary-bg); - border-color: var(--border-color); - font-size: 12px; - padding: 6px 12px; -} - -.clear-list-button:hover { - background-color: rgba(220, 53, 69, 0.1); - border-color: var(--danger-color); - color: var(--danger-color); + margin-bottom: 20px; } /* Null and object value styling */ @@ -373,7 +363,7 @@ body { /* Danger zone styling */ .danger-zone { - margin-top: 24px; + margin-top: 8px; padding: 16px; background-color: var(--danger-bg-color); border: 1px solid var(--danger-border-color); @@ -446,3 +436,213 @@ body { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } } + +/* Styling for the website lists section */ +.tables-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 16px; + margin-top: 16px; +} + +.list-title-section { + margin-bottom: 16px; +} + +.list-title-section h3 { + margin-top: 0; + margin-bottom: 12px; + color: var(--text-primary); + font-size: 18px; +} + +.list-section { + background-color: var(--bg-color); + border-radius: var(--radius-sm); + padding: 16px; +} + +.list-section h4 { + margin-top: 0; + margin-bottom: 8px; + color: var(--accent-color); +} + +.list-description { + margin-top: 0; + margin-bottom: 16px; + font-size: 13px; + color: var(--text-secondary); + font-style: italic; +} + +.remove-site-button { + background-color: var(--danger-color); + color: white; + border: none; + border-radius: 50%; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: var(--transition); +} + +.remove-site-button:hover { + background-color: var(--danger-hover-color); + transform: scale(1.1); +} + +.remove-site-button i { + font-size: 12px; +} + +.clear-list-button { + margin-bottom: 20px; +} + +/* Backup and Restore Styling */ +.backup-restore-container { + background-color: var(--bg-color); + border-radius: var(--radius-sm); + padding: 16px; + border-left: 3px solid var(--accent-color); +} + +.backup-description { + margin-top: 0; + margin-bottom: 16px; + color: var(--text-secondary); + font-size: 14px; + line-height: 1.5; +} + +.backup-actions { + display: flex; + gap: 16px; + margin-bottom: 16px; +} + +.import-container, +#export-settings { + flex: 1; +} + +.import-label { + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.import-status { + font-size: 14px; + margin-top: 8px; + padding: 8px 0; + border-radius: var(--radius-sm); +} + +.status-success { + color: var(--success-color); + font-weight: 500; +} + +.status-error { + color: var(--danger-color); + font-weight: 500; +} + +/* Repository URL styling */ +.repository-url-container { + background-color: var(--bg-color); + border-radius: var(--radius-sm); + padding: 16px; + border-left: 3px solid var(--accent-color); +} + +.repository-url-controls { + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 16px; +} + +.repository-url-input { + /* width: 100%; */ + padding: 10px 12px; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + background-color: var(--bg-color); + color: var(--text-primary); + font-size: 14px; +} + +.repository-url-input:focus { + outline: none; + border-color: var(--accent-color); +} + +.repository-url-buttons { + display: flex; + gap: 12px; +} + +.repository-url-status { + font-size: 14px; + margin-top: 8px; + padding: 8px 0; + border-radius: var(--radius-sm); +} + +/* Add responsive adjustments for mobile */ +@media (max-width: 1024px) { + .tables-container { + grid-template-columns: 1fr; + gap: 12px; + } +} + +@media (max-width: 768px) { + .repository-url-buttons { + flex-direction: column; + gap: 8px; + } + + .repository-url-buttons button { + width: 100%; + } +} + +/* Global toggles container styling */ +.global-toggles-container { + background-color: var(--bg-color); + border-radius: var(--radius-sm); + padding: 16px; + border-left: 3px solid var(--accent-color); +} + +.toggle-row { + display: flex; + flex-wrap: wrap; + gap: 16px; + margin-bottom: 12px; +} + +.toggle-row .toggle-container { + flex: 1; + min-width: 180px; + margin-bottom: 0; +} + +@media (max-width: 768px) { + .toggle-row { + flex-direction: column; + gap: 8px; + } + + .toggle-row .toggle-container { + margin-bottom: 4px; + } +} diff --git a/data-viewer/data-viewer.html b/data-viewer/data-viewer.html index b0d4a5f..0f4ba9b 100644 --- a/data-viewer/data-viewer.html +++ b/data-viewer/data-viewer.html @@ -16,7 +16,7 @@ <header class="app-header"> <div id="header-container"> <div class="logo-container"> - <img src="../assets/images/logo_48.png" alt="ZenInternet Logo" class="logo-img"> + <img src="../assets/images/logo.png" alt="ZenInternet Logo" class="logo-img"> <h1 class="app-title">Zen Internet Settings</h1> </div> <div class="miniheader"> @@ -27,22 +27,61 @@ </header> <main class="app-content"> - <div class="actions"> - <button id="back-button" class="action-button secondary"> - <i class="fas fa-arrow-left"></i> Back to Extension - </button> + <!-- Backup & Restore section moved to top --> + <div class="data-section"> + <h2 class="section-title">Backup & Restore ✨</h2> + <div class="backup-restore-container"> + <p class="backup-description"> + Export your settings to a JSON file or import settings from a previously exported file. + <br><strong>Note:</strong> This includes global settings, website lists, and website-specific + feature toggles, but not the actual style data which will be re-fetched. + </p> + <div class="backup-actions"> + <button id="export-settings" class="action-button primary"> + <i class="fas fa-upload"></i> Export Settings + </button> + <div class="import-container"> + <label for="import-file" class="action-button secondary import-label"> + <i class="fas fa-download"></i> Import Settings + </label> + <input type="file" id="import-file" accept=".json" hidden> + </div> + </div> + <div id="import-status" class="import-status"></div> + </div> </div> - <div class="toggle-setting-container"> - <div class="toggle-container"> - <label class="toggle-switch"> - <input type="checkbox" id="disable-transparency"> - <span class="slider round"></span> - </label> - <span class="toggle-label">Disable Transparency Globally</span> - </div> - <div class="setting-description"> - This will disable all transparency features while keeping other styling effects active + <!-- Global toggles grouped into a single section with a heading --> + <div class="data-section"> + <h2 class="section-title">Global Feature Controls ✨</h2> + <div class="global-toggles-container"> + <div class="toggle-row"> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="disable-transparency"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Disable Transparency</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="disable-hover"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Disable Hover Effects</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="disable-footer"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Keep Footers</span> + </div> + </div> + <div class="setting-description"> + These settings control specific feature types across all websites. + Changes apply only to newly opened or reloaded tabs. + </div> </div> </div> @@ -56,6 +95,32 @@ <div id="skip-list-data" class="data-container"></div> </div> + <!-- Repository URL section moved above danger zone --> + <div class="data-section"> + <h2 class="section-title">Custom Styles Repository ✨</h2> + <div class="repository-url-container"> + <p class="setting-description"> + Change the URL where styles are fetched from. Use this if you want to use a different styles + repository. + <br><strong>Note:</strong> After changing the URL, you should clear existing styles data for + best results. + </p> + <div class="repository-url-controls"> + <input type="text" id="repository-url" class="repository-url-input" + placeholder="Enter repository URL..."> + <div class="repository-url-buttons"> + <button id="set-repository-url" class="action-button primary"> + <i class="fas fa-save"></i> Set URL + </button> + <button id="reset-repository-url" class="action-button secondary"> + <i class="fas fa-undo"></i> Reset to Default + </button> + </div> + </div> + <div id="repository-url-status" class="repository-url-status"></div> + </div> + </div> + <div class="danger-zone"> <h3 class="danger-title">Danger Zone</h3> <div class="danger-actions"> @@ -69,17 +134,18 @@ <h2 class="section-title">Websites and CSS</h2> <div id="combined-websites-data" class="data-container"></div> </div> - </main> - <footer class="app-footer"> - <a href="https://sameerasw.github.io/my-internet/" class="footer-link" target="_blank"> - <i class="fas fa-book"></i> Styles Repository - </a> - <div class="footer-divider"></div> - <a href="https://github.com/sameerasw/zeninternet" class="footer-link" target="_blank"> - <i class="fa-brands fa-github"></i> Project Repository - </a> - </footer> + + <footer class="app-footer"> + <a href="https://sameerasw.github.io/my-internet/" class="footer-link" target="_blank"> + <i class="fas fa-book"></i> Styles Repository + </a> + <div class="footer-divider"></div> + <a href="https://github.com/sameerasw/zeninternet" class="footer-link" target="_blank"> + <i class="fa-brands fa-github"></i> Project Repository + </a> + </footer> + </main> </div> <script src="data-viewer.js"></script> </body> diff --git a/data-viewer/data-viewer.js b/data-viewer/data-viewer.js index f6dd566..be1b798 100644 --- a/data-viewer/data-viewer.js +++ b/data-viewer/data-viewer.js @@ -1,18 +1,38 @@ document.addEventListener("DOMContentLoaded", function () { const BROWSER_STORAGE_KEY = "transparentZenSettings"; const SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; + const SKIP_THEMING_KEY = "skipThemingList"; + const FALLBACK_BACKGROUND_KEY = "fallbackBackgroundList"; + const REPOSITORY_URL_KEY = "stylesRepositoryUrl"; + const DEFAULT_REPOSITORY_URL = + "https://sameerasw.github.io/my-internet/styles.json"; const globalSettingsElement = document.getElementById("global-settings-data"); const skipListElement = document.getElementById("skip-list-data"); const combinedWebsitesElement = document.getElementById( "combined-websites-data" ); - const backButton = document.getElementById("back-button"); const deleteAllButton = document.getElementById("delete-all-data"); const versionElement = document.getElementById("addon-version"); const disableTransparencyToggle = document.getElementById( "disable-transparency" ); + // New toggle elements + const disableHoverToggle = document.getElementById("disable-hover"); + const disableFooterToggle = document.getElementById("disable-footer"); + + // Repository URL Elements + const repositoryUrlInput = document.getElementById("repository-url"); + const setRepositoryUrlButton = document.getElementById("set-repository-url"); + const resetRepositoryUrlButton = document.getElementById( + "reset-repository-url" + ); + const repositoryUrlStatus = document.getElementById("repository-url-status"); + + // Backup & Restore Elements + const exportButton = document.getElementById("export-settings"); + const importFileInput = document.getElementById("import-file"); + const importStatusElement = document.getElementById("import-status"); // Load and display the data loadAllData(); @@ -20,16 +40,20 @@ document.addEventListener("DOMContentLoaded", function () { // Display addon version displayAddonVersion(); - // Event listener for the back button - backButton.addEventListener("click", function () { - window.close(); - }); - // Event listener for disable transparency toggle disableTransparencyToggle.addEventListener("change", function () { saveTransparencySettings(this.checked); }); + // Event listeners for new toggles + disableHoverToggle.addEventListener("change", function () { + saveHoverSettings(this.checked); + }); + + disableFooterToggle.addEventListener("change", function () { + saveFooterSettings(this.checked); + }); + // Event listener for delete all data button deleteAllButton.addEventListener("click", function () { if ( @@ -41,6 +65,132 @@ document.addEventListener("DOMContentLoaded", function () { } }); + // Repository URL event listeners + setRepositoryUrlButton.addEventListener("click", setRepositoryUrl); + resetRepositoryUrlButton.addEventListener("click", resetRepositoryUrl); + + // New event listeners for export and import functionality + exportButton.addEventListener("click", exportSettings); + importFileInput.addEventListener("change", importSettings); + + // Load the repository URL from storage + loadRepositoryUrl(); + + async function loadRepositoryUrl() { + try { + const data = await browser.storage.local.get(REPOSITORY_URL_KEY); + const repositoryUrl = data[REPOSITORY_URL_KEY] || DEFAULT_REPOSITORY_URL; + repositoryUrlInput.value = repositoryUrl; + } catch (error) { + console.error("Error loading repository URL:", error); + repositoryUrlInput.value = DEFAULT_REPOSITORY_URL; + } + } + + async function setRepositoryUrl() { + try { + const newUrl = repositoryUrlInput.value.trim(); + + if (!newUrl) { + showRepositoryUrlStatus("Repository URL cannot be empty", "error"); + return; + } + + // Simple URL validation + try { + new URL(newUrl); + } catch (e) { + showRepositoryUrlStatus("Invalid URL format", "error"); + return; + } + + // Save the new URL to storage + await browser.storage.local.set({ [REPOSITORY_URL_KEY]: newUrl }); + + showRepositoryUrlStatus("Repository URL saved successfully", "success"); + + // Prompt the user to clear styles data + if ( + confirm( + "Would you like to clear existing styles data to avoid conflicts with the new repository?\n\nThis will clear saved styles and website-specific settings, but keep your global settings." + ) + ) { + await clearStylesData(); + } + } catch (error) { + console.error("Error setting repository URL:", error); + showRepositoryUrlStatus(`Error saving URL: ${error.message}`, "error"); + } + } + + async function resetRepositoryUrl() { + try { + repositoryUrlInput.value = DEFAULT_REPOSITORY_URL; + await browser.storage.local.set({ + [REPOSITORY_URL_KEY]: DEFAULT_REPOSITORY_URL, + }); + + showRepositoryUrlStatus("Repository URL reset to default", "success"); + + // Prompt to clear styles data + if ( + confirm( + "Would you like to clear existing styles data to avoid conflicts?\n\nThis will clear saved styles and website-specific settings, but keep your global settings." + ) + ) { + await clearStylesData(); + } + } catch (error) { + console.error("Error resetting repository URL:", error); + showRepositoryUrlStatus(`Error resetting URL: ${error.message}`, "error"); + } + } + + async function clearStylesData() { + try { + // Get all storage data to filter what to keep and what to remove + const allData = await browser.storage.local.get(null); + + // Create a new object with just the data we want to keep + const dataToKeep = {}; + + // Keep global settings + if (allData[BROWSER_STORAGE_KEY]) { + dataToKeep[BROWSER_STORAGE_KEY] = allData[BROWSER_STORAGE_KEY]; + } + + // Keep repository URL + if (allData[REPOSITORY_URL_KEY]) { + dataToKeep[REPOSITORY_URL_KEY] = allData[REPOSITORY_URL_KEY]; + } + + // Clear all storage first + await browser.storage.local.clear(); + + // Then restore the data we want to keep + await browser.storage.local.set(dataToKeep); + + // Refresh the data display + loadAllData(); + + showRepositoryUrlStatus("Styles data cleared successfully", "success"); + } catch (error) { + console.error("Error clearing styles data:", error); + showRepositoryUrlStatus(`Error clearing data: ${error.message}`, "error"); + } + } + + function showRepositoryUrlStatus(message, type) { + repositoryUrlStatus.textContent = message; + repositoryUrlStatus.className = `repository-url-status status-${type}`; + + // Clear the message after 5 seconds + setTimeout(() => { + repositoryUrlStatus.textContent = ""; + repositoryUrlStatus.className = "repository-url-status"; + }, 5000); + } + async function deleteAllData() { try { // Clear all storage data @@ -68,20 +218,202 @@ document.addEventListener("DOMContentLoaded", function () { settings.disableTransparency = isDisabled; await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); - alert( - `Transparency has been ${ - isDisabled ? "disabled" : "enabled" - } globally. This will affect all websites.` - ); + // No notification - just save the setting silently } catch (error) { console.error("Error saving transparency settings:", error); - alert( - "An error occurred while saving the transparency setting: " + - error.message - ); } } + // New functions to save hover and footer settings + async function saveHoverSettings(isDisabled) { + try { + const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const settings = data[BROWSER_STORAGE_KEY] || {}; + + // Update the disableHover setting + settings.disableHover = isDisabled; + + await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); + // No notification - just save the setting silently + } catch (error) { + console.error("Error saving hover settings:", error); + } + } + + async function saveFooterSettings(isDisabled) { + try { + const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); + const settings = data[BROWSER_STORAGE_KEY] || {}; + + // Update the disableFooter setting + settings.disableFooter = isDisabled; + + await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); + // No notification - just save the setting silently + } catch (error) { + console.error("Error saving footer settings:", error); + } + } + + // Export settings functionality + async function exportSettings() { + try { + // Retrieve all storage data to find site-specific settings + const allData = await browser.storage.local.get(null); + + // Get the fallback background list once + const fallbackBackgroundList = allData[FALLBACK_BACKGROUND_KEY] || []; + + // Extract only the settings we want to backup + const settingsToBackup = { + [BROWSER_STORAGE_KEY]: allData[BROWSER_STORAGE_KEY] || {}, + [SKIP_FORCE_THEMING_KEY]: allData[SKIP_FORCE_THEMING_KEY] || [], + [SKIP_THEMING_KEY]: allData[SKIP_THEMING_KEY] || [], + [FALLBACK_BACKGROUND_KEY]: fallbackBackgroundList, + [REPOSITORY_URL_KEY]: + allData[REPOSITORY_URL_KEY] || DEFAULT_REPOSITORY_URL, + }; + + // Remove fallbackBackgroundList from global settings if it exists there + if (settingsToBackup[BROWSER_STORAGE_KEY].fallbackBackgroundList) { + delete settingsToBackup[BROWSER_STORAGE_KEY].fallbackBackgroundList; + } + + // Also extract site-specific settings (keys that start with BROWSER_STORAGE_KEY.) + const siteSpecificSettings = {}; + for (const [key, value] of Object.entries(allData)) { + if (key.startsWith(BROWSER_STORAGE_KEY + ".")) { + siteSpecificSettings[key] = value; + } + } + + // Add export timestamp and version + const manifest = browser.runtime.getManifest(); + const exportData = { + exportDate: new Date().toISOString(), + addonVersion: manifest.version, + settings: settingsToBackup, + siteSettings: siteSpecificSettings, + }; + + // Convert to JSON + const jsonData = JSON.stringify(exportData, null, 2); + + // Create a blob and download link + const blob = new Blob([jsonData], { type: "application/json" }); + const url = URL.createObjectURL(blob); + + // Create a temporary anchor and trigger download + const a = document.createElement("a"); + a.href = url; + a.download = `zen-internet-settings-${ + new Date().toISOString().split("T")[0] + }.json`; + document.body.appendChild(a); + a.click(); + + // Cleanup + setTimeout(() => { + document.body.removeChild(a); + URL.revokeObjectURL(url); + }, 0); + + // Show success message + showImportStatus("Settings exported successfully!", "success"); + } catch (error) { + console.error("Error exporting settings:", error); + showImportStatus(`Export failed: ${error.message}`, "error"); + } + } + + // Import settings functionality + async function importSettings(event) { + try { + const file = event.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + + reader.onload = async (e) => { + try { + const importData = JSON.parse(e.target.result); + + // Validate the imported data structure + if ( + !importData.settings || + !importData.settings[BROWSER_STORAGE_KEY] + ) { + throw new Error("Invalid settings file format"); + } + + // Confirm the import + if ( + confirm( + `Are you sure you want to import settings from ${importData.exportDate}? This will overwrite your current settings.` + ) + ) { + // First store the global settings, lists, and repository URL + const importOperations = { + [BROWSER_STORAGE_KEY]: importData.settings[BROWSER_STORAGE_KEY], + [SKIP_FORCE_THEMING_KEY]: + importData.settings[SKIP_FORCE_THEMING_KEY] || [], + [SKIP_THEMING_KEY]: importData.settings[SKIP_THEMING_KEY] || [], + [REPOSITORY_URL_KEY]: + importData.settings[REPOSITORY_URL_KEY] || + DEFAULT_REPOSITORY_URL, + }; + + // Then add any site-specific settings if they exist + if (importData.siteSettings) { + for (const [key, value] of Object.entries( + importData.siteSettings + )) { + importOperations[key] = value; + } + } + + // Apply all settings at once + await browser.storage.local.set(importOperations); + + showImportStatus( + "Settings imported successfully! Reloading...", + "success" + ); + + // Reload the page after a short delay + setTimeout(() => { + window.location.reload(); + }, 1500); + } else { + // User cancelled + importFileInput.value = ""; + showImportStatus("Import cancelled", "error"); + } + } catch (parseError) { + console.error("Error parsing import file:", parseError); + showImportStatus(`Import failed: ${parseError.message}`, "error"); + } + }; + + reader.readAsText(file); + } catch (error) { + console.error("Error handling import:", error); + showImportStatus(`Import failed: ${error.message}`, "error"); + } + } + + // Helper function to show import status messages + function showImportStatus(message, type) { + importStatusElement.textContent = message; + importStatusElement.className = `import-status status-${type}`; + + // Clear the message after 5 seconds + setTimeout(() => { + importStatusElement.textContent = ""; + importStatusElement.className = "import-status"; + }, 5000); + } + async function displayAddonVersion() { const manifest = browser.runtime.getManifest(); versionElement.textContent = `Version: ${manifest.version}`; @@ -90,24 +422,26 @@ document.addEventListener("DOMContentLoaded", function () { async function loadAllData() { try { // Load all data from storage - const data = await browser.storage.local.get(null); - - // Display global settings - const globalSettings = data[BROWSER_STORAGE_KEY] || {}; - displayGlobalSettings(globalSettings); - - // Set the disable transparency toggle state - disableTransparencyToggle.checked = - globalSettings.disableTransparency || false; + const allData = await browser.storage.local.get(null); - // Display skip/enable list - const skipList = data[SKIP_FORCE_THEMING_KEY] || []; - displaySkipList(skipList, globalSettings.whitelistMode); + // Extract global settings + const globalSettings = allData[BROWSER_STORAGE_KEY] || {}; - // Display combined websites and settings - displayCombinedWebsiteData(data); + // Extract skip lists + const skipForceList = allData[SKIP_FORCE_THEMING_KEY] || []; + const skipThemingList = allData[SKIP_THEMING_KEY] || []; + const fallbackBackgroundList = allData[FALLBACK_BACKGROUND_KEY] || []; - console.info("Data loaded successfully"); + // Display the data + displayGlobalSettings(globalSettings); + displayCombinedSkipLists( + skipForceList, + skipThemingList, + fallbackBackgroundList, + globalSettings.whitelistMode || false, + globalSettings.whitelistStyleMode || false + ); + displayCombinedWebsiteData(allData); } catch (error) { console.error("Error loading data:", error); } @@ -155,46 +489,123 @@ document.addEventListener("DOMContentLoaded", function () { globalSettingsElement.appendChild(table); } - function displaySkipList(skipList, isWhitelistMode) { + function displayCombinedSkipLists( + skipForceList, + skipThemingList, + fallbackBackgroundList, + isWhitelistMode, + isWhitelistStyleMode + ) { skipListElement.innerHTML = ""; - const modeType = isWhitelistMode ? "Whitelist" : "Blacklist"; - const actionType = isWhitelistMode ? "Enabled" : "Skipped"; + // Create title and description section + const titleSection = document.createElement("div"); + titleSection.className = "list-title-section"; + + const forceModeName = isWhitelistMode ? "Whitelist" : "Blacklist"; + const styleModeName = isWhitelistStyleMode ? "Whitelist" : "Blacklist"; - const modeInfo = document.createElement("div"); - modeInfo.classList.add("mode-info"); - modeInfo.innerHTML = `<strong>Current Mode:</strong> ${modeType} Mode - ${ + titleSection.innerHTML = ` + <h3>Website Lists Overview</h3> + <div class="mode-info"> + <div><strong>Force Styling Mode:</strong> ${forceModeName} Mode (${ isWhitelistMode - ? "Only apply forced styling to sites in the list" - : "Apply forced styling to all sites except those in the list" - }`; - skipListElement.appendChild(modeInfo); - - // Add Clear List button - if (skipList.length > 0) { - const clearListButton = document.createElement("button"); - clearListButton.classList.add( + ? "only apply to sites in the list" + : "apply to all except sites in the list" + })</div> + <div><strong>General Styling Mode:</strong> ${styleModeName} Mode (${ + isWhitelistStyleMode + ? "only apply to sites in the list" + : "apply to all except sites in the list" + })</div> + </div> + `; + + skipListElement.appendChild(titleSection); + + // Add Clear All Lists button + if ( + skipForceList.length > 0 || + skipThemingList.length > 0 || + fallbackBackgroundList.length > 0 + ) { + const clearAllButton = document.createElement("button"); + clearAllButton.classList.add( "action-button", - "secondary", + "danger", "clear-list-button" ); - clearListButton.innerHTML = '<i class="fas fa-trash"></i> Clear List'; - clearListButton.addEventListener("click", function () { - if ( - confirm( - `Are you sure you want to clear the entire ${modeType} list? This will affect how styling is applied to websites.` - ) - ) { - clearSkipList(); - } - }); - skipListElement.appendChild(clearListButton); + clearAllButton.innerHTML = '<i class="fas fa-trash"></i> Clear All Lists'; + clearAllButton.addEventListener("click", clearAllSkipLists); + skipListElement.appendChild(clearAllButton); } - if (skipList.length === 0) { - skipListElement.innerHTML += - '<div class="no-data">No websites in the list.</div>'; - return; + // Create container for the three tables + const tablesContainer = document.createElement("div"); + tablesContainer.className = "tables-container"; + + // Create force styling list + const forceListSection = createSingleListSection( + skipForceList, + isWhitelistMode, + "Force Styling List", + isWhitelistMode + ? "Sites where forced styling IS applied" + : "Sites where forced styling is NOT applied", + SKIP_FORCE_THEMING_KEY + ); + + // Create regular styling list + const regularListSection = createSingleListSection( + skipThemingList, + isWhitelistStyleMode, + "Regular Styling List", + isWhitelistStyleMode + ? "Sites where regular styling IS applied" + : "Sites where regular styling is NOT applied", + SKIP_THEMING_KEY + ); + + // Create fallback background list + const fallbackListSection = createSingleListSection( + fallbackBackgroundList, + false, // Fallback background is not whitelist/blacklist based + "Fallback Background List", + "Sites where a default background added, no transparency", + FALLBACK_BACKGROUND_KEY + ); + + tablesContainer.appendChild(forceListSection); + tablesContainer.appendChild(regularListSection); + tablesContainer.appendChild(fallbackListSection); + skipListElement.appendChild(tablesContainer); + } + + function createSingleListSection( + list, + isWhitelistMode, + title, + description, + storageKey + ) { + const section = document.createElement("div"); + section.className = "list-section"; + + const sectionTitle = document.createElement("h4"); + sectionTitle.textContent = title; + section.appendChild(sectionTitle); + + const sectionDescription = document.createElement("p"); + sectionDescription.className = "list-description"; + sectionDescription.textContent = description; + section.appendChild(sectionDescription); + + if (list.length === 0) { + const emptyMessage = document.createElement("div"); + emptyMessage.className = "no-data"; + emptyMessage.textContent = "No websites in this list"; + section.appendChild(emptyMessage); + return section; } const table = document.createElement("table"); @@ -203,33 +614,81 @@ document.addEventListener("DOMContentLoaded", function () { // Table header const thead = document.createElement("thead"); const headerRow = document.createElement("tr"); - headerRow.innerHTML = `<th>${actionType} Websites</th>`; + headerRow.innerHTML = `<th>Website</th><th>Action</th>`; thead.appendChild(headerRow); table.appendChild(thead); // Table body const tbody = document.createElement("tbody"); - for (const site of skipList) { + for (const site of list) { const row = document.createElement("tr"); - row.innerHTML = `<td>${site}</td>`; + + // Website column + const siteCell = document.createElement("td"); + siteCell.textContent = site; + row.appendChild(siteCell); + + // Action column + const actionCell = document.createElement("td"); + const removeButton = document.createElement("button"); + removeButton.className = "remove-site-button"; + removeButton.innerHTML = '<i class="fas fa-times"></i>'; + removeButton.title = "Remove from list"; + removeButton.addEventListener("click", function () { + removeSiteFromList(site, storageKey); + }); + actionCell.appendChild(removeButton); + row.appendChild(actionCell); + tbody.appendChild(row); } table.appendChild(tbody); - skipListElement.appendChild(table); + section.appendChild(table); + return section; + } + + async function removeSiteFromList(site, listKey) { + try { + // Get current list + const data = await browser.storage.local.get(listKey); + const list = data[listKey] || []; + + // Remove the site + const newList = list.filter((item) => item !== site); + + // Save updated list + await browser.storage.local.set({ [listKey]: newList }); + + // Refresh the display + loadAllData(); + + console.log(`Removed ${site} from ${listKey}`); + } catch (error) { + console.error(`Error removing site from list: ${error}`); + alert(`An error occurred: ${error.message}`); + } } - async function clearSkipList() { + async function clearAllSkipLists() { try { - await browser.storage.local.remove(SKIP_FORCE_THEMING_KEY); - alert(`${SKIP_FORCE_THEMING_KEY} has been cleared successfully.`); - loadAllData(); // Reload data to reflect changes + if ( + confirm( + "Are you sure you want to clear ALL website lists? This will remove all entries from:\n- Force Styling List\n- Regular Styling List\n- Fallback Background List\n\nThis action cannot be undone." + ) + ) { + await browser.storage.local.set({ + [SKIP_FORCE_THEMING_KEY]: [], + [SKIP_THEMING_KEY]: [], + [FALLBACK_BACKGROUND_KEY]: [], + }); + loadAllData(); // Reload to show empty lists + console.log("All skip lists cleared"); + } } catch (error) { - console.error("Error clearing skip list:", error); - alert( - "An error occurred while trying to clear the list: " + error.message - ); + console.error("Error clearing skip lists:", error); + alert("An error occurred while clearing the lists: " + error.message); } } diff --git a/logo.psd b/logo.psd Binary files differnew file mode 100644 index 0000000..5fa1662 --- /dev/null +++ b/logo.psd diff --git a/manifest.json b/manifest.json index beae3aa..3b5e8a8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,8 @@ { "manifest_version": 2, "name": "Zen Internet", - "version": "1.9.0", - "description": "Inject custom css from my repository in real time", + "version": "2.3.0", + "description": "Make the internet feel native and elegant. Zen Internet is a browser extension that enhances your browsing experience by providing a clean and minimalistic interface with transparency and a focus on content. Customize the features in the addon popup.", "browser_specific_settings": { "gecko": { "id": "{91aa3897-2634-4a8a-9092-279db23a7689}" @@ -23,7 +23,11 @@ ], "browser_action": { "default_popup": "popup/popup.html", - "default_title": "Zen Internet" + "default_title": "Zen Internet", + "default_icon": { + "48": "assets/images/logo_48.png", + "96": "assets/images/logo_96.png" + } }, "background": { "scripts": ["background.js"], @@ -34,6 +38,6 @@ "data-viewer/data-viewer.html", "data-viewer/data-viewer.js", "data-viewer/data-viewer.css", - "styling/*" + "shared/*" ] } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 0048cc3..0000000 --- a/package-lock.json +++ /dev/null @@ -1,4626 +0,0 @@ -{ - "name": "transparent-zen", - "version": "0.1.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "transparent-zen", - "version": "0.1.1", - "license": "MIT", - "devDependencies": { - "dotenv": "^16.4.7", - "web-ext": "^8.4.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@devicefarmer/adbkit": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit/-/adbkit-3.3.8.tgz", - "integrity": "sha512-7rBLLzWQnBwutH2WZ0EWUkQdihqrnLYCUMaB44hSol9e0/cdIhuNFcqZO0xNheAU6qqHVA8sMiLofkYTgb+lmw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@devicefarmer/adbkit-logcat": "^2.1.2", - "@devicefarmer/adbkit-monkey": "~1.2.1", - "bluebird": "~3.7", - "commander": "^9.1.0", - "debug": "~4.3.1", - "node-forge": "^1.3.1", - "split": "~1.0.1" - }, - "bin": { - "adbkit": "bin/adbkit" - }, - "engines": { - "node": ">= 0.10.4" - } - }, - "node_modules/@devicefarmer/adbkit-logcat": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-logcat/-/adbkit-logcat-2.1.3.tgz", - "integrity": "sha512-yeaGFjNBc/6+svbDeul1tNHtNChw6h8pSHAt5D+JsedUrMTN7tla7B15WLDyekxsuS2XlZHRxpuC6m92wiwCNw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@devicefarmer/adbkit-monkey": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-monkey/-/adbkit-monkey-1.2.1.tgz", - "integrity": "sha512-ZzZY/b66W2Jd6NHbAhLyDWOEIBWC11VizGFk7Wx7M61JZRz7HR9Cq5P+65RKWUU7u6wgsE8Lmh9nE4Mz+U2eTg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">= 0.10.4" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "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/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.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": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/eslintrc/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@fluent/syntax": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@fluent/syntax/-/syntax-0.19.0.tgz", - "integrity": "sha512-5D2qVpZrgpjtqU4eNOcWGp1gnUCgjfM+vKGE2y03kKN6z5EBhtx0qdRFbg8QuNNj8wXNoX93KJoYb+NqoxswmQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@fregante/relaxed-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fregante/relaxed-json/-/relaxed-json-2.0.0.tgz", - "integrity": "sha512-PyUXQWB42s4jBli435TDiYuVsadwRHnMc27YaLouINktvTWsL3FcKrRMGawTayFk46X+n5bE23RjUTWQwrukWw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "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/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@mdn/browser-compat-data": { - "version": "5.6.31", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.6.31.tgz", - "integrity": "sha512-E/X4YlErVjBCMvaJbqD2Jb0B/Z+TQJyw4vN6q98iit05RLW9VEcsedaTiL81BAbYF9GICn/KpFGE9dMJi66Ydw==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "license": "ISC" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", - "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "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/addons-linter": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/addons-linter/-/addons-linter-7.8.0.tgz", - "integrity": "sha512-SnDJUAtrHu1RUMIiIZXNN8wF0ze7IbDokwUy5HZYlCkNTn8E4RcI74xhdHtCdtoQprAmyhxePP/hFf+9XPhe8w==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "@fluent/syntax": "0.19.0", - "@fregante/relaxed-json": "2.0.0", - "@mdn/browser-compat-data": "5.6.31", - "addons-moz-compare": "1.3.0", - "addons-scanner-utils": "9.12.0", - "ajv": "8.17.1", - "chalk": "4.1.2", - "cheerio": "1.0.0-rc.12", - "columnify": "1.6.0", - "common-tags": "1.8.2", - "deepmerge": "4.3.1", - "eslint": "8.57.1", - "eslint-plugin-no-unsanitized": "4.1.2", - "eslint-visitor-keys": "4.2.0", - "espree": "10.3.0", - "esprima": "4.0.1", - "fast-json-patch": "3.1.1", - "image-size": "1.2.0", - "json-merge-patch": "1.0.2", - "pino": "8.20.0", - "semver": "7.6.3", - "source-map-support": "0.5.21", - "upath": "2.0.1", - "yargs": "17.7.2", - "yauzl": "2.10.0" - }, - "bin": { - "addons-linter": "bin/addons-linter" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/addons-linter/node_modules/pino": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.20.0.tgz", - "integrity": "sha512-uhIfMj5TVp+WynVASaVEJFTncTUe4dHBq6CWplu/vBgvGHhvBvQfxz+vcOrnnBQdORH3izaGEurLfNlq3YxdFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/addons-linter/node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", - "dev": true, - "license": "MIT" - }, - "node_modules/addons-linter/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/addons-linter/node_modules/sonic-boom": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", - "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/addons-linter/node_modules/thread-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", - "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/addons-moz-compare": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/addons-moz-compare/-/addons-moz-compare-1.3.0.tgz", - "integrity": "sha512-/rXpQeaY0nOKhNx00pmZXdk5Mu+KhVlL3/pSBuAYwrxRrNiTvI/9xfQI8Lmm7DMMl+PDhtfAHY/0ibTpdeoQQQ==", - "dev": true, - "license": "MPL-2.0" - }, - "node_modules/addons-scanner-utils": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/addons-scanner-utils/-/addons-scanner-utils-9.12.0.tgz", - "integrity": "sha512-Nn+mOgJhdSZKkycXd5GYfSfoyT1lEGbCVoCBKriEFceuP0dJxVBuFwuRD8+PuXegQQBw7COTS5DwM4nj+bK8Mg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "@types/yauzl": "2.10.3", - "common-tags": "1.8.2", - "first-chunk-stream": "3.0.0", - "strip-bom-stream": "4.0.0", - "upath": "2.0.1", - "yauzl": "2.10.0" - }, - "peerDependencies": { - "body-parser": "1.20.3", - "express": "4.21.0", - "node-fetch": "2.6.11", - "safe-compare": "1.1.4" - }, - "peerDependenciesMeta": { - "body-parser": { - "optional": true - }, - "express": { - "optional": true - }, - "node-fetch": { - "optional": true - }, - "safe-compare": { - "optional": true - } - } - }, - "node_modules/adm-zip": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", - "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/array-differ": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", - "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/atomically": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/atomically/-/atomically-2.0.3.tgz", - "integrity": "sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==", - "dev": true, - "dependencies": { - "stubborn-fs": "^1.2.5", - "when-exit": "^2.1.1" - } - }, - "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/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "4.34.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.1.tgz", - "integrity": "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "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/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "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/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chrome-launcher": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.1.2.tgz", - "integrity": "sha512-YclTJey34KUm5jB1aEJCq807bSievi7Nb/TU4Gu504fUYi3jw3KCIaH6L7nFWQhdEgH3V+wCh+kKD1P5cXnfxw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^2.0.1" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "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/columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "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/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/configstore": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-7.0.0.tgz", - "integrity": "sha512-yk7/5PN5im4qwz0WFZW3PXnzHgPu9mX29Y8uZ3aefe2lBPC1FYttWZRcaW9fKkT0pBCJyuQ2HfbmPVaODi9jcQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "atomically": "^2.0.3", - "dot-prop": "^9.0.0", - "graceful-fs": "^4.2.11", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/yeoman/configstore?sponsor=1" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "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/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", - "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "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/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-prop": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", - "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^4.18.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dot-prop/node_modules/type-fest": { - "version": "4.34.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.1.tgz", - "integrity": "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT" - }, - "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-goat": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", - "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-no-unsanitized": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.1.2.tgz", - "integrity": "sha512-ydF3PMFKEIkP71ZbLHFvu6/FW8SvRv6VV/gECfrQkqyD5+5oCAtPz8ZHy0GRuMDtNe2jsNdPCQXX4LSbkapAVQ==", - "dev": true, - "license": "MPL-2.0", - "peerDependencies": { - "eslint": "^8 || ^9" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.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/eslint/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/eslint/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/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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/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/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "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/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "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-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", - "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/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.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/firefox-profile": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/firefox-profile/-/firefox-profile-4.7.0.tgz", - "integrity": "sha512-aGApEu5bfCNbA4PGUZiRJAIU6jKmghV2UVdklXAofnNtiDjqYw0czLS46W7IfFqVKgKhFB8Ao2YoNGHY4BoIMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "adm-zip": "~0.5.x", - "fs-extra": "^11.2.0", - "ini": "^4.1.3", - "minimist": "^1.2.8", - "xml2js": "^0.6.2" - }, - "bin": { - "firefox-profile": "lib/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/first-chunk-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-3.0.0.tgz", - "integrity": "sha512-LNRvR4hr/S8cXXkIY5pTgVP7L3tq6LlYWcg9nWBuW7o1NMxKZo6oOVa/6GIekMGI0Iw7uC+HWimMe9u/VAeKqw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true, - "license": "ISC" - }, - "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fx-runner": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/fx-runner/-/fx-runner-1.4.0.tgz", - "integrity": "sha512-rci1g6U0rdTg6bAaBboP7XdRu01dzTAaKXxFf+PUqGuCv6Xu7o8NZdY1D5MvKGIjb6EdS1g3VlXOgksir1uGkg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "commander": "2.9.0", - "shell-quote": "1.7.3", - "spawn-sync": "1.0.15", - "when": "3.7.7", - "which": "1.2.4", - "winreg": "0.0.12" - }, - "bin": { - "fx-runner": "bin/fx-runner" - } - }, - "node_modules/fx-runner/node_modules/commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-readlink": ">= 1.0.0" - }, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/fx-runner/node_modules/isexe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", - "integrity": "sha512-d2eJzK691yZwPHcv1LbeAOa91yMJ9QmfTgSO1oXB65ezVhXQsxBac2vEB4bMVms9cGzaA99n6V2viHMq82VLDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fx-runner/node_modules/which": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.4.tgz", - "integrity": "sha512-zDRAqDSBudazdfM9zpiI30Fu9ve47htYXcGi3ln0wfKu2a7SmrT6F3VDoYONu//48V8Vz4TdCRNPjtvyRO3yBA==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-absolute": "^0.1.7", - "isexe": "^1.1.1" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-directory/node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "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==", - "dev": true, - "license": "ISC" - }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", - "dev": true, - "license": "MIT" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", - "dev": true, - "license": "MIT" - }, - "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/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "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/image-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", - "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=16.x" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" - }, - "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/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/is-absolute": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "integrity": "sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-relative": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/is-in-ci": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-1.0.0.tgz", - "integrity": "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==", - "dev": true, - "license": "MIT", - "bin": { - "is-in-ci": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-installed-globally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.0.tgz", - "integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-directory": "^4.0.1", - "is-path-inside": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-installed-globally/node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", - "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-relative": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "integrity": "sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "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/jose": { - "version": "5.9.6", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz", - "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "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/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-merge-patch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-merge-patch/-/json-merge-patch-1.0.2.tgz", - "integrity": "sha512-M6Vp2GN9L7cfuMXiWOmHj9bEFbeC250iVtcKQbqVgEsDVYnIsrNsbU+h/Y/PkbBQCtEa4Bez+Ebv0zfbC8ObLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "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/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "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/ky": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/ky/-/ky-1.7.5.tgz", - "integrity": "sha512-HzhziW6sc5m0pwi5M196+7cEBtbt0lCYi67wNsiwMUmz833wloE0gbzJPWKs1gliFKQb34huItDQX97LyOdPdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, - "node_modules/latest-version": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", - "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", - "dev": true, - "license": "MIT", - "dependencies": { - "package-json": "^10.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lighthouse-logger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-2.0.1.tgz", - "integrity": "sha512-ioBrW3s2i97noEmnXxmUq7cjIcVRjT5HBpAYy8zE11CxU9HqlWHHeRxfeN1tn8F7OEMVPIC9x1f8t3Z7US9ehQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^2.6.9", - "marky": "^1.2.2" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "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/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/marky": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", - "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/multimatch": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-6.0.0.tgz", - "integrity": "sha512-I7tSVxHGPlmPN/enE3mS1aOSo6bWBfls+3HmuEeCUBCE7gWnm3cBXCBkpurzFjVRwC6Kld8lLaZ1Iv5vOcjvcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "^3.0.5", - "array-differ": "^4.0.0", - "array-union": "^3.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-notifier": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-10.0.1.tgz", - "integrity": "sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "growly": "^1.3.0", - "is-wsl": "^2.2.0", - "semver": "^7.3.5", - "shellwords": "^0.1.1", - "uuid": "^8.3.2", - "which": "^2.0.2" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/os-shim": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==", - "dev": true, - "engines": { - "node": ">= 0.4.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/package-json": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", - "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ky": "^1.2.0", - "registry-auth-token": "^5.0.2", - "registry-url": "^6.0.1", - "semver": "^7.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "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/parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-json/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.5.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", - "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "domhandler": "^5.0.3", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "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-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/pino": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.4.0.tgz", - "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==", - "dev": true, - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^4.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/pino-abstract-transport/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", - "dev": true, - "license": "MIT" - }, - "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/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/process-warning": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", - "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/promise-toolbox": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/promise-toolbox/-/promise-toolbox-0.21.0.tgz", - "integrity": "sha512-NV8aTmpwrZv+Iys54sSFOBx3tuVaOBvvrft5PNppnxy9xpU/akHbaWIril22AB22zaPgrgwKdD0KsrM0ptUtpg==", - "dev": true, - "license": "ISC", - "dependencies": { - "make-error": "^1.3.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true, - "license": "ISC" - }, - "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/pupa": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", - "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-goat": "^4.0.0" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.3" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "dev": true, - "license": "MIT" - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" - }, - "node_modules/registry-auth-token": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", - "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "dev": true, - "license": "ISC" - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "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/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true, - "license": "MIT" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/sonic-boom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", - "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", - "dev": true, - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "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/spawn-sync": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "concat-stream": "^1.4.7", - "os-shim": "^0.1.2" - } - }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-5.0.0.tgz", - "integrity": "sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-bom-buf": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz", - "integrity": "sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-utf8": "^0.2.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom-stream": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-4.0.0.tgz", - "integrity": "sha512-0ApK3iAkHv6WbgLICw/J4nhwHeDZsBxIIsOD+gHgZICL6SeJ0S9f/WZqemka9cjkTyMN5geId6e8U5WGFAn3cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "first-chunk-stream": "^3.0.0", - "strip-bom-buf": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz", - "integrity": "sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stubborn-fs": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", - "integrity": "sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==", - "dev": true - }, - "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/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "dev": true, - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, - "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/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/update-notifier": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.3.1.tgz", - "integrity": "sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boxen": "^8.0.1", - "chalk": "^5.3.0", - "configstore": "^7.0.0", - "is-in-ci": "^1.0.0", - "is-installed-globally": "^1.0.0", - "is-npm": "^6.0.0", - "latest-version": "^9.0.0", - "pupa": "^3.1.0", - "semver": "^7.6.3", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "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/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-ext": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/web-ext/-/web-ext-8.4.0.tgz", - "integrity": "sha512-zO0GNacJeqw3fwbBvgHC2G8reieyN+oCKiMQepX3iv2fm9KEBqg1gdbcdEvi7edfj+gjgxyXhVlFcHIvcEM2Cg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "@babel/runtime": "7.26.7", - "@devicefarmer/adbkit": "3.3.8", - "addons-linter": "7.8.0", - "camelcase": "8.0.0", - "chrome-launcher": "1.1.2", - "debounce": "1.2.1", - "decamelize": "6.0.0", - "es6-error": "4.1.1", - "firefox-profile": "4.7.0", - "fx-runner": "1.4.0", - "https-proxy-agent": "^7.0.0", - "jose": "5.9.6", - "jszip": "3.10.1", - "multimatch": "6.0.0", - "node-notifier": "10.0.1", - "open": "9.1.0", - "parse-json": "7.1.1", - "pino": "9.4.0", - "promise-toolbox": "0.21.0", - "source-map-support": "0.5.21", - "strip-bom": "5.0.0", - "strip-json-comments": "5.0.1", - "tmp": "0.2.3", - "update-notifier": "7.3.1", - "watchpack": "2.4.2", - "ws": "8.18.0", - "yargs": "17.7.2", - "zip-dir": "2.0.0" - }, - "bin": { - "web-ext": "bin/web-ext.js" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - } - }, - "node_modules/when": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.7.tgz", - "integrity": "sha512-9lFZp/KHoqH6bPKjbWqa+3Dg/K/r2v0X/3/G2x4DBGchVS2QX2VXL3cZV994WQVnTM1/PD71Az25nAzryEUugw==", - "dev": true, - "license": "MIT" - }, - "node_modules/when-exit": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.4.tgz", - "integrity": "sha512-4rnvd3A1t16PWzrBUcSDZqcAmsUIy4minDXT/CZ8F2mVDgd65i4Aalimgz1aQkRGU0iH5eT5+6Rx2TK8o443Pg==", - "dev": true, - "license": "MIT" - }, - "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/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/winreg": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/winreg/-/winreg-0.0.12.tgz", - "integrity": "sha512-typ/+JRmi7RqP1NanzFULK36vczznSNN8kWVA9vIqXyv8GhghUlwhGp1Xj3Nms1FsPcNnsQrJOR10N58/nQ9hQ==", - "dev": true, - "license": "BSD" - }, - "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/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dev": true, - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "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" - } - }, - "node_modules/zip-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/zip-dir/-/zip-dir-2.0.0.tgz", - "integrity": "sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^3.2.0", - "jszip": "^3.2.2" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 6580df2..0000000 --- a/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "transparent-zen", - "version": "0.1.10", - "description": "A browser extension for Zen Browser to inject custom styles to make your favorite websites transparent", - "scripts": { - "build": "web-ext build --config web-ext-config.mjs", - "run": "web-ext run --config web-ext-config.mjs", - "sign": "web-ext sign --config web-ext-config.mjs", - "lint": "web-ext lint --config web-ext-config.mjs" - }, - "author": "FrostyBiscuit", - "license": "MIT", - "devDependencies": { - "dotenv": "^16.4.7", - "web-ext": "^8.4.0" - } -} diff --git a/popup/popup.css b/popup/popup.css index f1d23e4..78d9434 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -60,14 +60,14 @@ body { font-size: 30px;
}
-#header-container{
+#header-container {
display: flex;
justify-content: space-between;
flex-direction: column;
width: 100%;
}
-.miniheader{
+.miniheader {
margin-top: 2px;
font-size: 11px;
display: flex;
@@ -85,11 +85,59 @@ body { text-decoration: underline;
}
-/* What's New Button */
+/* Header buttons container */
+.header-buttons {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+/* Icon button styles */
+.icon-button {
+ background: none;
+ border: none;
+ color: white;
+ font-size: 18px;
+ cursor: pointer;
+ padding: 5px;
+ border-radius: 50%;
+ transition: all 0.2s ease;
+ width: 32px;
+ height: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.icon-button:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+ transform: scale(1.1);
+}
+
+.icon-button::after {
+ content: attr(title);
+ position: absolute;
+ bottom: -25px;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.7);
+ color: white;
+ padding: 3px 8px;
+ border-radius: 4px;
+ font-size: 10px;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity 0.2s ease, visibility 0.2s ease;
+ pointer-events: none;
+ white-space: nowrap;
+}
+
+.icon-button:hover::after {
+ opacity: 1;
+ visibility: visible;
+}
+
+/* What's New Button - make it use icon-button styles */
.whats-new-button {
- /* position: absolute;
- top: 16px;
- right: 16px; */
background: none;
border: none;
color: white;
@@ -110,6 +158,25 @@ body { transform: scale(1.1);
}
+/* Add glow pulse animation for the What's New button emoji */
+@keyframes glowPulse {
+ 0% {
+ text-shadow: 0 0 0 rgba(255, 255, 255, 0);
+ }
+ 50% {
+ text-shadow: 0 0 8px rgba(255, 255, 255, 0.8),
+ 0 0 12px rgba(249, 135, 100, 0.6);
+ }
+ 100% {
+ text-shadow: 0 0 0 rgba(255, 255, 255, 0);
+ }
+}
+
+/* Apply the animation to the What's New button */
+.whats-new-button {
+ animation: glowPulse 2s ease-in-out infinite;
+}
+
.whats-new-button::after {
content: "What's New";
position: absolute;
@@ -145,7 +212,7 @@ body { display: flex;
align-items: center;
gap: 12px;
- margin-bottom: 8px;
+ margin-bottom: 2px;
}
/* Current site toggle styling */
@@ -502,6 +569,11 @@ input:checked + .slider:before { margin-bottom: 16px;
}
+/* Make forcing container collapsible */
+.forcing-container.collapsed {
+ display: none;
+}
+
.warning {
color: var(--warning-color);
margin-top: 8px;
@@ -554,3 +626,21 @@ input:checked + .slider:before { .toggle-switch.disabled input:checked + .slider {
background-color: rgba(249, 135, 100, 0.5);
}
+
+.site-domain {
+ color: var(--accent-color);
+ font-weight: 600;
+ max-width: 180px;
+ display: inline-block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: bottom;
+ margin-right: 4px;
+}
+
+/* Update the reload button styles to fit in the features container */
+.features-container #reload {
+ margin-top: 12px;
+ width: 100%;
+}
diff --git a/popup/popup.html b/popup/popup.html index 9d8d042..d16cb88 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -14,7 +14,7 @@ <header class="app-header"> <div id="header-container"> <div class="logo-container"> - <img src="../assets/images/logo_48.png" alt="ZenInternet Logo" class="logo-img"> + <img src="../assets/images/logo.png" alt="ZenInternet Logo" class="logo-img"> <h1 class="app-title">Zen Internet</h1> </div> <div class="miniheader"> @@ -22,30 +22,53 @@ <div class="author">by <a href="https://www.sameerasw.com/" target="_blank">@sameerasw</a></div> </div> </div> - <button id="whats-new" class="whats-new-button" title="What's New">✨</button> + <div class="header-buttons"> + <button id="how-to-use" class="icon-button" title="How to use?">🤔</button> + <button id="whats-new" class="whats-new-button" title="What's New">✨</button> + </div> </header> <main class="app-content"> - <div class="toggle-container features-container"> - <label class="toggle-switch"> - <input type="checkbox" id="enable-styling"> - <span class="slider round"></span> - </label> - <span class="toggle-label">Enable Styling</span> + <div class="features-container"> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="enable-styling"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Global Styling</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="whitelist-style-mode"> + <span class="slider round"></span> + </label> + <span id="whitelist-style-mode-label" class="toggle-label">Blacklist Mode</span> + </div> + <!-- Moved reload button here --> + <button id="reload" class="action-button secondary"> + Reload to apply <i class="fas fa-sync-alt"></i> + </button> </div> <!-- Current Site Features Section --> <div id="current-site-features" class="features-container"> <button class="collapsible-button" id="toggle-features"> - <span>Current Site Features</span> + <span id="current-site-label"> + <span id="site-domain" class="site-domain"></span> + <span>Features</span> + </span> <i class="fas fa-chevron-down"></i> </button> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="skip-theming"> + <span class="slider round"></span> + </label> + <span id="site-style-toggle-label" class="toggle-label">Skip Styling for this Site</span> + </div> <div id="current-site-toggles" class="features-list collapsed"></div> <div class="actions" id="current-site-actions"> - <!-- reload botton --> - <button id="reload" class="action-button secondary"> - Reload to apply <i class="fas fa-sync-alt"></i> - </button> + <!-- Reload button was here, now moved above --> </div> </div> @@ -63,27 +86,41 @@ <span class="toggle-label">Auto Update Styles</span> </div> <div id="last-fetched-time" class="last-fetched-time"></div> - <div class="forcing-container"> - <div class="toggle-container"> - <label class="toggle-switch"> - <input type="checkbox" id="force-styling"> - <span class="slider round"></span> - </label> - <span class="toggle-label">Force Styling</span> - </div> - <div class="toggle-container"> - <label class="toggle-switch"> - <input type="checkbox" id="whitelist-mode"> - <span class="slider round"></span> - </label> - <span id="whitelist-mode-label" class="toggle-label">Blacklist Mode</span> - </div> - <div class="toggle-container"> - <label class="toggle-switch"> - <input type="checkbox" id="skip-force-theming"> - <span class="slider round"></span> - </label> - <span id="site-toggle-label" class="toggle-label">Skip Forcing for this Site</span> + + <div class="features-container"> + <button class="collapsible-button" id="toggle-forcing"> + <span>Force Styling Settings</span> + <i class="fas fa-chevron-down"></i> + </button> + <div id="forcing-content" class="forcing-container collapsed"> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="force-styling"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Force Styling</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="whitelist-mode"> + <span class="slider round"></span> + </label> + <span id="whitelist-mode-label" class="toggle-label">Blacklist Mode</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="skip-force-theming"> + <span class="slider round"></span> + </label> + <span id="site-toggle-label" class="toggle-label">Skip Forcing for this Site</span> + </div> + <div class="toggle-container"> + <label class="toggle-switch"> + <input type="checkbox" id="fallback-background"> + <span class="slider round"></span> + </label> + <span class="toggle-label">Fallback Background</span> + </div> </div> </div> diff --git a/popup/popup.js b/popup/popup.js index c353182..4515856 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -1,5 +1,34 @@ let logging = false; let SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; +let SKIP_THEMING_KEY = "skipThemingList"; +let FALLBACK_BACKGROUND_KEY = "fallbackBackgroundList"; + +// Default settings to use when values are missing +const DEFAULT_SETTINGS = { + enableStyling: true, // Enable styling globally + autoUpdate: true, // Auto-update styles + forceStyling: false, // Force styling on sites without themes + whitelistMode: false, // Use blacklist mode by default for force styling + whitelistStyleMode: false, // Use blacklist mode by default for regular styling + disableTransparency: false, // Don't disable transparency by default + disableHover: false, // Don't disable hover effects by default + disableFooter: false, // Don't disable footers by default + fallbackBackgroundList: [], // Empty array for fallback background sites +}; + +// Helper function to ensure all required settings exist +function ensureDefaultSettings(settings = {}) { + const result = { ...settings }; + + // Apply default values for any missing settings + for (const [key, defaultValue] of Object.entries(DEFAULT_SETTINGS)) { + if (result[key] === undefined) { + result[key] = defaultValue; + } + } + + return result; +} // Helper function to normalize hostnames by removing www. prefix function normalizeHostname(hostname) { @@ -11,6 +40,13 @@ new (class ExtensionPopup { globalSettings = {}; siteSettings = {}; enableStylingSwitch = document.getElementById("enable-styling"); + whitelistStylingModeSwitch = document.getElementById("whitelist-style-mode"); + whitelistStylingModeLabel = document.getElementById( + "whitelist-style-mode-label" + ); + skipThemingSwitch = document.getElementById("skip-theming"); + siteStyleToggleLabel = document.getElementById("site-style-toggle-label"); + skipThemingList = []; refetchCSSButton = document.getElementById("refetch-css"); websitesList = document.getElementById("websites-list"); currentSiteFeatures = document.getElementById("current-site-toggles"); @@ -27,15 +63,22 @@ new (class ExtensionPopup { reloadButton = document.getElementById("reload"); modeIndicator = document.getElementById("mode-indicator"); whatsNewButton = document.getElementById("whats-new"); + howToUseButton = document.getElementById("how-to-use"); + fallbackBackgroundSwitch = document.getElementById("fallback-background"); + fallbackBackgroundList = []; constructor() { if (logging) console.log("Initializing ExtensionPopup"); // Load settings and initialize the popup this.loadSettings().then(() => { this.loadSkipForceThemingList().then(() => { - this.getCurrentTabInfo().then(() => { - this.restoreSettings(); - this.bindEvents(); + this.loadSkipThemingList().then(() => { + this.loadFallbackBackgroundList().then(() => { + this.getCurrentTabInfo().then(() => { + this.restoreSettings(); + this.bindEvents(); + }); + }); }); }); }); @@ -61,14 +104,27 @@ new (class ExtensionPopup { .getElementById("toggle-features") ?.addEventListener("click", this.toggleFeatures.bind(this)); + // Add toggle forcing button event listener + document + .getElementById("toggle-forcing") + ?.addEventListener("click", this.toggleForcing.bind(this)); + this.whitelistModeSwitch.addEventListener( "change", this.handleWhitelistModeChange.bind(this) ); + this.whitelistStylingModeSwitch.addEventListener( + "change", + this.handleWhitelistStyleModeChange.bind(this) + ); + // Add event listener for the "What's New" button this.whatsNewButton.addEventListener("click", this.openWhatsNew.bind(this)); + // Add event listener for the "How to use?" button + this.howToUseButton.addEventListener("click", this.openHowToUse.bind(this)); + // Add event listener for the data viewer button document.getElementById("view-data")?.addEventListener("click", () => { browser.tabs.create({ @@ -103,6 +159,14 @@ new (class ExtensionPopup { this.normalizedCurrentSiteHostname, ")" ); + + // Update the site label with current hostname (without www.) + const siteDomainElement = document.getElementById("site-domain"); + if (siteDomainElement) { + const displayDomain = normalizeHostname(this.currentSiteHostname); + siteDomainElement.textContent = displayDomain; + siteDomainElement.title = displayDomain; // Add full domain as tooltip for long domains + } } } catch (error) { console.error("Error getting current tab info:", error); @@ -128,6 +192,14 @@ new (class ExtensionPopup { this.saveSkipForceThemingList(); }); + this.skipThemingSwitch.addEventListener("change", () => { + this.saveSkipThemingList(); + }); + + this.fallbackBackgroundSwitch.addEventListener("change", () => { + this.saveFallbackBackgroundList(); + }); + this.reloadButton.addEventListener("click", this.reloadPage.bind(this)); } @@ -140,15 +212,25 @@ new (class ExtensionPopup { this.forceStylingSwitch.checked = this.globalSettings.forceStyling ?? false; this.whitelistModeSwitch.checked = this.globalSettings.whitelistMode ?? false; + this.whitelistStylingModeSwitch.checked = + this.globalSettings.whitelistStyleMode ?? false; this.updateModeLabels(); // In whitelist mode, checked means "include this site" // In blacklist mode, checked means "skip this site" - const isInList = this.skipForceThemingList.includes( - this.currentSiteHostname + this.skipForceThemingSwitch.checked = this.skipForceThemingList.includes( + normalizeHostname(this.currentSiteHostname) + ); + + this.skipThemingSwitch.checked = this.skipThemingList.includes( + normalizeHostname(this.currentSiteHostname) ); - this.skipForceThemingSwitch.checked = isInList; + + this.fallbackBackgroundSwitch.checked = + this.fallbackBackgroundList.includes( + normalizeHostname(this.currentSiteHostname) + ); this.loadCurrentSiteFeatures(); } @@ -159,12 +241,22 @@ new (class ExtensionPopup { const globalData = await browser.storage.local.get( this.BROWSER_STORAGE_KEY ); - this.globalSettings = globalData[this.BROWSER_STORAGE_KEY] || { - enableStyling: true, - autoUpdate: false, - lastFetchedTime: null, - forceStyling: false, - }; + + // Apply defaults for any missing settings + this.globalSettings = ensureDefaultSettings( + globalData[this.BROWSER_STORAGE_KEY] || {} + ); + + // Save back any applied defaults + if ( + JSON.stringify(this.globalSettings) !== + JSON.stringify(globalData[this.BROWSER_STORAGE_KEY]) + ) { + await browser.storage.local.set({ + [this.BROWSER_STORAGE_KEY]: this.globalSettings, + }); + if (logging) console.log("Applied missing default settings"); + } // Load site-specific settings if on a specific site if (this.currentSiteHostname) { @@ -204,6 +296,8 @@ new (class ExtensionPopup { this.globalSettings.autoUpdate = this.autoUpdateSwitch.checked; this.globalSettings.forceStyling = this.forceStylingSwitch.checked; this.globalSettings.whitelistMode = this.whitelistModeSwitch.checked; + this.globalSettings.whitelistStyleMode = + this.whitelistStylingModeSwitch.checked; browser.storage.local .set({ @@ -248,15 +342,47 @@ new (class ExtensionPopup { async loadSkipForceThemingList() { const data = await browser.storage.local.get(SKIP_FORCE_THEMING_KEY); this.skipForceThemingList = data[SKIP_FORCE_THEMING_KEY] || []; + + // Initialize with empty array if missing + if (!data[SKIP_FORCE_THEMING_KEY]) { + await browser.storage.local.set({ [SKIP_FORCE_THEMING_KEY]: [] }); + if (logging) console.log("Initialized empty skip force theming list"); + } + } + + async loadSkipThemingList() { + const data = await browser.storage.local.get(SKIP_THEMING_KEY); + this.skipThemingList = data[SKIP_THEMING_KEY] || []; + + // Initialize with empty array if missing + if (!data[SKIP_THEMING_KEY]) { + await browser.storage.local.set({ [SKIP_THEMING_KEY]: [] }); + if (logging) console.log("Initialized empty skip theming list"); + } + } + + async loadFallbackBackgroundList() { + const data = await browser.storage.local.get(FALLBACK_BACKGROUND_KEY); + this.fallbackBackgroundList = data[FALLBACK_BACKGROUND_KEY] || []; + + // Initialize with empty array if missing + if (!data[FALLBACK_BACKGROUND_KEY]) { + await browser.storage.local.set({ [FALLBACK_BACKGROUND_KEY]: [] }); + if (logging) console.log("Initialized empty fallback background list"); + } } saveSkipForceThemingList() { const isChecked = this.skipForceThemingSwitch.checked; - const index = this.skipForceThemingList.indexOf(this.currentSiteHostname); + const index = this.skipForceThemingList.indexOf( + normalizeHostname(this.currentSiteHostname) + ); if (isChecked && index === -1) { // Add to the list (whitelist: include, blacklist: skip) - this.skipForceThemingList.push(this.currentSiteHostname); + this.skipForceThemingList.push( + normalizeHostname(this.currentSiteHostname) + ); } else if (!isChecked && index !== -1) { // Remove from the list (whitelist: exclude, blacklist: include) this.skipForceThemingList.splice(index, 1); @@ -271,6 +397,54 @@ new (class ExtensionPopup { }); } + saveSkipThemingList() { + const isChecked = this.skipThemingSwitch.checked; + const index = this.skipThemingList.indexOf( + normalizeHostname(this.currentSiteHostname) + ); + + if (isChecked && index === -1) { + // Add to the list (whitelist: include, blacklist: skip) + this.skipThemingList.push(normalizeHostname(this.currentSiteHostname)); + } else if (!isChecked && index !== -1) { + // Remove from the list (whitelist: exclude, blacklist: include) + this.skipThemingList.splice(index, 1); + } + + browser.storage.local + .set({ + [SKIP_THEMING_KEY]: this.skipThemingList, + }) + .then(() => { + this.updateActiveTabStyling(); + }); + } + + saveFallbackBackgroundList() { + const isChecked = this.fallbackBackgroundSwitch.checked; + const index = this.fallbackBackgroundList.indexOf( + normalizeHostname(this.currentSiteHostname) + ); + + if (isChecked && index === -1) { + // Add to the list + this.fallbackBackgroundList.push( + normalizeHostname(this.currentSiteHostname) + ); + } else if (!isChecked && index !== -1) { + // Remove from the list + this.fallbackBackgroundList.splice(index, 1); + } + + browser.storage.local + .set({ + [FALLBACK_BACKGROUND_KEY]: this.fallbackBackgroundList, + }) + .then(() => { + this.updateActiveTabStyling(); + }); + } + async loadCurrentSiteFeatures() { if (logging) console.log("loadCurrentSiteFeatures called"); try { @@ -335,6 +509,26 @@ new (class ExtensionPopup { } } + // Set the forcing section's initial collapsed state + const forcingContent = document.getElementById("forcing-content"); + const toggleForcingButton = document.getElementById("toggle-forcing"); + + if (hasSpecificTheme) { + // We have a specific theme, collapse the forcing section + forcingContent.classList.add("collapsed"); + if (toggleForcingButton) { + const icon = toggleForcingButton.querySelector("i"); + if (icon) icon.className = "fas fa-chevron-down"; + } + } else { + // No specific theme found, expand the forcing section + forcingContent.classList.remove("collapsed"); + if (toggleForcingButton) { + const icon = toggleForcingButton.querySelector("i"); + if (icon) icon.className = "fas fa-chevron-up"; + } + } + // Disable the force styling toggle if we found a theme for this site if (hasSpecificTheme) { // We found a specific theme for this site, no need for force styling @@ -412,6 +606,8 @@ new (class ExtensionPopup { // Check if transparency is globally disabled const isTransparencyDisabled = this.globalSettings.disableTransparency === true; + const isHoverDisabled = this.globalSettings.disableHover === true; + const isFooterDisabled = this.globalSettings.disableFooter === true; for (const [feature, css] of Object.entries(features)) { const displayFeatureName = feature.includes("-") @@ -422,7 +618,13 @@ new (class ExtensionPopup { const isTransparencyFeature = feature .toLowerCase() .includes("transparency"); - const isOverridden = isTransparencyDisabled && isTransparencyFeature; + const isHoverFeature = feature.toLowerCase().includes("hover"); + const isFooterFeature = feature.toLowerCase().includes("footer"); + + const isOverridden = + (isTransparencyDisabled && isTransparencyFeature) || + (isHoverDisabled && isHoverFeature) || + (isFooterDisabled && isFooterFeature); const featureToggle = document.createElement("div"); featureToggle.className = "feature-toggle"; @@ -444,7 +646,7 @@ new (class ExtensionPopup { featureToggle.innerHTML = toggleHTML; - // If this is a transparency feature and it's disabled globally, add a class + // If this feature is overridden by global settings, add a class if (isOverridden) { featureToggle.classList.add("overridden-feature"); } @@ -525,28 +727,73 @@ new (class ExtensionPopup { if (logging) console.log("refetchCSS called"); this.refetchCSSButton.textContent = "Fetching..."; try { - const response = await fetch( - "https://sameerasw.github.io/my-internet/styles.json", - { - headers: { - "Cache-Control": "no-cache", - }, - } + // Get the repository URL from storage or use the default one + const DEFAULT_REPOSITORY_URL = + "https://sameerasw.github.io/my-internet/styles.json"; + const repoUrlData = await browser.storage.local.get( + "stylesRepositoryUrl" ); - if (!response.ok) throw new Error("Failed to fetch styles.json"); + const repositoryUrl = + repoUrlData.stylesRepositoryUrl || DEFAULT_REPOSITORY_URL; + + console.log("Fetching styles from:", repositoryUrl); + + const response = await fetch(repositoryUrl, { + headers: { + "Cache-Control": "no-cache", + }, + }); + if (!response.ok) + throw new Error(`Failed to fetch styles (Status: ${response.status})`); const styles = await response.json(); await browser.storage.local.set({ styles }); - await browser.storage.local.set({ lastFetchedTime: Date.now() }); + + // Check if we need to initialize default settings + const settingsData = await browser.storage.local.get( + this.BROWSER_STORAGE_KEY + ); + if (!settingsData[this.BROWSER_STORAGE_KEY]) { + // Initialize default settings if none exist + const defaultSettings = { + enableStyling: true, + autoUpdate: true, + forceStyling: false, + whitelistMode: false, + whitelistStyleMode: false, + lastFetchedTime: Date.now(), + }; + + // Save default settings + await browser.storage.local.set({ + [this.BROWSER_STORAGE_KEY]: defaultSettings, + }); + console.info("Initialized default settings during first fetch"); + + // Update our internal global settings + this.globalSettings = defaultSettings; + + // Update UI to reflect these defaults + this.enableStylingSwitch.checked = true; + this.autoUpdateSwitch.checked = false; + this.forceStylingSwitch.checked = false; + this.whitelistModeSwitch.checked = false; + this.whitelistStylingModeSwitch.checked = false; + + // Update labels + this.updateModeLabels(); + } else { + // Just update the lastFetchedTime + await browser.storage.local.set({ lastFetchedTime: Date.now() }); + } this.loadCurrentSiteFeatures(); - // this.loadWebsitesList(); this.updateActiveTabStyling(); this.refetchCSSButton.textContent = "Done!"; setTimeout(() => { this.refetchCSSButton.textContent = "Refetch latest styles"; }, 2000); - console.info("All styles refetched and updated from GitHub." + styles); + console.info(`All styles refetched and updated from ${repositoryUrl}`); this.displayLastFetchedTime(); } catch (error) { this.refetchCSSButton.textContent = "Error!"; @@ -554,6 +801,7 @@ new (class ExtensionPopup { this.refetchCSSButton.textContent = "Refetch latest styles"; }, 2000); console.error("Error refetching styles:", error); + alert(`Error fetching styles: ${error.message}`); } } @@ -734,6 +982,7 @@ new (class ExtensionPopup { shouldApplyCSS(hostname) { if (logging) console.log("shouldApplyCSS called with", hostname); + // Use default if not explicitly set return this.globalSettings.enableStyling !== false; } @@ -755,10 +1004,11 @@ new (class ExtensionPopup { displayLastFetchedTime() { if (logging) console.log("displayLastFetchedTime called"); - browser.storage.local.get("lastFetchedTime").then((result) => { - if (result.lastFetchedTime) { + browser.storage.local.get(this.BROWSER_STORAGE_KEY).then((result) => { + const settings = result[this.BROWSER_STORAGE_KEY] || {}; + if (settings.lastFetchedTime) { this.lastFetchedTime.textContent = `Last fetched: ${new Date( - result.lastFetchedTime + settings.lastFetchedTime ).toLocaleString()}`; } }); @@ -786,6 +1036,11 @@ new (class ExtensionPopup { this.saveSettings(); } + handleWhitelistStyleModeChange() { + this.updateModeLabels(); + this.saveSettings(); + } + updateModeIndicator() { if (this.whitelistModeSwitch.checked) { this.modeIndicator.textContent = @@ -813,6 +1068,14 @@ new (class ExtensionPopup { this.whitelistModeLabel.textContent = "Blacklist Mode"; this.siteToggleLabel.textContent = "Skip Forcing for this Site"; } + + if (this.whitelistStylingModeSwitch.checked) { + this.whitelistStylingModeLabel.textContent = "Whitelist Mode"; + this.siteStyleToggleLabel.textContent = "Enable for this Site"; + } else { + this.whitelistStylingModeLabel.textContent = "Blacklist Mode"; + this.siteStyleToggleLabel.textContent = "Skip Styling for this Site"; + } } // Open the What's New page @@ -822,6 +1085,13 @@ new (class ExtensionPopup { }); } + // Open the How to Use guide + openHowToUse() { + browser.tabs.create({ + url: "https://www.sameerasw.com/zen", + }); + } + // Toggle features section visibility toggleFeatures() { const featuresList = document.getElementById("current-site-toggles"); @@ -844,4 +1114,20 @@ new (class ExtensionPopup { icon.className = "fas fa-chevron-up"; } } + + // Toggle forcing section visibility + toggleForcing() { + const forcingContent = document.getElementById("forcing-content"); + const toggleButton = document.getElementById("toggle-forcing"); + + forcingContent.classList.toggle("collapsed"); + + // Update the icon + const icon = toggleButton.querySelector("i"); + if (forcingContent.classList.contains("collapsed")) { + icon.className = "fas fa-chevron-down"; + } else { + icon.className = "fas fa-chevron-up"; + } + } })(); diff --git a/shared/constants.js b/shared/constants.js index 132bbec..03c7bc3 100644 --- a/shared/constants.js +++ b/shared/constants.js @@ -1,2 +1,3 @@ export const BROWSER_STORAGE_KEY = "transparentZenSettings"; export const SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; +export const FALLBACK_BACKGROUND_KEY = "fallbackBackgroundList"; diff --git a/shared/defaults.js b/shared/defaults.js new file mode 100644 index 0000000..db637fc --- /dev/null +++ b/shared/defaults.js @@ -0,0 +1,34 @@ +/** + * Default settings for Zen Internet extension + * These defaults are used when settings are missing or undefined + */ + +export const DEFAULT_SETTINGS = { + enableStyling: true, // Enable styling globally + autoUpdate: true, // Auto-update styles + forceStyling: false, // Force styling on sites without themes + whitelistMode: false, // Use blacklist mode by default for force styling + whitelistStyleMode: false, // Use blacklist mode by default for regular styling + disableTransparency: false, // Don't disable transparency by default + disableHover: false, // Don't disable hover effects by default + disableFooter: false, // Don't disable footers by default + fallbackBackgroundList: [], // Empty array for fallback background sites +}; + +/** + * Ensures all required settings are present with default values + * @param {Object} settings - Current settings object + * @returns {Object} - Settings object with defaults applied where needed + */ +export function ensureDefaultSettings(settings = {}) { + const result = { ...settings }; + + // Apply default values for any missing settings + for (const [key, defaultValue] of Object.entries(DEFAULT_SETTINGS)) { + if (result[key] === undefined) { + result[key] = defaultValue; + } + } + + return result; +} diff --git a/styling/README.md b/styling/README.md deleted file mode 100644 index dc3847c..0000000 --- a/styling/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Styling Directory - -This directory is used to store cached CSS files for faster injection. -The extension will generate and manage files in this directory automatically. diff --git a/web-ext-config.mjs b/web-ext-config.mjs deleted file mode 100644 index a1d7916..0000000 --- a/web-ext-config.mjs +++ /dev/null @@ -1,19 +0,0 @@ -import "dotenv/config";
-
-export default {
- artifactsDir: "builds",
- ignoreFiles: [
- "node_modules/",
- ".git/",
- ".gitignore",
- ".env"
- ],
- build: {
- overwriteDest: true
- },
- sign: {
- apiKey: process.env.FIREFOX_API_KEY,
- apiSecret: process.env.FIREFOX_API_SECRET,
- channel: "listed"
- }
-};
\ No newline at end of file |