diff --git a/.output/chrome-mv3/background.js b/.output/chrome-mv3/background.js
new file mode 100644
index 0000000..31af0ff
--- /dev/null
+++ b/.output/chrome-mv3/background.js
@@ -0,0 +1 @@
+var background=(function(){"use strict";const t=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome;function i(r){return r==null||typeof r=="function"?{main:r}:r}const a=i(()=>{console.log("Claude Conversation Exporter background script loaded"),t.runtime.onInstalled.addListener(()=>{console.log("Claude Conversation Exporter installed"),(async()=>{try{const r=await t.tabs.query({url:"https://claude.ai/*"});for(const e of r)if(e.id)try{await t.scripting.executeScript({target:{tabId:e.id},files:["content-scripts/content.js"]})}catch(n){console.log("Could not inject into tab",e.id,n)}}catch(r){console.error("Error querying or injecting tabs:",r)}})()}),t.runtime.onMessage.addListener((r,e)=>r.action==="ensureContentScript"?(async()=>{try{const c=(await t.tabs.query({active:!0,currentWindow:!0}))[0];return c?.id?(await t.scripting.executeScript({target:{tabId:c.id},files:["content-scripts/content.js"]}),{success:!0}):{success:!1,error:"No active tab found"}}catch(n){return{success:!1,error:n instanceof Error?n.message:"Unknown error"}}})():!1)});function d(){}function o(r,...e){}const u={debug:(...r)=>o(console.debug,...r),log:(...r)=>o(console.log,...r),warn:(...r)=>o(console.warn,...r),error:(...r)=>o(console.error,...r)};let s;try{s=a.main(),s instanceof Promise&&console.warn("The background's main() function return a promise, but it must be synchronous")}catch(r){throw u.error("The background crashed on startup!"),r}return s})();
diff --git a/.output/chrome-mv3/chunks/popup-BzajcGsb.js b/.output/chrome-mv3/chunks/popup-BzajcGsb.js
new file mode 100644
index 0000000..0d1f308
--- /dev/null
+++ b/.output/chrome-mv3/chunks/popup-BzajcGsb.js
@@ -0,0 +1 @@
+(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))c(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&c(o)}).observe(document,{childList:!0,subtree:!0});function t(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function c(r){if(r.ep)return;r.ep=!0;const s=t(r);fetch(r.href,s)}})();try{}catch(n){console.error("[wxt] Failed to initialize plugins",n)}const p=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome,u=p;async function f(){return(await u.storage.sync.get(["organizationId"])).organizationId}async function g(){const e=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!e?.url)return null;const t=new URL(e.url);return/\/chat\/([a-f0-9-]+)/.exec(t.pathname)?.[1]??null}function l(n,e="info"){const t=document.getElementById("status");t&&(t.className=`status ${e}`,t.textContent=n,e==="success"&&setTimeout(()=>{t.textContent="",t.className=""},3e3))}function i(n){return document.getElementById(n)}async function w(){if(!await f()){const e=i("setupNotice");e&&(e.style.display="block");const t=i("exportCurrent"),c=i("exportAll");t&&(t.disabled=!0),c&&(c.disabled=!0)}}function h(){i("openOptions")?.addEventListener("click",e=>{e.preventDefault(),u.runtime.openOptionsPage()})}async function m(){const n=i("exportCurrent");if(n){n.disabled=!0,l("Fetching conversation...","info");try{const e=await f(),t=await g();if(!e)throw new Error("Organization ID not configured. Click the setup link above to configure it.");if(!t)throw new Error("Could not detect a conversation ID. Make sure you are on a Claude.ai conversation page.");const r=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!r?.url?.includes("claude.ai"))throw new Error("Please navigate to a Claude.ai conversation page first.");if(!r.id)throw new Error("Could not identify active tab.");const s=i("format"),o=i("includeMetadata");try{const a=await u.tabs.sendMessage(r.id,{action:"exportConversation",conversationId:t,orgId:e,format:s?.value??"json",includeMetadata:o?.checked??!0});if(a?.success)l("Conversation exported successfully!","success");else{const d=a?.error??"Export failed";console.error("Export failed:",d,a?.details),l(d,"error")}}catch(a){const d=a instanceof Error?a.message:String(a);throw d.includes("connection")||d.includes("Receiving end")?new Error("Cannot connect to page. Please ensure you are on a Claude.ai conversation page (https://claude.ai/chat/...) and refresh if needed."):a}}catch(e){const t=e instanceof Error?e.message:"Unknown error occurred";l(t,"error")}finally{n.disabled=!1}}}function b(){u.tabs.create({url:u.runtime.getURL("browse.html")})}async function v(){const n=i("exportAll");if(n){n.disabled=!0,l("Fetching all conversations...","info");try{const e=await f();if(!e)throw new Error("Organization ID not configured. Click the setup link above to configure it.");const c=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!c?.url?.includes("claude.ai"))throw new Error('Please navigate to a Claude.ai page first, or use "Browse All Conversations" instead.');if(!c.id)throw new Error("Could not identify active tab.");const r=i("format"),s=i("includeMetadata");try{const o=await u.tabs.sendMessage(c.id,{action:"exportAllConversations",orgId:e,format:r?.value??"json",includeMetadata:s?.checked??!0});if(o?.success)o.warnings?l(o.warnings,"info"):l(`Exported ${o.count??0} conversations!`,"success");else{const a=o?.error??"Export failed";console.error("Export failed:",a,o?.details),l(a,"error")}}catch(o){const a=o instanceof Error?o.message:String(o);throw a.includes("connection")||a.includes("Receiving end")?new Error('Cannot connect to page. This feature requires a Claude.ai page (https://claude.ai/chat/... or similar). Try "Browse All Conversations" instead - it works from any tab.'):o}}catch(e){const t=e instanceof Error?e.message:"Unknown error occurred";l(t,"error")}finally{n.disabled=!1}}}document.addEventListener("DOMContentLoaded",()=>{w(),h();const n=i("exportCurrent"),e=i("browseConversations"),t=i("exportAll");n?.addEventListener("click",()=>void m()),e?.addEventListener("click",b),t?.addEventListener("click",()=>void v())});
diff --git a/.output/chrome-mv3/content-scripts/content.js b/.output/chrome-mv3/content-scripts/content.js
new file mode 100644
index 0000000..4fe5211
--- /dev/null
+++ b/.output/chrome-mv3/content-scripts/content.js
@@ -0,0 +1,27 @@
+var content=(function(){"use strict";const v=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome;function A(t){return t}const E=[{date:new Date("2024-01-01"),model:"claude-3-sonnet-20240229"},{date:new Date("2024-06-20"),model:"claude-3-5-sonnet-20240620"},{date:new Date("2024-10-22"),model:"claude-3-5-sonnet-20241022"},{date:new Date("2025-02-29"),model:"claude-3-7-sonnet-20250219"},{date:new Date("2025-05-14"),model:"claude-sonnet-4-20250514"},{date:new Date("2025-09-29"),model:"claude-sonnet-4-5-20250929"}];function g(t){if(t.model)return t.model;const n=new Date(t.created_at);for(let e=E.length-1;e>=0;e--){const r=E[e];if(r&&n>=r.date)return r.model}return E[0]?.model}function _(t){if(!t.chat_messages||!t.current_leaf_message_uuid)return[];const n=new Map;t.chat_messages.forEach(o=>{n.set(o.uuid,o)});const e=[];let r=t.current_leaf_message_uuid;for(;r&&n.has(r);){const o=n.get(r);if(!o||(e.unshift(o),r=o.parent_message_uuid,r&&!n.has(r)))break}return e}function C(t){let n="";if(t.content)for(const e of t.content)e.text&&(n+=e.text);else t.text&&(n=t.text);return n}function I(t,n){let e=`# ${t.name||"Untitled Conversation"}
+
+`;n&&(e+=`**Created:** ${new Date(t.created_at).toLocaleString()}
+`,e+=`**Updated:** ${new Date(t.updated_at).toLocaleString()}
+`,e+=`**Model:** ${g(t)}
+
+`,e+=`---
+
+`);const r=_(t);for(const o of r){const i=o.sender==="human"?"**You**":"**Claude**";e+=`${i}:
+
+`;const s=C(o);s&&(e+=`${s}
+
+`),n&&o.created_at&&(e+=`*${new Date(o.created_at).toLocaleString()}*
+
+`),e+=`---
+
+`}return e}function k(t,n){let e="";n&&(e+=`${t.name||"Untitled Conversation"}
+`,e+=`Created: ${new Date(t.created_at).toLocaleString()}
+`,e+=`Updated: ${new Date(t.updated_at).toLocaleString()}
+`,e+=`Model: ${g(t)}
+
+`,e+=`---
+
+`);const r=_(t);let o=!1,i=!1;for(const s of r){const c=C(s);let a;s.sender==="human"?(a=o?"H":"Human",o=!0):(a=i?"A":"Assistant",i=!0),e+=`${a}: ${c}
+
+`}return e.trim()}function S(t,n,e="application/json"){const r=new Blob([t],{type:e}),o=URL.createObjectURL(r),i=document.createElement("a");i.href=o,i.download=n,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(o)}function h(t,n,e){const r=t.replace(/[^a-z0-9]/gi,"_").toLowerCase().substring(0,50),o=n==="json"?"json":n==="markdown"?"md":"txt",i=e?`_${e.substring(0,8)}`:"";return`${r}${i}.${o}`}const M={matches:["https://claude.ai/*"],cssInjectionMode:"ui",main(){console.log("Claude Conversation Exporter content script loaded");async function t(o,i){const s=`https://claude.ai/api/organizations/${o}/chat_conversations/${i}?tree=True&rendering_mode=messages&render_all_tools=true`,c=await fetch(s,{credentials:"include",headers:{Accept:"application/json"}});if(!c.ok)throw new Error(`Failed to fetch conversation: ${c.status}`);return await c.json()}async function n(o){const i=`https://claude.ai/api/organizations/${o}/chat_conversations`,s=await fetch(i,{credentials:"include",headers:{Accept:"application/json"}});if(!s.ok)throw new Error(`Failed to fetch conversations: ${s.status}`);return await s.json()}async function e(o,i,s,c){console.log("Fetching conversation:",i);const a=await t(o,i);console.log("Conversation data fetched successfully:",a);const f=g(a);a.model=f;let l,d,u;switch(s){case"markdown":l=I(a,c),d=h(a.name||"untitled","markdown",a.uuid),u="text/markdown";break;case"text":l=k(a,c),d=h(a.name||"untitled","text",a.uuid),u="text/plain";break;default:l=JSON.stringify(a,null,2),d=h(a.name||"untitled","json",a.uuid),u="application/json"}console.log("Downloading file:",d),S(l,d,u)}async function r(o,i,s){const c=await n(o);if(console.log(`Fetched ${c.length} conversations`),i==="json"){const l=`claude-all-conversations-${new Date().toISOString().split("T")[0]??"export"}.json`;return console.log("Downloading all conversations as JSON:",l),S(JSON.stringify(c,null,2),l,"application/json"),{count:c.length}}let a=0;const f=[];for(const l of c)try{console.log(`Fetching full conversation ${a+1}/${c.length}: ${l.uuid}`);const d=await t(o,l.uuid);d.model=g(d);let u,x,T;i==="markdown"?(u=I(d,s),x=h(l.name||"untitled","markdown",l.uuid),T="text/markdown"):(u=k(d,s),x=h(l.name||"untitled","text",l.uuid),T="text/plain"),S(u,x,T),a++,await new Promise(F=>setTimeout(F,500))}catch(d){const u=d instanceof Error?d.message:"Unknown error";console.error(`Failed to export conversation ${l.uuid}:`,u),f.push(`${l.name||l.uuid}: ${u}`)}return f.length>0?(console.warn("Some conversations failed to export:",f),{count:a,warnings:`Exported ${a}/${c.length} conversations. Some failed: ${f.join("; ")}`}):{count:a}}(async()=>v.runtime.onMessage.addListener((o,i)=>o.action==="exportConversation"?(console.log("Export conversation request received:",o),(async()=>{try{return await e(o.orgId,o.conversationId,o.format,o.includeMetadata),{success:!0}}catch(s){const c=s instanceof Error?s.message:"Unknown error",a=s instanceof Error?s.stack:void 0;return console.error("Export conversation error:",s),{success:!1,error:c,details:a}}})()):o.action==="exportAllConversations"?(console.log("Export all conversations request received:",o),(async()=>{try{const s=await r(o.orgId,o.format,o.includeMetadata);return{success:!0,count:s.count,warnings:s.warnings}}catch(s){const c=s instanceof Error?s.message:"Unknown error",a=s instanceof Error?s.stack:void 0;return console.error("Export all conversations error:",s),{success:!1,error:c,details:a}}})()):!1))()}};function m(t,...n){}const y={debug:(...t)=>m(console.debug,...t),log:(...t)=>m(console.log,...t),warn:(...t)=>m(console.warn,...t),error:(...t)=>m(console.error,...t)};class b extends Event{constructor(n,e){super(b.EVENT_NAME,{}),this.newUrl=n,this.oldUrl=e}static EVENT_NAME=$("wxt:locationchange")}function $(t){return`${v?.runtime?.id}:content:${t}`}function L(t){let n,e;return{run(){n==null&&(e=new URL(location.href),n=t.setInterval(()=>{let r=new URL(location.href);r.href!==e.href&&(window.dispatchEvent(new b(r,e)),e=r)},1e3))}}}class w{constructor(n,e){this.contentScriptName=n,this.options=e,this.abortController=new AbortController,this.isTopFrame?(this.listenForNewerScripts({ignoreFirstEvent:!0}),this.stopOldScripts()):this.listenForNewerScripts()}static SCRIPT_STARTED_MESSAGE_TYPE=$("wxt:content-script-started");isTopFrame=window.self===window.top;abortController;locationWatcher=L(this);receivedMessageIds=new Set;get signal(){return this.abortController.signal}abort(n){return this.abortController.abort(n)}get isInvalid(){return v.runtime.id==null&&this.notifyInvalidated(),this.signal.aborted}get isValid(){return!this.isInvalid}onInvalidated(n){return this.signal.addEventListener("abort",n),()=>this.signal.removeEventListener("abort",n)}block(){return new Promise(()=>{})}setInterval(n,e){const r=setInterval(()=>{this.isValid&&n()},e);return this.onInvalidated(()=>clearInterval(r)),r}setTimeout(n,e){const r=setTimeout(()=>{this.isValid&&n()},e);return this.onInvalidated(()=>clearTimeout(r)),r}requestAnimationFrame(n){const e=requestAnimationFrame((...r)=>{this.isValid&&n(...r)});return this.onInvalidated(()=>cancelAnimationFrame(e)),e}requestIdleCallback(n,e){const r=requestIdleCallback((...o)=>{this.signal.aborted||n(...o)},e);return this.onInvalidated(()=>cancelIdleCallback(r)),r}addEventListener(n,e,r,o){e==="wxt:locationchange"&&this.isValid&&this.locationWatcher.run(),n.addEventListener?.(e.startsWith("wxt:")?$(e):e,r,{...o,signal:this.signal})}notifyInvalidated(){this.abort("Content script context invalidated"),y.debug(`Content script "${this.contentScriptName}" context invalidated`)}stopOldScripts(){window.postMessage({type:w.SCRIPT_STARTED_MESSAGE_TYPE,contentScriptName:this.contentScriptName,messageId:Math.random().toString(36).slice(2)},"*")}verifyScriptStartedEvent(n){const e=n.data?.type===w.SCRIPT_STARTED_MESSAGE_TYPE,r=n.data?.contentScriptName===this.contentScriptName,o=!this.receivedMessageIds.has(n.data?.messageId);return e&&r&&o}listenForNewerScripts(n){let e=!0;const r=o=>{if(this.verifyScriptStartedEvent(o)){this.receivedMessageIds.add(o.data.messageId);const i=e;if(e=!1,i&&n?.ignoreFirstEvent)return;this.notifyInvalidated()}};addEventListener("message",r),this.onInvalidated(()=>removeEventListener("message",r))}}function U(){}function p(t,...n){}const D={debug:(...t)=>p(console.debug,...t),log:(...t)=>p(console.log,...t),warn:(...t)=>p(console.warn,...t),error:(...t)=>p(console.error,...t)};return(async()=>{try{const{main:t,...n}=M,e=new w("content",n);return await t(e)}catch(t){throw D.error('The content script "content" crashed on startup!',t),t}})()})();
+content;
\ No newline at end of file
diff --git a/.output/chrome-mv3/content-styles.css b/.output/chrome-mv3/content-styles.css
new file mode 100644
index 0000000..cdd2461
--- /dev/null
+++ b/.output/chrome-mv3/content-styles.css
@@ -0,0 +1,22 @@
+/* Optional: Add a floating export button on Claude.ai pages */
+.claude-exporter-button {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ z-index: 9999;
+ background: #5436da;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 60px;
+ height: 60px;
+ font-size: 24px;
+ cursor: pointer;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ transition: all 0.3s;
+}
+
+.claude-exporter-button:hover {
+ background: #4329b8;
+ transform: scale(1.1);
+}
diff --git a/.output/chrome-mv3/icon128.png b/.output/chrome-mv3/icon128.png
new file mode 100644
index 0000000..23a9b5a
Binary files /dev/null and b/.output/chrome-mv3/icon128.png differ
diff --git a/.output/chrome-mv3/icon16.png b/.output/chrome-mv3/icon16.png
new file mode 100644
index 0000000..06b49c2
Binary files /dev/null and b/.output/chrome-mv3/icon16.png differ
diff --git a/.output/chrome-mv3/icon48.png b/.output/chrome-mv3/icon48.png
new file mode 100644
index 0000000..6bad8be
Binary files /dev/null and b/.output/chrome-mv3/icon48.png differ
diff --git a/.output/chrome-mv3/manifest.json b/.output/chrome-mv3/manifest.json
new file mode 100644
index 0000000..a3e61fb
--- /dev/null
+++ b/.output/chrome-mv3/manifest.json
@@ -0,0 +1 @@
+{"manifest_version":3,"name":"Claude Conversation Exporter","description":"Export your Claude.ai conversations with full message history","version":"1.0.0","permissions":["activeTab","storage"],"host_permissions":["https://claude.ai/*"],"background":{"service_worker":"background.js"},"action":{"default_title":"Claude Conversation Exporter","default_popup":"popup.html"},"content_scripts":[{"matches":["https://claude.ai/*"],"js":["content-scripts/content.js"]}]}
\ No newline at end of file
diff --git a/.output/chrome-mv3/popup-header.png b/.output/chrome-mv3/popup-header.png
new file mode 100644
index 0000000..de149e6
Binary files /dev/null and b/.output/chrome-mv3/popup-header.png differ
diff --git a/.output/chrome-mv3/popup.html b/.output/chrome-mv3/popup.html
new file mode 100644
index 0000000..524cc2b
--- /dev/null
+++ b/.output/chrome-mv3/popup.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Claude Conversation Exporter
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.output/firefox-mv2/background.js b/.output/firefox-mv2/background.js
new file mode 100644
index 0000000..31af0ff
--- /dev/null
+++ b/.output/firefox-mv2/background.js
@@ -0,0 +1 @@
+var background=(function(){"use strict";const t=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome;function i(r){return r==null||typeof r=="function"?{main:r}:r}const a=i(()=>{console.log("Claude Conversation Exporter background script loaded"),t.runtime.onInstalled.addListener(()=>{console.log("Claude Conversation Exporter installed"),(async()=>{try{const r=await t.tabs.query({url:"https://claude.ai/*"});for(const e of r)if(e.id)try{await t.scripting.executeScript({target:{tabId:e.id},files:["content-scripts/content.js"]})}catch(n){console.log("Could not inject into tab",e.id,n)}}catch(r){console.error("Error querying or injecting tabs:",r)}})()}),t.runtime.onMessage.addListener((r,e)=>r.action==="ensureContentScript"?(async()=>{try{const c=(await t.tabs.query({active:!0,currentWindow:!0}))[0];return c?.id?(await t.scripting.executeScript({target:{tabId:c.id},files:["content-scripts/content.js"]}),{success:!0}):{success:!1,error:"No active tab found"}}catch(n){return{success:!1,error:n instanceof Error?n.message:"Unknown error"}}})():!1)});function d(){}function o(r,...e){}const u={debug:(...r)=>o(console.debug,...r),log:(...r)=>o(console.log,...r),warn:(...r)=>o(console.warn,...r),error:(...r)=>o(console.error,...r)};let s;try{s=a.main(),s instanceof Promise&&console.warn("The background's main() function return a promise, but it must be synchronous")}catch(r){throw u.error("The background crashed on startup!"),r}return s})();
diff --git a/.output/firefox-mv2/chunks/popup-BzajcGsb.js b/.output/firefox-mv2/chunks/popup-BzajcGsb.js
new file mode 100644
index 0000000..0d1f308
--- /dev/null
+++ b/.output/firefox-mv2/chunks/popup-BzajcGsb.js
@@ -0,0 +1 @@
+(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))c(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&c(o)}).observe(document,{childList:!0,subtree:!0});function t(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function c(r){if(r.ep)return;r.ep=!0;const s=t(r);fetch(r.href,s)}})();try{}catch(n){console.error("[wxt] Failed to initialize plugins",n)}const p=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome,u=p;async function f(){return(await u.storage.sync.get(["organizationId"])).organizationId}async function g(){const e=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!e?.url)return null;const t=new URL(e.url);return/\/chat\/([a-f0-9-]+)/.exec(t.pathname)?.[1]??null}function l(n,e="info"){const t=document.getElementById("status");t&&(t.className=`status ${e}`,t.textContent=n,e==="success"&&setTimeout(()=>{t.textContent="",t.className=""},3e3))}function i(n){return document.getElementById(n)}async function w(){if(!await f()){const e=i("setupNotice");e&&(e.style.display="block");const t=i("exportCurrent"),c=i("exportAll");t&&(t.disabled=!0),c&&(c.disabled=!0)}}function h(){i("openOptions")?.addEventListener("click",e=>{e.preventDefault(),u.runtime.openOptionsPage()})}async function m(){const n=i("exportCurrent");if(n){n.disabled=!0,l("Fetching conversation...","info");try{const e=await f(),t=await g();if(!e)throw new Error("Organization ID not configured. Click the setup link above to configure it.");if(!t)throw new Error("Could not detect a conversation ID. Make sure you are on a Claude.ai conversation page.");const r=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!r?.url?.includes("claude.ai"))throw new Error("Please navigate to a Claude.ai conversation page first.");if(!r.id)throw new Error("Could not identify active tab.");const s=i("format"),o=i("includeMetadata");try{const a=await u.tabs.sendMessage(r.id,{action:"exportConversation",conversationId:t,orgId:e,format:s?.value??"json",includeMetadata:o?.checked??!0});if(a?.success)l("Conversation exported successfully!","success");else{const d=a?.error??"Export failed";console.error("Export failed:",d,a?.details),l(d,"error")}}catch(a){const d=a instanceof Error?a.message:String(a);throw d.includes("connection")||d.includes("Receiving end")?new Error("Cannot connect to page. Please ensure you are on a Claude.ai conversation page (https://claude.ai/chat/...) and refresh if needed."):a}}catch(e){const t=e instanceof Error?e.message:"Unknown error occurred";l(t,"error")}finally{n.disabled=!1}}}function b(){u.tabs.create({url:u.runtime.getURL("browse.html")})}async function v(){const n=i("exportAll");if(n){n.disabled=!0,l("Fetching all conversations...","info");try{const e=await f();if(!e)throw new Error("Organization ID not configured. Click the setup link above to configure it.");const c=(await u.tabs.query({active:!0,currentWindow:!0}))[0];if(!c?.url?.includes("claude.ai"))throw new Error('Please navigate to a Claude.ai page first, or use "Browse All Conversations" instead.');if(!c.id)throw new Error("Could not identify active tab.");const r=i("format"),s=i("includeMetadata");try{const o=await u.tabs.sendMessage(c.id,{action:"exportAllConversations",orgId:e,format:r?.value??"json",includeMetadata:s?.checked??!0});if(o?.success)o.warnings?l(o.warnings,"info"):l(`Exported ${o.count??0} conversations!`,"success");else{const a=o?.error??"Export failed";console.error("Export failed:",a,o?.details),l(a,"error")}}catch(o){const a=o instanceof Error?o.message:String(o);throw a.includes("connection")||a.includes("Receiving end")?new Error('Cannot connect to page. This feature requires a Claude.ai page (https://claude.ai/chat/... or similar). Try "Browse All Conversations" instead - it works from any tab.'):o}}catch(e){const t=e instanceof Error?e.message:"Unknown error occurred";l(t,"error")}finally{n.disabled=!1}}}document.addEventListener("DOMContentLoaded",()=>{w(),h();const n=i("exportCurrent"),e=i("browseConversations"),t=i("exportAll");n?.addEventListener("click",()=>void m()),e?.addEventListener("click",b),t?.addEventListener("click",()=>void v())});
diff --git a/.output/firefox-mv2/content-scripts/content.js b/.output/firefox-mv2/content-scripts/content.js
new file mode 100644
index 0000000..4fe5211
--- /dev/null
+++ b/.output/firefox-mv2/content-scripts/content.js
@@ -0,0 +1,27 @@
+var content=(function(){"use strict";const v=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome;function A(t){return t}const E=[{date:new Date("2024-01-01"),model:"claude-3-sonnet-20240229"},{date:new Date("2024-06-20"),model:"claude-3-5-sonnet-20240620"},{date:new Date("2024-10-22"),model:"claude-3-5-sonnet-20241022"},{date:new Date("2025-02-29"),model:"claude-3-7-sonnet-20250219"},{date:new Date("2025-05-14"),model:"claude-sonnet-4-20250514"},{date:new Date("2025-09-29"),model:"claude-sonnet-4-5-20250929"}];function g(t){if(t.model)return t.model;const n=new Date(t.created_at);for(let e=E.length-1;e>=0;e--){const r=E[e];if(r&&n>=r.date)return r.model}return E[0]?.model}function _(t){if(!t.chat_messages||!t.current_leaf_message_uuid)return[];const n=new Map;t.chat_messages.forEach(o=>{n.set(o.uuid,o)});const e=[];let r=t.current_leaf_message_uuid;for(;r&&n.has(r);){const o=n.get(r);if(!o||(e.unshift(o),r=o.parent_message_uuid,r&&!n.has(r)))break}return e}function C(t){let n="";if(t.content)for(const e of t.content)e.text&&(n+=e.text);else t.text&&(n=t.text);return n}function I(t,n){let e=`# ${t.name||"Untitled Conversation"}
+
+`;n&&(e+=`**Created:** ${new Date(t.created_at).toLocaleString()}
+`,e+=`**Updated:** ${new Date(t.updated_at).toLocaleString()}
+`,e+=`**Model:** ${g(t)}
+
+`,e+=`---
+
+`);const r=_(t);for(const o of r){const i=o.sender==="human"?"**You**":"**Claude**";e+=`${i}:
+
+`;const s=C(o);s&&(e+=`${s}
+
+`),n&&o.created_at&&(e+=`*${new Date(o.created_at).toLocaleString()}*
+
+`),e+=`---
+
+`}return e}function k(t,n){let e="";n&&(e+=`${t.name||"Untitled Conversation"}
+`,e+=`Created: ${new Date(t.created_at).toLocaleString()}
+`,e+=`Updated: ${new Date(t.updated_at).toLocaleString()}
+`,e+=`Model: ${g(t)}
+
+`,e+=`---
+
+`);const r=_(t);let o=!1,i=!1;for(const s of r){const c=C(s);let a;s.sender==="human"?(a=o?"H":"Human",o=!0):(a=i?"A":"Assistant",i=!0),e+=`${a}: ${c}
+
+`}return e.trim()}function S(t,n,e="application/json"){const r=new Blob([t],{type:e}),o=URL.createObjectURL(r),i=document.createElement("a");i.href=o,i.download=n,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(o)}function h(t,n,e){const r=t.replace(/[^a-z0-9]/gi,"_").toLowerCase().substring(0,50),o=n==="json"?"json":n==="markdown"?"md":"txt",i=e?`_${e.substring(0,8)}`:"";return`${r}${i}.${o}`}const M={matches:["https://claude.ai/*"],cssInjectionMode:"ui",main(){console.log("Claude Conversation Exporter content script loaded");async function t(o,i){const s=`https://claude.ai/api/organizations/${o}/chat_conversations/${i}?tree=True&rendering_mode=messages&render_all_tools=true`,c=await fetch(s,{credentials:"include",headers:{Accept:"application/json"}});if(!c.ok)throw new Error(`Failed to fetch conversation: ${c.status}`);return await c.json()}async function n(o){const i=`https://claude.ai/api/organizations/${o}/chat_conversations`,s=await fetch(i,{credentials:"include",headers:{Accept:"application/json"}});if(!s.ok)throw new Error(`Failed to fetch conversations: ${s.status}`);return await s.json()}async function e(o,i,s,c){console.log("Fetching conversation:",i);const a=await t(o,i);console.log("Conversation data fetched successfully:",a);const f=g(a);a.model=f;let l,d,u;switch(s){case"markdown":l=I(a,c),d=h(a.name||"untitled","markdown",a.uuid),u="text/markdown";break;case"text":l=k(a,c),d=h(a.name||"untitled","text",a.uuid),u="text/plain";break;default:l=JSON.stringify(a,null,2),d=h(a.name||"untitled","json",a.uuid),u="application/json"}console.log("Downloading file:",d),S(l,d,u)}async function r(o,i,s){const c=await n(o);if(console.log(`Fetched ${c.length} conversations`),i==="json"){const l=`claude-all-conversations-${new Date().toISOString().split("T")[0]??"export"}.json`;return console.log("Downloading all conversations as JSON:",l),S(JSON.stringify(c,null,2),l,"application/json"),{count:c.length}}let a=0;const f=[];for(const l of c)try{console.log(`Fetching full conversation ${a+1}/${c.length}: ${l.uuid}`);const d=await t(o,l.uuid);d.model=g(d);let u,x,T;i==="markdown"?(u=I(d,s),x=h(l.name||"untitled","markdown",l.uuid),T="text/markdown"):(u=k(d,s),x=h(l.name||"untitled","text",l.uuid),T="text/plain"),S(u,x,T),a++,await new Promise(F=>setTimeout(F,500))}catch(d){const u=d instanceof Error?d.message:"Unknown error";console.error(`Failed to export conversation ${l.uuid}:`,u),f.push(`${l.name||l.uuid}: ${u}`)}return f.length>0?(console.warn("Some conversations failed to export:",f),{count:a,warnings:`Exported ${a}/${c.length} conversations. Some failed: ${f.join("; ")}`}):{count:a}}(async()=>v.runtime.onMessage.addListener((o,i)=>o.action==="exportConversation"?(console.log("Export conversation request received:",o),(async()=>{try{return await e(o.orgId,o.conversationId,o.format,o.includeMetadata),{success:!0}}catch(s){const c=s instanceof Error?s.message:"Unknown error",a=s instanceof Error?s.stack:void 0;return console.error("Export conversation error:",s),{success:!1,error:c,details:a}}})()):o.action==="exportAllConversations"?(console.log("Export all conversations request received:",o),(async()=>{try{const s=await r(o.orgId,o.format,o.includeMetadata);return{success:!0,count:s.count,warnings:s.warnings}}catch(s){const c=s instanceof Error?s.message:"Unknown error",a=s instanceof Error?s.stack:void 0;return console.error("Export all conversations error:",s),{success:!1,error:c,details:a}}})()):!1))()}};function m(t,...n){}const y={debug:(...t)=>m(console.debug,...t),log:(...t)=>m(console.log,...t),warn:(...t)=>m(console.warn,...t),error:(...t)=>m(console.error,...t)};class b extends Event{constructor(n,e){super(b.EVENT_NAME,{}),this.newUrl=n,this.oldUrl=e}static EVENT_NAME=$("wxt:locationchange")}function $(t){return`${v?.runtime?.id}:content:${t}`}function L(t){let n,e;return{run(){n==null&&(e=new URL(location.href),n=t.setInterval(()=>{let r=new URL(location.href);r.href!==e.href&&(window.dispatchEvent(new b(r,e)),e=r)},1e3))}}}class w{constructor(n,e){this.contentScriptName=n,this.options=e,this.abortController=new AbortController,this.isTopFrame?(this.listenForNewerScripts({ignoreFirstEvent:!0}),this.stopOldScripts()):this.listenForNewerScripts()}static SCRIPT_STARTED_MESSAGE_TYPE=$("wxt:content-script-started");isTopFrame=window.self===window.top;abortController;locationWatcher=L(this);receivedMessageIds=new Set;get signal(){return this.abortController.signal}abort(n){return this.abortController.abort(n)}get isInvalid(){return v.runtime.id==null&&this.notifyInvalidated(),this.signal.aborted}get isValid(){return!this.isInvalid}onInvalidated(n){return this.signal.addEventListener("abort",n),()=>this.signal.removeEventListener("abort",n)}block(){return new Promise(()=>{})}setInterval(n,e){const r=setInterval(()=>{this.isValid&&n()},e);return this.onInvalidated(()=>clearInterval(r)),r}setTimeout(n,e){const r=setTimeout(()=>{this.isValid&&n()},e);return this.onInvalidated(()=>clearTimeout(r)),r}requestAnimationFrame(n){const e=requestAnimationFrame((...r)=>{this.isValid&&n(...r)});return this.onInvalidated(()=>cancelAnimationFrame(e)),e}requestIdleCallback(n,e){const r=requestIdleCallback((...o)=>{this.signal.aborted||n(...o)},e);return this.onInvalidated(()=>cancelIdleCallback(r)),r}addEventListener(n,e,r,o){e==="wxt:locationchange"&&this.isValid&&this.locationWatcher.run(),n.addEventListener?.(e.startsWith("wxt:")?$(e):e,r,{...o,signal:this.signal})}notifyInvalidated(){this.abort("Content script context invalidated"),y.debug(`Content script "${this.contentScriptName}" context invalidated`)}stopOldScripts(){window.postMessage({type:w.SCRIPT_STARTED_MESSAGE_TYPE,contentScriptName:this.contentScriptName,messageId:Math.random().toString(36).slice(2)},"*")}verifyScriptStartedEvent(n){const e=n.data?.type===w.SCRIPT_STARTED_MESSAGE_TYPE,r=n.data?.contentScriptName===this.contentScriptName,o=!this.receivedMessageIds.has(n.data?.messageId);return e&&r&&o}listenForNewerScripts(n){let e=!0;const r=o=>{if(this.verifyScriptStartedEvent(o)){this.receivedMessageIds.add(o.data.messageId);const i=e;if(e=!1,i&&n?.ignoreFirstEvent)return;this.notifyInvalidated()}};addEventListener("message",r),this.onInvalidated(()=>removeEventListener("message",r))}}function U(){}function p(t,...n){}const D={debug:(...t)=>p(console.debug,...t),log:(...t)=>p(console.log,...t),warn:(...t)=>p(console.warn,...t),error:(...t)=>p(console.error,...t)};return(async()=>{try{const{main:t,...n}=M,e=new w("content",n);return await t(e)}catch(t){throw D.error('The content script "content" crashed on startup!',t),t}})()})();
+content;
\ No newline at end of file
diff --git a/.output/firefox-mv2/content-styles.css b/.output/firefox-mv2/content-styles.css
new file mode 100644
index 0000000..cdd2461
--- /dev/null
+++ b/.output/firefox-mv2/content-styles.css
@@ -0,0 +1,22 @@
+/* Optional: Add a floating export button on Claude.ai pages */
+.claude-exporter-button {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ z-index: 9999;
+ background: #5436da;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 60px;
+ height: 60px;
+ font-size: 24px;
+ cursor: pointer;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ transition: all 0.3s;
+}
+
+.claude-exporter-button:hover {
+ background: #4329b8;
+ transform: scale(1.1);
+}
diff --git a/.output/firefox-mv2/icon128.png b/.output/firefox-mv2/icon128.png
new file mode 100644
index 0000000..23a9b5a
Binary files /dev/null and b/.output/firefox-mv2/icon128.png differ
diff --git a/.output/firefox-mv2/icon16.png b/.output/firefox-mv2/icon16.png
new file mode 100644
index 0000000..06b49c2
Binary files /dev/null and b/.output/firefox-mv2/icon16.png differ
diff --git a/.output/firefox-mv2/icon48.png b/.output/firefox-mv2/icon48.png
new file mode 100644
index 0000000..6bad8be
Binary files /dev/null and b/.output/firefox-mv2/icon48.png differ
diff --git a/.output/firefox-mv2/manifest.json b/.output/firefox-mv2/manifest.json
new file mode 100644
index 0000000..20b3240
--- /dev/null
+++ b/.output/firefox-mv2/manifest.json
@@ -0,0 +1 @@
+{"manifest_version":2,"name":"Claude Conversation Exporter","description":"Export your Claude.ai conversations with full message history","version":"1.0.0","permissions":["activeTab","storage","https://claude.ai/*"],"background":{"scripts":["background.js"]},"browser_action":{"default_title":"Claude Conversation Exporter","default_popup":"popup.html"},"content_scripts":[{"matches":["https://claude.ai/*"],"js":["content-scripts/content.js"]}]}
\ No newline at end of file
diff --git a/.output/firefox-mv2/popup-header.png b/.output/firefox-mv2/popup-header.png
new file mode 100644
index 0000000..de149e6
Binary files /dev/null and b/.output/firefox-mv2/popup-header.png differ
diff --git a/.output/firefox-mv2/popup.html b/.output/firefox-mv2/popup.html
new file mode 100644
index 0000000..524cc2b
--- /dev/null
+++ b/.output/firefox-mv2/popup.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Claude Conversation Exporter
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.wxt/eslintrc-auto-import.json b/.wxt/eslintrc-auto-import.json
new file mode 100644
index 0000000..1419a27
--- /dev/null
+++ b/.wxt/eslintrc-auto-import.json
@@ -0,0 +1,49 @@
+{
+ "globals": {
+ "AutoMount": true,
+ "AutoMountOptions": true,
+ "Browser": true,
+ "ContentScriptAnchoredOptions": true,
+ "ContentScriptAppendMode": true,
+ "ContentScriptContext": true,
+ "ContentScriptInlinePositioningOptions": true,
+ "ContentScriptModalPositioningOptions": true,
+ "ContentScriptOverlayAlignment": true,
+ "ContentScriptOverlayPositioningOptions": true,
+ "ContentScriptPositioningOptions": true,
+ "ContentScriptUi": true,
+ "ContentScriptUiOptions": true,
+ "IframeContentScriptUi": true,
+ "IframeContentScriptUiOptions": true,
+ "InjectScriptOptions": true,
+ "IntegratedContentScriptUi": true,
+ "IntegratedContentScriptUiOptions": true,
+ "InvalidMatchPattern": true,
+ "MatchPattern": true,
+ "MigrationError": true,
+ "ScriptPublicPath": true,
+ "ShadowRootContentScriptUi": true,
+ "ShadowRootContentScriptUiOptions": true,
+ "StopAutoMount": true,
+ "StorageArea": true,
+ "StorageAreaChanges": true,
+ "StorageItemKey": true,
+ "WxtAppConfig": true,
+ "WxtStorage": true,
+ "WxtStorageItem": true,
+ "WxtWindowEventMap": true,
+ "browser": true,
+ "createIframeUi": true,
+ "createIntegratedUi": true,
+ "createShadowRootUi": true,
+ "defineAppConfig": true,
+ "defineBackground": true,
+ "defineContentScript": true,
+ "defineUnlistedScript": true,
+ "defineWxtPlugin": true,
+ "fakeBrowser": true,
+ "injectScript": true,
+ "storage": true,
+ "useAppConfig": true
+ }
+}
diff --git a/.wxt/tsconfig.json b/.wxt/tsconfig.json
new file mode 100644
index 0000000..899f31c
--- /dev/null
+++ b/.wxt/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "noEmit": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "paths": {
+ "@": [".."],
+ "@/*": ["../*"],
+ "~": [".."],
+ "~/*": ["../*"],
+ "@@": [".."],
+ "@@/*": ["../*"],
+ "~~": [".."],
+ "~~/*": ["../*"]
+ }
+ },
+ "include": [
+ "../**/*",
+ "./wxt.d.ts"
+ ],
+ "exclude": ["../.output"]
+}
\ No newline at end of file
diff --git a/build-check.sh b/build-check.sh
deleted file mode 100755
index f4ce515..0000000
--- a/build-check.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-set -e
-
-echo "Building Firefox extension..."
-cd /home/jasonross/workspace/Claude-Conversation-Exporter-Firefox-TS
-
-# Run TypeScript compiler
-echo "Running TypeScript compiler..."
-npx tsc --noEmit
-
-# Run Vite build
-echo "Running Vite build..."
-npx vite build --mode firefox
-
-# Check if content script was built correctly
-echo ""
-echo "Checking content script..."
-CONTENT_SIZE=$(stat -f%z dist/firefox/src/content.js 2>/dev/null || stat -c%s dist/firefox/src/content.js 2>/dev/null)
-echo "Content script size: $CONTENT_SIZE bytes"
-
-if [ "$CONTENT_SIZE" -lt 100 ]; then
- echo "❌ ERROR: Content script is too small! ($CONTENT_SIZE bytes)"
- echo "Content of content.js:"
- cat dist/firefox/src/content.js
-else
- echo "✅ Content script built successfully"
-fi
-
-echo ""
-echo "Build complete!"
-ls -lh dist/firefox/src/*.js
diff --git a/build-chrome.sh b/build-chrome.sh
deleted file mode 100755
index d3bbc20..0000000
--- a/build-chrome.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# Build script for Chrome extension
-# This script builds the content script separately as an IIFE to avoid
-# the broken dynamic import loader that the vite-plugin-web-extension creates
-
-set -e
-
-echo "Building Chrome extension..."
-
-# Step 1: Build content script separately as IIFE
-echo "Step 1: Building content script..."
-npx vite build --config vite.content-chrome.config.ts
-
-# Step 2: Build main extension with vite-plugin-web-extension
-echo "Step 2: Building main extension..."
-BROWSER=chrome npx vite build --mode chrome
-
-# Step 3: Copy the IIFE content script over the stub
-echo "Step 3: Replacing content script stub with IIFE bundle..."
-cp dist-temp-content-chrome/content.js dist/chrome/src/chrome/scripts/content.js
-
-# Step 3.5: Fix serviceWorker.js import path (make it relative)
-echo "Step 3.5: Fixing serviceWorker.js import path..."
-sed -i 's|"/src/|"./src/|g' dist/chrome/serviceWorker.js
-
-# Step 4: Copy icon files
-echo "Step 4: Copying icon files..."
-mkdir -p dist/chrome/src
-cp src/icon16.png dist/chrome/src/
-cp src/icon48.png dist/chrome/src/
-cp src/icon128.png dist/chrome/src/
-
-# Step 5: Copy popup header image
-echo "Step 5: Copying popup header..."
-mkdir -p dist/chrome/src/chrome/scripts
-cp src/popup-header.png dist/chrome/src/chrome/scripts/
-
-echo "Chrome build complete!"
-echo "Load unpacked extension from: dist/chrome/"
diff --git a/build-firefox.sh b/build-firefox.sh
deleted file mode 100755
index 4a471da..0000000
--- a/build-firefox.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-set -e
-
-cd /home/jasonross/workspace/Claude-Conversation-Exporter-Firefox-TS
-
-echo "Building content script separately..."
-npx vite build --config vite.content-firefox.config.ts
-
-echo "Building main extension..."
-npx vite build --mode firefox
-
-echo "Copying content script to dist..."
-cp dist-temp-content-firefox/content.js dist/firefox/src/firefox/scripts/content.js
-rm -rf dist-temp-content-firefox
-
-echo "Copying icon files..."
-mkdir -p dist/firefox/src
-cp src/icon16.png dist/firefox/src/
-cp src/icon48.png dist/firefox/src/
-cp src/icon128.png dist/firefox/src/
-
-echo "Copying popup header..."
-mkdir -p dist/firefox/src/firefox/scripts
-cp src/popup-header.png dist/firefox/src/firefox/scripts/
-
-echo ""
-echo "Checking content script..."
-CONTENT_SIZE=$(stat -c%s dist/firefox/src/firefox/scripts/content.js 2>/dev/null || stat -f%z dist/firefox/src/firefox/scripts/content.js)
-echo "Content script size: $CONTENT_SIZE bytes"
-
-if [ "$CONTENT_SIZE" -gt 1000 ]; then
- echo "✅ Content script built successfully!"
-else
- echo "❌ ERROR: Content script is too small"
-fi
-
-echo ""
-echo "Build complete!"
diff --git a/convert-to-chrome.sh b/convert-to-chrome.sh
deleted file mode 100755
index 503cffd..0000000
--- a/convert-to-chrome.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-
-# Script to convert Firefox browser.* API calls to Chrome chrome.* API calls
-# This creates Chrome-specific versions of the extension scripts
-
-set -e
-
-echo "Converting Firefox scripts to Chrome API..."
-
-# Files to convert
-FILES=("popup.ts" "options.ts" "browse.ts" "content.ts" "background.ts")
-
-for file in "${FILES[@]}"; do
- echo "Converting $file..."
-
- # Copy file to Chrome directory
- cp "src/$file" "src/chrome/scripts/$file"
-
- # Convert browser.* calls to chrome.*
- # This uses sed to replace browser API calls with chrome API calls
- # and wraps Promise-based calls with callbacks
-
- sed -i 's/browser\.storage\.sync\.get/chrome.storage.sync.get/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.storage\.sync\.set/chrome.storage.sync.set/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.tabs\.query/chrome.tabs.query/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.tabs\.sendMessage/chrome.tabs.sendMessage/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.tabs\.create/chrome.tabs.create/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.runtime\.sendMessage/chrome.runtime.sendMessage/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.runtime\.getURL/chrome.runtime.getURL/g' "src/chrome/scripts/$file"
- sed -i 's/browser\.runtime\.onMessage/chrome.runtime.onMessage/g' "src/chrome/scripts/$file"
-
- echo "✅ Converted $file"
-done
-
-# Copy Firefox scripts to firefox directory
-echo "Copying Firefox scripts..."
-for file in "${FILES[@]}"; do
- cp "src/$file" "src/firefox/scripts/$file"
- echo "✅ Copied $file to Firefox directory"
-done
-
-echo ""
-echo "Conversion complete!"
-echo "Chrome scripts: src/chrome/scripts/"
-echo "Firefox scripts: src/firefox/scripts/"
diff --git a/entrypoints/background.ts b/entrypoints/background.ts
new file mode 100644
index 0000000..566af69
--- /dev/null
+++ b/entrypoints/background.ts
@@ -0,0 +1,81 @@
+/**
+ * Background script for Claude Conversation Exporter
+ * Handles extension lifecycle events and content script injection
+ */
+
+import { defineBackground as wxtDefineBackground } from 'wxt/utils/define-background';
+import type { ExtensionMessage } from '../src/types';
+
+export default wxtDefineBackground(() => {
+ console.log('Claude Conversation Exporter background script loaded');
+
+ /**
+ * Handle extension installation
+ */
+ browser.runtime.onInstalled.addListener(() => {
+ console.log('Claude Conversation Exporter installed');
+
+ // Inject content script into already-open Claude.ai tabs
+ void (async () => {
+ try {
+ const tabs = await browser.tabs.query({ url: 'https://claude.ai/*' });
+
+ for (const tab of tabs) {
+ if (tab.id) {
+ try {
+ await browser.scripting.executeScript({
+ target: { tabId: tab.id },
+ files: ['content-scripts/content.js'],
+ });
+ } catch (err) {
+ console.log('Could not inject into tab', tab.id, err);
+ }
+ }
+ }
+ } catch (err) {
+ console.error('Error querying or injecting tabs:', err);
+ }
+ })();
+ });
+
+ /**
+ * Handle messages from popup or other extension components
+ */
+ browser.runtime.onMessage.addListener(
+ (request: ExtensionMessage, _sender: browser.runtime.MessageSender) => {
+ if (request.action === 'ensureContentScript') {
+ return (async () => {
+ try {
+ const tabs = await browser.tabs.query({
+ active: true,
+ currentWindow: true,
+ });
+
+ const activeTab = tabs[0];
+ if (activeTab?.id) {
+ await browser.scripting.executeScript({
+ target: { tabId: activeTab.id },
+ files: ['content-scripts/content.js'],
+ });
+
+ return { success: true };
+ }
+
+ return {
+ success: false,
+ error: 'No active tab found',
+ };
+ } catch (err) {
+ return {
+ success: false,
+ error: err instanceof Error ? err.message : 'Unknown error',
+ };
+ }
+ })();
+ }
+
+ // Return false to indicate no response will be sent
+ return false;
+ }
+ );
+});
diff --git a/entrypoints/content.ts b/entrypoints/content.ts
new file mode 100644
index 0000000..8032468
--- /dev/null
+++ b/entrypoints/content.ts
@@ -0,0 +1,255 @@
+/**
+ * Content script for Claude Conversation Exporter
+ * Runs on claude.ai pages to handle conversation exports
+ */
+
+import { defineContentScript as wxtDefineContentScript } from 'wxt/utils/define-content-script';
+import type {
+ Conversation,
+ ConversationListItem,
+ ExtensionMessage,
+ ExportFormat,
+} from '../src/types';
+import {
+ convertToMarkdown,
+ convertToText,
+ downloadFile,
+ generateFilename,
+ inferModel,
+} from '../src/utils';
+
+export default wxtDefineContentScript({
+ matches: ['https://claude.ai/*'],
+ cssInjectionMode: 'ui',
+ main() {
+ console.log('Claude Conversation Exporter content script loaded');
+
+ /**
+ * Fetch a single conversation from Claude API
+ */
+ async function fetchConversation(
+ orgId: string,
+ conversationId: string
+ ): Promise {
+ const url = `https://claude.ai/api/organizations/${orgId}/chat_conversations/${conversationId}?tree=True&rendering_mode=messages&render_all_tools=true`;
+
+ const response = await fetch(url, {
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch conversation: ${response.status}`);
+ }
+
+ return (await response.json()) as Conversation;
+ }
+
+ /**
+ * Fetch all conversations from Claude API
+ */
+ async function fetchAllConversations(orgId: string): Promise {
+ const url = `https://claude.ai/api/organizations/${orgId}/chat_conversations`;
+
+ const response = await fetch(url, {
+ credentials: 'include',
+ headers: {
+ Accept: 'application/json',
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch conversations: ${response.status}`);
+ }
+
+ return (await response.json()) as ConversationListItem[];
+ }
+
+ /**
+ * Export a single conversation
+ */
+ async function exportConversation(
+ orgId: string,
+ conversationId: string,
+ format: ExportFormat,
+ includeMetadata: boolean
+ ): Promise {
+ console.log('Fetching conversation:', conversationId);
+ const data = await fetchConversation(orgId, conversationId);
+
+ console.log('Conversation data fetched successfully:', data);
+
+ // Infer model if null
+ const modelName = inferModel(data);
+ data.model = modelName;
+
+ let content: string;
+ let filename: string;
+ let type: string;
+
+ switch (format) {
+ case 'markdown':
+ content = convertToMarkdown(data, includeMetadata);
+ filename = generateFilename(data.name || 'untitled', 'markdown', data.uuid);
+ type = 'text/markdown';
+ break;
+ case 'text':
+ content = convertToText(data, includeMetadata);
+ filename = generateFilename(data.name || 'untitled', 'text', data.uuid);
+ type = 'text/plain';
+ break;
+ default:
+ content = JSON.stringify(data, null, 2);
+ filename = generateFilename(data.name || 'untitled', 'json', data.uuid);
+ type = 'application/json';
+ }
+
+ console.log('Downloading file:', filename);
+ downloadFile(content, filename, type);
+ }
+
+ /**
+ * Export all conversations
+ */
+ async function exportAllConversations(
+ orgId: string,
+ format: ExportFormat,
+ includeMetadata: boolean
+ ): Promise<{ count: number; warnings?: string }> {
+ const conversations = await fetchAllConversations(orgId);
+ console.log(`Fetched ${conversations.length} conversations`);
+
+ if (format === 'json') {
+ // For JSON, export as a single file with all conversations
+ const filename = `claude-all-conversations-${
+ new Date().toISOString().split('T')[0] ?? 'export'
+ }.json`;
+ console.log('Downloading all conversations as JSON:', filename);
+ downloadFile(
+ JSON.stringify(conversations, null, 2),
+ filename,
+ 'application/json'
+ );
+ return { count: conversations.length };
+ }
+
+ // For other formats, create individual files
+ let count = 0;
+ const errors: string[] = [];
+
+ for (const conv of conversations) {
+ try {
+ console.log(
+ `Fetching full conversation ${count + 1}/${conversations.length}: ${conv.uuid}`
+ );
+ const fullConv = await fetchConversation(orgId, conv.uuid);
+
+ // Infer model if null
+ fullConv.model = inferModel(fullConv);
+
+ let content: string;
+ let filename: string;
+ let type: string;
+
+ if (format === 'markdown') {
+ content = convertToMarkdown(fullConv, includeMetadata);
+ filename = generateFilename(conv.name || 'untitled', 'markdown', conv.uuid);
+ type = 'text/markdown';
+ } else {
+ content = convertToText(fullConv, includeMetadata);
+ filename = generateFilename(conv.name || 'untitled', 'text', conv.uuid);
+ type = 'text/plain';
+ }
+
+ downloadFile(content, filename, type);
+ count++;
+
+ // Add a small delay to avoid overwhelming the API
+ await new Promise((resolve) => setTimeout(resolve, 500));
+ } catch (error) {
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
+ console.error(`Failed to export conversation ${conv.uuid}:`, errorMsg);
+ errors.push(`${conv.name || conv.uuid}: ${errorMsg}`);
+ }
+ }
+
+ if (errors.length > 0) {
+ console.warn('Some conversations failed to export:', errors);
+ return {
+ count,
+ warnings: `Exported ${count}/${conversations.length} conversations. Some failed: ${errors.join('; ')}`,
+ };
+ }
+
+ return { count };
+ }
+
+ /**
+ * Handle messages from popup or background script
+ */
+ (async () => {
+ browser.runtime.onMessage.addListener(
+ (request: ExtensionMessage, _sender: browser.runtime.MessageSender) => {
+ if (request.action === 'exportConversation') {
+ console.log('Export conversation request received:', request);
+
+ return (async () => {
+ try {
+ await exportConversation(
+ request.orgId,
+ request.conversationId,
+ request.format,
+ request.includeMetadata
+ );
+ return { success: true };
+ } catch (error) {
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
+ const errorStack = error instanceof Error ? error.stack : undefined;
+ console.error('Export conversation error:', error);
+ return {
+ success: false,
+ error: errorMsg,
+ details: errorStack,
+ };
+ }
+ })();
+ }
+
+ if (request.action === 'exportAllConversations') {
+ console.log('Export all conversations request received:', request);
+
+ return (async () => {
+ try {
+ const result = await exportAllConversations(
+ request.orgId,
+ request.format,
+ request.includeMetadata
+ );
+ return {
+ success: true,
+ count: result.count,
+ warnings: result.warnings,
+ };
+ } catch (error) {
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
+ const errorStack = error instanceof Error ? error.stack : undefined;
+ console.error('Export all conversations error:', error);
+ return {
+ success: false,
+ error: errorMsg,
+ details: errorStack,
+ };
+ }
+ })();
+ }
+
+ // Return false to indicate no response will be sent
+ return false;
+ }
+ );
+ })();
+ },
+} as const);
+
diff --git a/entrypoints/popup/index.html b/entrypoints/popup/index.html
new file mode 100644
index 0000000..65630d9
--- /dev/null
+++ b/entrypoints/popup/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+
+ Claude Conversation Exporter
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/entrypoints/popup/main.ts b/entrypoints/popup/main.ts
new file mode 100644
index 0000000..122f7e8
--- /dev/null
+++ b/entrypoints/popup/main.ts
@@ -0,0 +1,257 @@
+/**
+ * Popup script for Claude Conversation Exporter
+ * Handles the extension popup UI and user interactions
+ */
+
+import type { ExtensionResponse } from '../../src/types';
+
+/**
+ * Get organization ID from storage
+ */
+async function getOrgId(): Promise {
+ const result = await browser.storage.sync.get(['organizationId']);
+ return result['organizationId'] as string | undefined;
+}
+
+/**
+ * Get current conversation ID from active tab URL
+ */
+async function getCurrentConversationId(): Promise {
+ const tabs = await browser.tabs.query({ active: true, currentWindow: true });
+ const tab = tabs[0];
+
+ if (!tab?.url) {
+ return null;
+ }
+
+ const url = new URL(tab.url);
+ const match = /\/chat\/([a-f0-9-]+)/.exec(url.pathname);
+ return match?.[1] ?? null;
+}
+
+/**
+ * Show status message to user
+ */
+function showStatus(message: string, type: 'info' | 'success' | 'error' = 'info'): void {
+ const statusEl = document.getElementById('status');
+ if (!statusEl) return;
+
+ statusEl.className = `status ${type}`;
+ statusEl.textContent = message;
+
+ if (type === 'success') {
+ setTimeout(() => {
+ statusEl.textContent = '';
+ statusEl.className = '';
+ }, 3000);
+ }
+}
+
+/**
+ * Get HTML element by ID with type checking
+ */
+function getElement(id: string): T | null {
+ return document.getElementById(id) as T | null;
+}
+
+/**
+ * Check if org ID is configured on popup load
+ */
+async function initializePopup(): Promise {
+ const orgId = await getOrgId();
+
+ if (!orgId) {
+ const setupNotice = getElement('setupNotice');
+ if (setupNotice) {
+ setupNotice.style.display = 'block';
+ }
+
+ const exportCurrentBtn = getElement('exportCurrent');
+ const exportAllBtn = getElement('exportAll');
+
+ if (exportCurrentBtn) exportCurrentBtn.disabled = true;
+ if (exportAllBtn) exportAllBtn.disabled = true;
+ }
+}
+
+/**
+ * Handle options link click
+ */
+function setupOptionsLink(): void {
+ const openOptionsBtn = getElement('openOptions');
+ openOptionsBtn?.addEventListener('click', (e) => {
+ e.preventDefault();
+ void browser.runtime.openOptionsPage();
+ });
+}
+
+/**
+ * Handle export current conversation
+ */
+async function handleExportCurrent(): Promise {
+ const button = getElement('exportCurrent');
+ if (!button) return;
+
+ button.disabled = true;
+ showStatus('Fetching conversation...', 'info');
+
+ try {
+ const orgId = await getOrgId();
+ const conversationId = await getCurrentConversationId();
+
+ if (!orgId) {
+ throw new Error(
+ 'Organization ID not configured. Click the setup link above to configure it.'
+ );
+ }
+
+ if (!conversationId) {
+ throw new Error(
+ 'Could not detect a conversation ID. Make sure you are on a Claude.ai conversation page.'
+ );
+ }
+
+ const tabs = await browser.tabs.query({ active: true, currentWindow: true });
+ const tab = tabs[0];
+
+ // Check if we're on Claude.ai
+ if (!tab?.url?.includes('claude.ai')) {
+ throw new Error('Please navigate to a Claude.ai conversation page first.');
+ }
+
+ if (!tab.id) {
+ throw new Error('Could not identify active tab.');
+ }
+
+ const formatSelect = getElement('format');
+ const metadataCheck = getElement('includeMetadata');
+
+ try {
+ const response = (await browser.tabs.sendMessage(tab.id, {
+ action: 'exportConversation',
+ conversationId,
+ orgId,
+ format: formatSelect?.value ?? 'json',
+ includeMetadata: metadataCheck?.checked ?? true,
+ })) as ExtensionResponse;
+
+ if (response?.success) {
+ showStatus('Conversation exported successfully!', 'success');
+ } else {
+ const errorMsg = response?.error ?? 'Export failed';
+ console.error('Export failed:', errorMsg, response?.details);
+ showStatus(errorMsg, 'error');
+ }
+ } catch (sendError) {
+ // Handle "Could not establish connection" error
+ const errorMsg = sendError instanceof Error ? sendError.message : String(sendError);
+ if (errorMsg.includes('connection') || errorMsg.includes('Receiving end')) {
+ throw new Error(
+ 'Cannot connect to page. Please ensure you are on a Claude.ai conversation page (https://claude.ai/chat/...) and refresh if needed.'
+ );
+ }
+ throw sendError;
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message : 'Unknown error occurred';
+ showStatus(message, 'error');
+ } finally {
+ button.disabled = false;
+ }
+}
+
+/**
+ * Handle browse conversations button
+ */
+function handleBrowseConversations(): void {
+ void browser.tabs.create({ url: browser.runtime.getURL('browse.html') });
+}
+
+/**
+ * Handle export all conversations
+ */
+async function handleExportAll(): Promise {
+ const button = getElement('exportAll');
+ if (!button) return;
+
+ button.disabled = true;
+ showStatus('Fetching all conversations...', 'info');
+
+ try {
+ const orgId = await getOrgId();
+
+ if (!orgId) {
+ throw new Error(
+ 'Organization ID not configured. Click the setup link above to configure it.'
+ );
+ }
+
+ const tabs = await browser.tabs.query({ active: true, currentWindow: true });
+ const tab = tabs[0];
+
+ // Check if we're on Claude.ai
+ if (!tab?.url?.includes('claude.ai')) {
+ throw new Error(
+ 'Please navigate to a Claude.ai page first, or use "Browse All Conversations" instead.'
+ );
+ }
+
+ if (!tab.id) {
+ throw new Error('Could not identify active tab.');
+ }
+
+ const formatSelect = getElement('format');
+ const metadataCheck = getElement('includeMetadata');
+
+ try {
+ const response = (await browser.tabs.sendMessage(tab.id, {
+ action: 'exportAllConversations',
+ orgId,
+ format: formatSelect?.value ?? 'json',
+ includeMetadata: metadataCheck?.checked ?? true,
+ })) as ExtensionResponse;
+
+ if (response?.success) {
+ if (response.warnings) {
+ showStatus(response.warnings, 'info');
+ } else {
+ showStatus(`Exported ${response.count ?? 0} conversations!`, 'success');
+ }
+ } else {
+ const errorMsg = response?.error ?? 'Export failed';
+ console.error('Export failed:', errorMsg, response?.details);
+ showStatus(errorMsg, 'error');
+ }
+ } catch (sendError) {
+ // Handle "Could not establish connection" error
+ const errorMsg = sendError instanceof Error ? sendError.message : String(sendError);
+ if (errorMsg.includes('connection') || errorMsg.includes('Receiving end')) {
+ throw new Error(
+ 'Cannot connect to page. This feature requires a Claude.ai page (https://claude.ai/chat/... or similar). Try "Browse All Conversations" instead - it works from any tab.'
+ );
+ }
+ throw sendError;
+ }
+ } catch (error) {
+ const message = error instanceof Error ? error.message : 'Unknown error occurred';
+ showStatus(message, 'error');
+ } finally {
+ button.disabled = false;
+ }
+}
+
+/**
+ * Initialize popup when DOM is loaded
+ */
+document.addEventListener('DOMContentLoaded', () => {
+ void initializePopup();
+ setupOptionsLink();
+
+ const exportCurrentBtn = getElement('exportCurrent');
+ const browseBtn = getElement('browseConversations');
+ const exportAllBtn = getElement('exportAll');
+
+ exportCurrentBtn?.addEventListener('click', () => void handleExportCurrent());
+ browseBtn?.addEventListener('click', handleBrowseConversations);
+ exportAllBtn?.addEventListener('click', () => void handleExportAll());
+});
diff --git a/package.json b/package.json
index 02e5381..ba5dd09 100644
--- a/package.json
+++ b/package.json
@@ -4,24 +4,25 @@
"description": "Export your Claude.ai conversations in various formats - Chrome and Firefox extension with TypeScript support",
"type": "module",
"scripts": {
- "build": "tsc && vite build",
- "build:firefox": "bash build-firefox.sh",
- "build:chrome": "bash build-chrome.sh",
- "dev": "vite build --watch",
- "dev:firefox": "vite build --mode firefox --watch",
- "dev:chrome": "vite build --mode chrome --watch",
- "type-check": "tsc --noEmit",
- "lint": "eslint src/**/*.ts",
- "lint:fix": "eslint src/**/*.ts --fix",
- "format": "prettier --check \"src/**/*.{ts,html,css,json}\"",
- "format:fix": "prettier --write \"src/**/*.{ts,html,css,json}\"",
+ "dev": "wxt",
+ "dev:firefox": "wxt -b firefox",
+ "dev:chrome": "wxt -b chrome",
+ "build": "wxt build",
+ "build:firefox": "wxt build -b firefox",
+ "build:chrome": "wxt build -b chrome",
+ "zip": "wxt zip",
+ "zip:firefox": "wxt zip -b firefox",
+ "zip:chrome": "wxt zip -b chrome",
+ "type-check": "wxt type-check",
+ "lint": "eslint entrypoints/**/*.ts src/**/*.ts",
+ "lint:fix": "eslint entrypoints/**/*.ts src/**/*.ts --fix",
+ "format": "prettier --check \"**/*.{ts,html,css,json}\"",
+ "format:fix": "prettier --write \"**/*.{ts,html,css,json}\"",
"test": "vitest run",
"test:ui": "vitest run --ui",
"test:coverage": "vitest run --coverage",
- "check": "pnpm type-check && pnpm lint && pnpm format && pnpm test:run",
- "firefox:run": "web-ext run --source-dir=dist/firefox --start-url https://claude.ai",
- "chrome:run": "echo 'Load dist/chrome in chrome://extensions with Developer Mode enabled'",
- "clean": "rm -rf dist"
+ "check": "pnpm type-check && pnpm lint && pnpm format && pnpm test",
+ "clean": "rm -rf .wxt .output dist"
},
"keywords": [
"claude",
@@ -37,7 +38,6 @@
"packageManager": "pnpm@10.18.1",
"devDependencies": {
"@eslint/js": "^9.38.0",
- "@samrum/vite-plugin-web-extension": "^5.1.1",
"@types/chrome": "^0.1.24",
"@types/firefox-webext-browser": "^143.0.0",
"@types/jszip": "^3.4.0",
@@ -53,10 +53,9 @@
"prettier": "^3.6.2",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.1",
- "vite": "^7.1.10",
- "vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4",
- "web-ext": "^9.0.0"
+ "web-ext": "^9.0.0",
+ "wxt": "^0.20.11"
},
"dependencies": {
"jszip": "^3.10.1"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2b55901..bb84584 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,9 +15,6 @@ importers:
'@eslint/js':
specifier: ^9.38.0
version: 9.38.0
- '@samrum/vite-plugin-web-extension':
- specifier: ^5.1.1
- version: 5.1.1(vite@7.1.10(@types/node@24.8.1))
'@types/chrome':
specifier: ^0.1.24
version: 0.1.24
@@ -29,10 +26,10 @@ importers:
version: 3.4.1
'@typescript-eslint/eslint-plugin':
specifier: ^8.46.1
- version: 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0)(typescript@5.9.3))(eslint@9.38.0)(typescript@5.9.3)
+ version: 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: ^8.46.1
- version: 8.46.1(eslint@9.38.0)(typescript@5.9.3)
+ version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@vitest/coverage-v8':
specifier: ^3.2.4
version: 3.2.4(vitest@3.2.4)
@@ -41,13 +38,13 @@ importers:
version: 3.2.4(vitest@3.2.4)
eslint:
specifier: ^9.38.0
- version: 9.38.0
+ version: 9.38.0(jiti@2.6.1)
eslint-config-prettier:
specifier: ^10.1.8
- version: 10.1.8(eslint@9.38.0)
+ version: 10.1.8(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-prettier:
specifier: ^5.5.4
- version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.38.0))(eslint@9.38.0)(prettier@3.6.2)
+ version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)))(eslint@9.38.0(jiti@2.6.1))(prettier@3.6.2)
happy-dom:
specifier: ^20.0.5
version: 20.0.5
@@ -62,22 +59,32 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.46.1
- version: 8.46.1(eslint@9.38.0)(typescript@5.9.3)
- vite:
- specifier: ^7.1.10
- version: 7.1.10(@types/node@24.8.1)
- vite-tsconfig-paths:
- specifier: ^5.1.4
- version: 5.1.4(typescript@5.9.3)(vite@7.1.10(@types/node@24.8.1))
+ version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^3.2.4
- version: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jsdom@27.0.1(postcss@8.5.6))
+ version: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))
web-ext:
specifier: ^9.0.0
version: 9.0.0
+ wxt:
+ specifier: ^0.20.11
+ version: 0.20.11(@types/node@24.8.1)(jiti@2.6.1)(rollup@4.52.5)
packages:
+ '@1natsu/wait-element@4.1.2':
+ resolution: {integrity: sha512-qWxSJD+Q5b8bKOvESFifvfZ92DuMsY+03SBNjTO34ipJLP6mZ9yK4bQz/vlh48aEQXoJfaZBqUwKL5BdI5iiWw==}
+
+ '@aklinker1/rollup-plugin-visualizer@5.12.0':
+ resolution: {integrity: sha512-X24LvEGw6UFmy0lpGJDmXsMyBD58XmX1bbwsaMLhNoM+UMQfQ3b2RtC+nz4b/NoRK5r6QJSKJHBNVeUdwqybaQ==}
+ engines: {node: '>=14'}
+ hasBin: true
+ peerDependencies:
+ rollup: 2.x || 3.x || 4.x
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
'@ampproject/remapping@2.3.0':
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
@@ -108,6 +115,10 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/runtime@7.28.2':
+ resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/runtime@7.28.4':
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
@@ -402,6 +413,14 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.0':
+ resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
+ engines: {node: 20 || >=22}
+
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -413,6 +432,9 @@ packages:
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
@@ -571,18 +593,9 @@ packages:
cpu: [x64]
os: [win32]
- '@samrum/vite-plugin-web-extension@5.1.1':
- resolution: {integrity: sha512-ZpmAN5bGaPouW8iwwCpz5UpvAHGG5f1poxtvjych/C7BIg0A1D8IM9ewacBO3odf5iuuPZIA0SFdgwtgHozueA==}
- engines: {node: '>=16.0.0'}
- peerDependencies:
- vite: ^4.0.3 || ^5.0.0
-
'@types/chai@5.2.2':
resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
- '@types/chrome@0.0.233':
- resolution: {integrity: sha512-T3HUW8LDhHfYPbUkOZilhnqX04sZqEFIQO0OIG8byZ7PBIk2jYys1AkNg56UbtKbsh3dABmOniK+0Q3oyo7Sxg==}
-
'@types/chrome@0.1.24':
resolution: {integrity: sha512-9iO9HL2bMeGS4C8m6gNFWUyuPE5HEUFk+rGh+7oriUjg+ata4Fc9PoVlu8xvGm7yoo3AmS3J6fAjoFj61NL2rw==}
@@ -592,9 +605,6 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
- '@types/etag@1.8.4':
- resolution: {integrity: sha512-f1z/UMth8gQ6636NBqhFmJ3zES7EuDcUnV6K1gl1osHp+85KPKX+VixYWUpqLkw1fftCagyHJjJOZjZkEi2rHw==}
-
'@types/filesystem@0.0.36':
resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==}
@@ -734,6 +744,21 @@ packages:
'@vitest/utils@3.2.4':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+ '@webext-core/fake-browser@1.3.2':
+ resolution: {integrity: sha512-jFyPWWz+VkHAC9DRIiIPOyu6X/KlC8dYqSKweHz6tsDb86QawtVgZSpYcM+GOQBlZc5DHFo92jJ7cIq4uBnU0A==}
+
+ '@webext-core/isolated-element@1.1.2':
+ resolution: {integrity: sha512-CNHYhsIR8TPkPb+4yqTIuzaGnVn/Fshev5fyoPW+/8Cyc93tJbCjP9PC1XSK6fDWu+xASdPHLZaoa2nWAYoxeQ==}
+
+ '@webext-core/match-patterns@1.0.3':
+ resolution: {integrity: sha512-NY39ACqCxdKBmHgw361M9pfJma8e4AZo20w9AY+5ZjIj1W2dvXC8J31G5fjfOGbulW9w4WKpT8fPooi0mLkn9A==}
+
+ '@wxt-dev/browser@0.1.4':
+ resolution: {integrity: sha512-9x03I15i79XU8qYwjv4le0K2HdMl/Yga2wUBSoUbcrCnamv8P3nvuYxREQ9C5QY/qPAfeEVdAtaTrS3KWak71g==}
+
+ '@wxt-dev/storage@1.2.6':
+ resolution: {integrity: sha512-f6AknnpJvhNHW4s0WqwSGCuZAj0fjP3EVNPBO5kB30pY+3Zt/nqZGqJN6FgBLCSkYjPJ8VL1hNX5LMVmvxQoDw==}
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -786,6 +811,10 @@ packages:
ansi-align@3.0.1:
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
+ ansi-escapes@7.1.1:
+ resolution: {integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==}
+ engines: {node: '>=18'}
+
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -820,6 +849,9 @@ packages:
ast-v8-to-istanbul@0.3.7:
resolution: {integrity: sha512-kr1Hy6YRZBkGQSb6puP+D6FQ59Cx4m0siYhAxygMCAgadiWQ6oxAxQXHOMvJx67SJ63jRoVIIg5eXzUbbct1ww==}
+ async-mutex@0.5.0:
+ resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==}
+
async@3.2.6:
resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
@@ -866,6 +898,14 @@ packages:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'}
+ c12@3.3.1:
+ resolution: {integrity: sha512-LcWQ01LT9tkoUINHgpIOv3mMs+Abv7oVCrtpMRi1PaapVEpWoMga5WuT7/DqFTu7URP9ftbOmimNw1KNIGh9DQ==}
+ peerDependencies:
+ magicast: ^0.3.5
+ peerDependenciesMeta:
+ magicast:
+ optional: true
+
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -901,15 +941,38 @@ packages:
resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==}
engines: {node: '>=20.18.1'}
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
+
chrome-launcher@1.2.0:
resolution: {integrity: sha512-JbuGuBNss258bvGil7FT4HKdC3SC2K7UAEUqiPy3ACS3Yxo3hAW6bvFpCu2HsIJLgTqxgEX6BkujvzZfLpUD0Q==}
engines: {node: '>=12.13.0'}
hasBin: true
+ ci-info@4.3.1:
+ resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==}
+ engines: {node: '>=8'}
+
+ citty@0.1.6:
+ resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
+
cli-boxes@3.0.0:
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
engines: {node: '>=10'}
+ cli-cursor@5.0.0:
+ resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
+ engines: {node: '>=18'}
+
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
+ cli-truncate@4.0.0:
+ resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
+ engines: {node: '>=18'}
+
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
@@ -925,6 +988,9 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ colorette@2.0.20:
+ resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
+
columnify@1.6.0:
resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==}
engines: {node: '>=8.0.0'}
@@ -948,6 +1014,12 @@ packages:
resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==}
engines: {'0': node >= 0.8}
+ confbox@0.1.8:
+ resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+ confbox@0.2.2:
+ resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
+
config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
@@ -955,9 +1027,9 @@ packages:
resolution: {integrity: sha512-N4oog6YJWbR9kGyXvS7jEykLDXIE2C0ILYqNBZBp9iwiJpoCBWYsuAdW6PPFn6w06jjnC+3JstVvWHO4cZqvRg==}
engines: {node: '>=18'}
- content-security-policy-parser@0.4.1:
- resolution: {integrity: sha512-NNJS8XPnx3OKr/CUOSwDSJw+lWTrZMYnclLKj0Y9CYOfJNJTWLFGPg3u2hYgbXMXKVRkZR2fbyReNQ1mUff/Qg==}
- engines: {node: '>=8.0.0'}
+ consola@3.4.2:
+ resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
+ engines: {node: ^14.18.0 || >=16.10.0}
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -977,6 +1049,9 @@ packages:
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
engines: {node: '>= 6'}
+ cssom@0.5.0:
+ resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==}
+
cssstyle@5.3.1:
resolution: {integrity: sha512-g5PC9Aiph9eiczFpcgUhd9S4UUO3F+LHGRIi5NUMZ+4xtoIYbHNZwZnWA2JsFGe8OU8nl4WyaEFiZuGuxlutJQ==}
engines: {node: '>=20'}
@@ -1039,10 +1114,24 @@ packages:
defaults@1.0.4:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+ define-lazy-prop@2.0.0:
+ resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
+ engines: {node: '>=8'}
+
define-lazy-prop@3.0.0:
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
engines: {node: '>=12'}
+ defu@6.1.4:
+ resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ destr@2.0.5:
+ resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
+
doctrine@3.0.0:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
@@ -1064,6 +1153,18 @@ packages:
resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==}
engines: {node: '>=18'}
+ dotenv-expand@12.0.3:
+ resolution: {integrity: sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA==}
+ engines: {node: '>=12'}
+
+ dotenv@16.6.1:
+ resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
+ engines: {node: '>=12'}
+
+ dotenv@17.2.3:
+ resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
+ engines: {node: '>=12'}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -1087,6 +1188,13 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
+ environment@1.1.0:
+ resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
+ engines: {node: '>=18'}
+
+ error-ex@1.3.4:
+ resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
+
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
@@ -1110,6 +1218,10 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
eslint-config-prettier@10.1.8:
resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
hasBin: true
@@ -1199,14 +1311,16 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
- etag@1.8.1:
- resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
- engines: {node: '>= 0.6'}
+ eventemitter3@5.0.1:
+ resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
expect-type@1.2.2:
resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
engines: {node: '>=12.0.0'}
+ exsolve@1.0.7:
+ resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -1259,6 +1373,10 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
+ filesize@11.0.13:
+ resolution: {integrity: sha512-mYJ/qXKvREuO0uH8LTQJ6v7GsUvVOguqxg2VTwQUkyTPXXRRWPdjuUPVqdBrJQhvci48OHlNGRnux+Slr2Rnvw==}
+ engines: {node: '>= 10.8.0'}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@@ -1291,6 +1409,14 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
+ form-data-encoder@4.1.0:
+ resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==}
+ engines: {node: '>= 18'}
+
+ formdata-node@6.0.3:
+ resolution: {integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==}
+ engines: {node: '>= 18'}
+
fs-extra@11.3.2:
resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==}
engines: {node: '>=14.14'}
@@ -1315,6 +1441,13 @@ packages:
resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'}
+ get-port-please@3.2.0:
+ resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==}
+
+ giget@2.0.0:
+ resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
+ hasBin: true
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -1346,9 +1479,6 @@ packages:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
- globrex@0.1.2:
- resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
-
graceful-fs@4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
@@ -1372,6 +1502,9 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
+ hookable@5.5.3:
+ resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
html-encoding-sniffer@4.0.0:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
@@ -1379,6 +1512,9 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-escaper@3.0.3:
+ resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
+
htmlparser2@10.0.0:
resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==}
@@ -1414,6 +1550,9 @@ packages:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
+ import-meta-resolve@4.2.0:
+ resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
+
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -1444,6 +1583,9 @@ packages:
resolution: {integrity: sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA==}
engines: {node: '>=0.10.0'}
+ is-arrayish@0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
is-docker@2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'}
@@ -1462,6 +1604,14 @@ packages:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
+ is-fullwidth-code-point@4.0.0:
+ resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
+ engines: {node: '>=12'}
+
+ is-fullwidth-code-point@5.1.0:
+ resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
+ engines: {node: '>=18'}
+
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -1480,6 +1630,10 @@ packages:
resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==}
engines: {node: '>=18'}
+ is-interactive@2.0.0:
+ resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
+ engines: {node: '>=12'}
+
is-npm@6.1.0:
resolution: {integrity: sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -1496,13 +1650,29 @@ packages:
resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==}
engines: {node: '>=12'}
+ is-plain-object@2.0.4:
+ resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
+ engines: {node: '>=0.10.0'}
+
is-potential-custom-element-name@1.0.1:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+ is-primitive@3.0.1:
+ resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==}
+ engines: {node: '>=0.10.0'}
+
is-relative@0.1.3:
resolution: {integrity: sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==}
engines: {node: '>=0.10.0'}
+ is-unicode-supported@1.3.0:
+ resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
+ engines: {node: '>=12'}
+
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
is-utf8@0.2.1:
resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==}
@@ -1523,6 +1693,10 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ isobject@3.0.1:
+ resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+ engines: {node: '>=0.10.0'}
+
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
@@ -1542,6 +1716,10 @@ packages:
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
+ hasBin: true
+
jose@5.9.6:
resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
@@ -1570,6 +1748,10 @@ packages:
json-merge-patch@1.0.2:
resolution: {integrity: sha512-M6Vp2GN9L7cfuMXiWOmHj9bEFbeC250iVtcKQbqVgEsDVYnIsrNsbU+h/Y/PkbBQCtEa4Bez+Ebv0zfbC8ObLg==}
+ json-parse-even-better-errors@3.0.2:
+ resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
@@ -1579,6 +1761,11 @@ packages:
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
jsonfile@6.2.0:
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
@@ -1588,6 +1775,10 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
ky@1.12.0:
resolution: {integrity: sha512-YRLmSUHCwOJRBMArtqMRLOmO7fewn3yOoui6aB8ERkRVXupa0UiaQaKbIXteMt4jUElhbdqTMsLFHs8APxxUoQ==}
engines: {node: '>=18'}
@@ -1606,6 +1797,27 @@ packages:
lighthouse-logger@2.0.2:
resolution: {integrity: sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg==}
+ lines-and-columns@2.0.4:
+ resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ linkedom@0.18.12:
+ resolution: {integrity: sha512-jalJsOwIKuQJSeTvsgzPe9iJzyfVaEJiEXl+25EkKevsULHvMJzpNqwvj1jOESWdmgKDiXObyjOYwlUqG7wo1Q==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ canvas: '>= 2'
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
+ listr2@8.3.3:
+ resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
+ engines: {node: '>=18.0.0'}
+
+ local-pkg@1.1.2:
+ resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
+ engines: {node: '>=14'}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -1613,6 +1825,14 @@ packages:
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ log-symbols@6.0.0:
+ resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
+ engines: {node: '>=18'}
+
+ log-update@6.1.0:
+ resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
+ engines: {node: '>=18'}
+
loupe@3.2.1:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
@@ -1636,6 +1856,9 @@ packages:
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+ many-keys-map@2.0.1:
+ resolution: {integrity: sha512-DHnZAD4phTbZ+qnJdjoNEVU1NecYoSdbOOoVmTDH46AuxDkEVh3MxTVpXq10GtcTC6mndN9dkv1rNfpjRcLnOw==}
+
marky@1.3.0:
resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==}
@@ -1650,6 +1873,14 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
+ mimic-function@5.0.1:
+ resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
+ engines: {node: '>=18'}
+
+ minimatch@10.0.3:
+ resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==}
+ engines: {node: 20 || >=22}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -1664,6 +1895,9 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ mlly@1.8.0:
+ resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
mrmime@2.0.1:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
@@ -1675,6 +1909,10 @@ packages:
resolution: {integrity: sha512-I7tSVxHGPlmPN/enE3mS1aOSo6bWBfls+3HmuEeCUBCE7gWnm3cBXCBkpurzFjVRwC6Kld8lLaZ1Iv5vOcjvcQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ nano-spawn@1.0.3:
+ resolution: {integrity: sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==}
+ engines: {node: '>=20.17'}
+
nanoid@3.3.11:
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -1683,6 +1921,9 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ node-fetch-native@1.6.7:
+ resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
+
node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
@@ -1690,9 +1931,24 @@ packages:
node-notifier@10.0.1:
resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==}
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+ nypm@0.6.2:
+ resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==}
+ engines: {node: ^14.16.0 || >=16.10.0}
+ hasBin: true
+
+ ofetch@1.4.1:
+ resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==}
+
+ ohash@2.0.11:
+ resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
+
on-exit-leak-free@2.1.2:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
@@ -1700,14 +1956,26 @@ packages:
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ onetime@7.0.0:
+ resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
+ engines: {node: '>=18'}
+
open@10.2.0:
resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
engines: {node: '>=18'}
+ open@8.4.2:
+ resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
+ engines: {node: '>=12'}
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
+ ora@8.2.0:
+ resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==}
+ engines: {node: '>=18'}
+
os-shim@0.1.3:
resolution: {integrity: sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==}
engines: {node: '>= 0.4.0'}
@@ -1734,6 +2002,10 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
+ parse-json@7.1.1:
+ resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==}
+ engines: {node: '>=16'}
+
parse-json@8.3.0:
resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==}
engines: {node: '>=18'}
@@ -1776,6 +2048,9 @@ packages:
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+ perfect-debounce@2.0.0:
+ resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -1797,6 +2072,16 @@ packages:
resolution: {integrity: sha512-+YIodBB9sxcWeR8PrXC2K3gEDyfkUuVEITOcbqrfcj+z5QW4ioIcqZfYFbrLTYLsmAwunbS7nfU/dpBB6PZc1g==}
hasBin: true
+ pino@9.7.0:
+ resolution: {integrity: sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==}
+ hasBin: true
+
+ pkg-types@1.3.1:
+ resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+ pkg-types@2.3.0:
+ resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
postcss@8.5.6:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
@@ -1824,9 +2109,17 @@ packages:
resolution: {integrity: sha512-NV8aTmpwrZv+Iys54sSFOBx3tuVaOBvvrft5PNppnxy9xpU/akHbaWIril22AB22zaPgrgwKdD0KsrM0ptUtpg==}
engines: {node: '>=6'}
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
proto-list@1.2.4:
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
+ publish-browser-extension@3.0.3:
+ resolution: {integrity: sha512-cBINZCkLo7YQaGoUvEHthZ0sDzgJQht28IS+SFMT2omSNhGsPiVNRkWir3qLiTrhGhW9Ci2KVHpA1QAMoBdL2g==}
+ hasBin: true
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -1835,12 +2128,18 @@ packages:
resolution: {integrity: sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==}
engines: {node: '>=12.20'}
+ quansync@0.2.11:
+ resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+ rc9@2.1.2:
+ resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
+
rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
@@ -1848,6 +2147,10 @@ packages:
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
@@ -1872,10 +2175,17 @@ packages:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
+ restore-cursor@5.1.0:
+ resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
+ engines: {node: '>=18'}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ rfdc@1.4.1:
+ resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
@@ -1913,6 +2223,9 @@ packages:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
+ scule@1.3.0:
+ resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
+
semver@7.7.2:
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
engines: {node: '>=10'}
@@ -1923,6 +2236,10 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ set-value@4.1.0:
+ resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==}
+ engines: {node: '>=11.0'}
+
setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
@@ -1951,6 +2268,17 @@ packages:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ slice-ansi@5.0.0:
+ resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
+ engines: {node: '>=12'}
+
+ slice-ansi@7.1.2:
+ resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
+ engines: {node: '>=18'}
+
sonic-boom@4.2.0:
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
@@ -1965,6 +2293,10 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ source-map@0.7.6:
+ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
+ engines: {node: '>= 12'}
+
spawn-sync@1.0.15:
resolution: {integrity: sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==}
@@ -1981,6 +2313,10 @@ packages:
std-env@3.10.0:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+ stdin-discarder@0.2.2:
+ resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
+ engines: {node: '>=18'}
+
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -2024,6 +2360,10 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
+ strip-json-comments@5.0.2:
+ resolution: {integrity: sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g==}
+ engines: {node: '>=14.16'}
+
strip-json-comments@5.0.3:
resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==}
engines: {node: '>=14.16'}
@@ -2064,6 +2404,9 @@ packages:
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+ tinyexec@1.0.1:
+ resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
+
tinyglobby@0.2.15:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
@@ -2113,15 +2456,8 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
- tsconfck@3.1.6:
- resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
- engines: {node: ^18 || >=20}
- hasBin: true
- peerDependencies:
- typescript: ^5.0.0
- peerDependenciesMeta:
- typescript:
- optional: true
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
@@ -2131,6 +2467,10 @@ packages:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
+ type-fest@3.13.1:
+ resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
+ engines: {node: '>=14.16'}
+
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
@@ -2150,6 +2490,12 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ ufo@1.6.1:
+ resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
+
+ uhyphen@0.2.0:
+ resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==}
+
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
@@ -2160,10 +2506,22 @@ packages:
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
engines: {node: '>=20.18.1'}
+ unimport@5.5.0:
+ resolution: {integrity: sha512-/JpWMG9s1nBSlXJAQ8EREFTFy3oy6USFd8T6AoBaw1q2GGcF4R9yp3ofg32UODZlYEO5VD0EWE1RpI9XDWyPYg==}
+ engines: {node: '>=18.12.0'}
+
universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
+ unplugin-utils@0.3.1:
+ resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
+ engines: {node: '>=20.19.0'}
+
+ unplugin@2.3.10:
+ resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==}
+ engines: {node: '>=18.12.0'}
+
upath@2.0.1:
resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==}
engines: {node: '>=4'}
@@ -2187,14 +2545,6 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
- vite-tsconfig-paths@5.1.4:
- resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==}
- peerDependencies:
- vite: '*'
- peerDependenciesMeta:
- vite:
- optional: true
-
vite@7.1.10:
resolution: {integrity: sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2274,6 +2624,10 @@ packages:
wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+ web-ext-run@0.2.4:
+ resolution: {integrity: sha512-rQicL7OwuqWdQWI33JkSXKcp7cuv1mJG8u3jRQwx/8aDsmhbTHs9ZRmNYOL+LX0wX8edIEQX8jj4bB60GoXtKA==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+
web-ext@9.0.0:
resolution: {integrity: sha512-QheVP1seAMB5EOnTxlR8mOgQU85ik44K6FedEzqmOEq9kpCy1NrycekMw1mk8qwlkeN0RbJmEK65NIDCRthy1Q==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -2283,6 +2637,9 @@ packages:
resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==}
engines: {node: '>=20'}
+ webpack-virtual-modules@0.6.2:
+ resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+
whatwg-encoding@3.1.1:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
@@ -2361,6 +2718,10 @@ packages:
resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
engines: {node: '>=18'}
+ wxt@0.20.11:
+ resolution: {integrity: sha512-DqqHc/5COs8GR21ii99bANXf/mu6zuDpiXFV1YKNsqO5/PvkrCx5arY0aVPL5IATsuacAnNzdj4eMc1qbzS53Q==}
+ hasBin: true
+
xdg-basedir@5.1.0:
resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==}
engines: {node: '>=12'}
@@ -2402,8 +2763,25 @@ packages:
zip-dir@2.0.0:
resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==}
+ zod@4.1.12:
+ resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
+
snapshots:
+ '@1natsu/wait-element@4.1.2':
+ dependencies:
+ defu: 6.1.4
+ many-keys-map: 2.0.1
+
+ '@aklinker1/rollup-plugin-visualizer@5.12.0(rollup@4.52.5)':
+ dependencies:
+ open: 8.4.2
+ picomatch: 2.3.1
+ source-map: 0.7.6
+ yargs: 17.7.2
+ optionalDependencies:
+ rollup: 4.52.5
+
'@ampproject/remapping@2.3.0':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
@@ -2441,6 +2819,8 @@ snapshots:
dependencies:
'@babel/types': 7.28.4
+ '@babel/runtime@7.28.2': {}
+
'@babel/runtime@7.28.4': {}
'@babel/types@7.28.4':
@@ -2573,9 +2953,9 @@ snapshots:
eslint: 8.57.1
eslint-visitor-keys: 3.4.3
- '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0)':
+ '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
@@ -2660,6 +3040,12 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.0':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
+
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
@@ -2676,6 +3062,11 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.31
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
@@ -2784,25 +3175,10 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.52.5':
optional: true
- '@samrum/vite-plugin-web-extension@5.1.1(vite@7.1.10(@types/node@24.8.1))':
- dependencies:
- '@types/chrome': 0.0.233
- '@types/etag': 1.8.4
- content-security-policy-parser: 0.4.1
- etag: 1.8.1
- fs-extra: 11.3.2
- magic-string: 0.30.19
- vite: 7.1.10(@types/node@24.8.1)
-
'@types/chai@5.2.2':
dependencies:
'@types/deep-eql': 4.0.2
- '@types/chrome@0.0.233':
- dependencies:
- '@types/filesystem': 0.0.36
- '@types/har-format': 1.2.16
-
'@types/chrome@0.1.24':
dependencies:
'@types/filesystem': 0.0.36
@@ -2812,10 +3188,6 @@ snapshots:
'@types/estree@1.0.8': {}
- '@types/etag@1.8.4':
- dependencies:
- '@types/node': 24.8.1
-
'@types/filesystem@0.0.36':
dependencies:
'@types/filewriter': 0.0.33
@@ -2848,15 +3220,15 @@ snapshots:
dependencies:
'@types/node': 24.8.1
- '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0)(typescript@5.9.3))(eslint@9.38.0)(typescript@5.9.3)':
+ '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.46.1
- '@typescript-eslint/type-utils': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
- '@typescript-eslint/utils': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
+ '@typescript-eslint/type-utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.46.1
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
@@ -2865,14 +3237,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.46.1(eslint@9.38.0)(typescript@5.9.3)':
+ '@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.46.1
'@typescript-eslint/types': 8.46.1
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.46.1
debug: 4.4.3
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -2895,13 +3267,13 @@ snapshots:
dependencies:
typescript: 5.9.3
- '@typescript-eslint/type-utils@8.46.1(eslint@9.38.0)(typescript@5.9.3)':
+ '@typescript-eslint/type-utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.46.1
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
@@ -2925,13 +3297,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.46.1(eslint@9.38.0)(typescript@5.9.3)':
+ '@typescript-eslint/utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.46.1
'@typescript-eslint/types': 8.46.1
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -2958,7 +3330,7 @@ snapshots:
std-env: 3.10.0
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jsdom@27.0.1(postcss@8.5.6))
+ vitest: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))
transitivePeerDependencies:
- supports-color
@@ -2970,13 +3342,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(vite@7.1.10(@types/node@24.8.1))':
+ '@vitest/mocker@3.2.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.19
optionalDependencies:
- vite: 7.1.10(@types/node@24.8.1)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -3007,7 +3379,7 @@ snapshots:
sirv: 3.0.2
tinyglobby: 0.2.15
tinyrainbow: 2.0.0
- vitest: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jsdom@27.0.1(postcss@8.5.6))
+ vitest: 3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))
'@vitest/utils@3.2.4':
dependencies:
@@ -3015,6 +3387,27 @@ snapshots:
loupe: 3.2.1
tinyrainbow: 2.0.0
+ '@webext-core/fake-browser@1.3.2':
+ dependencies:
+ lodash.merge: 4.6.2
+
+ '@webext-core/isolated-element@1.1.2':
+ dependencies:
+ is-potential-custom-element-name: 1.0.1
+
+ '@webext-core/match-patterns@1.0.3': {}
+
+ '@wxt-dev/browser@0.1.4':
+ dependencies:
+ '@types/filesystem': 0.0.36
+ '@types/har-format': 1.2.16
+
+ '@wxt-dev/storage@1.2.6':
+ dependencies:
+ '@wxt-dev/browser': 0.1.4
+ async-mutex: 0.5.0
+ dequal: 2.0.3
+
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
acorn: 8.15.0
@@ -3088,6 +3481,10 @@ snapshots:
dependencies:
string-width: 4.2.3
+ ansi-escapes@7.1.1:
+ dependencies:
+ environment: 1.1.0
+
ansi-regex@5.0.1: {}
ansi-regex@6.2.2: {}
@@ -3112,6 +3509,10 @@ snapshots:
estree-walker: 3.0.3
js-tokens: 9.0.1
+ async-mutex@0.5.0:
+ dependencies:
+ tslib: 2.8.1
+
async@3.2.6: {}
atomic-sleep@1.0.0: {}
@@ -3163,6 +3564,23 @@ snapshots:
dependencies:
run-applescript: 7.1.0
+ c12@3.3.1(magicast@0.3.5):
+ dependencies:
+ chokidar: 4.0.3
+ confbox: 0.2.2
+ defu: 6.1.4
+ dotenv: 17.2.3
+ exsolve: 1.0.7
+ giget: 2.0.0
+ jiti: 2.6.1
+ ohash: 2.0.11
+ pathe: 2.0.3
+ perfect-debounce: 2.0.0
+ pkg-types: 2.3.0
+ rc9: 2.1.2
+ optionalDependencies:
+ magicast: 0.3.5
+
cac@6.7.14: {}
callsites@3.1.0: {}
@@ -3209,6 +3627,10 @@ snapshots:
undici: 7.16.0
whatwg-mimetype: 4.0.0
+ chokidar@4.0.3:
+ dependencies:
+ readdirp: 4.1.2
+
chrome-launcher@1.2.0:
dependencies:
'@types/node': 24.8.1
@@ -3218,8 +3640,25 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ ci-info@4.3.1: {}
+
+ citty@0.1.6:
+ dependencies:
+ consola: 3.4.2
+
cli-boxes@3.0.0: {}
+ cli-cursor@5.0.0:
+ dependencies:
+ restore-cursor: 5.1.0
+
+ cli-spinners@2.9.2: {}
+
+ cli-truncate@4.0.0:
+ dependencies:
+ slice-ansi: 5.0.0
+ string-width: 7.2.0
+
cliui@8.0.1:
dependencies:
string-width: 4.2.3
@@ -3234,6 +3673,8 @@ snapshots:
color-name@1.1.4: {}
+ colorette@2.0.20: {}
+
columnify@1.6.0:
dependencies:
strip-ansi: 6.0.1
@@ -3256,6 +3697,10 @@ snapshots:
readable-stream: 2.3.8
typedarray: 0.0.6
+ confbox@0.1.8: {}
+
+ confbox@0.2.2: {}
+
config-chain@1.1.13:
dependencies:
ini: 1.3.8
@@ -3268,7 +3713,7 @@ snapshots:
graceful-fs: 4.2.11
xdg-basedir: 5.1.0
- content-security-policy-parser@0.4.1: {}
+ consola@3.4.2: {}
core-util-is@1.0.3: {}
@@ -3293,6 +3738,8 @@ snapshots:
css-what@6.2.2: {}
+ cssom@0.5.0: {}
+
cssstyle@5.3.1(postcss@8.5.6):
dependencies:
'@asamuzakjp/css-color': 4.0.5
@@ -3339,8 +3786,16 @@ snapshots:
dependencies:
clone: 1.0.4
+ define-lazy-prop@2.0.0: {}
+
define-lazy-prop@3.0.0: {}
+ defu@6.1.4: {}
+
+ dequal@2.0.3: {}
+
+ destr@2.0.5: {}
+
doctrine@3.0.0:
dependencies:
esutils: 2.0.3
@@ -3367,6 +3822,14 @@ snapshots:
dependencies:
type-fest: 4.41.0
+ dotenv-expand@12.0.3:
+ dependencies:
+ dotenv: 16.6.1
+
+ dotenv@16.6.1: {}
+
+ dotenv@17.2.3: {}
+
eastasianwidth@0.2.0: {}
emoji-regex@10.6.0: {}
@@ -3384,6 +3847,12 @@ snapshots:
entities@6.0.1: {}
+ environment@1.1.0: {}
+
+ error-ex@1.3.4:
+ dependencies:
+ is-arrayish: 0.2.1
+
es-module-lexer@1.7.0: {}
es6-error@4.1.1: {}
@@ -3423,22 +3892,24 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-config-prettier@10.1.8(eslint@9.38.0):
+ escape-string-regexp@5.0.0: {}
+
+ eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)):
dependencies:
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
eslint-plugin-no-unsanitized@4.1.4(eslint@8.57.1):
dependencies:
eslint: 8.57.1
- eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.38.0))(eslint@9.38.0)(prettier@3.6.2):
+ eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.38.0(jiti@2.6.1)))(eslint@9.38.0(jiti@2.6.1))(prettier@3.6.2):
dependencies:
- eslint: 9.38.0
+ eslint: 9.38.0(jiti@2.6.1)
prettier: 3.6.2
prettier-linter-helpers: 1.0.0
synckit: 0.11.11
optionalDependencies:
- eslint-config-prettier: 10.1.8(eslint@9.38.0)
+ eslint-config-prettier: 10.1.8(eslint@9.38.0(jiti@2.6.1))
eslint-scope@7.2.2:
dependencies:
@@ -3497,9 +3968,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint@9.38.0:
+ eslint@9.38.0(jiti@2.6.1):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.1
'@eslint/config-helpers': 0.4.1
@@ -3533,6 +4004,8 @@ snapshots:
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
+ optionalDependencies:
+ jiti: 2.6.1
transitivePeerDependencies:
- supports-color
@@ -3566,10 +4039,12 @@ snapshots:
esutils@2.0.3: {}
- etag@1.8.1: {}
+ eventemitter3@5.0.1: {}
expect-type@1.2.2: {}
+ exsolve@1.0.7: {}
+
fast-deep-equal@3.1.3: {}
fast-diff@1.3.0: {}
@@ -3614,6 +4089,8 @@ snapshots:
dependencies:
flat-cache: 4.0.1
+ filesize@11.0.13: {}
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@@ -3651,6 +4128,10 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
+ form-data-encoder@4.1.0: {}
+
+ formdata-node@6.0.3: {}
+
fs-extra@11.3.2:
dependencies:
graceful-fs: 4.2.11
@@ -3675,6 +4156,17 @@ snapshots:
get-east-asian-width@1.4.0: {}
+ get-port-please@3.2.0: {}
+
+ giget@2.0.0:
+ dependencies:
+ citty: 0.1.6
+ consola: 3.4.2
+ defu: 6.1.4
+ node-fetch-native: 1.6.7
+ nypm: 0.6.2
+ pathe: 2.0.3
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -3713,8 +4205,6 @@ snapshots:
globals@14.0.0: {}
- globrex@0.1.2: {}
-
graceful-fs@4.2.10: {}
graceful-fs@4.2.11: {}
@@ -3733,12 +4223,16 @@ snapshots:
has-flag@4.0.0: {}
+ hookable@5.5.3: {}
+
html-encoding-sniffer@4.0.0:
dependencies:
whatwg-encoding: 3.1.1
html-escaper@2.0.2: {}
+ html-escaper@3.0.3: {}
+
htmlparser2@10.0.0:
dependencies:
domelementtype: 2.3.0
@@ -3777,6 +4271,8 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
+ import-meta-resolve@4.2.0: {}
+
imurmurhash@0.1.4: {}
index-to-position@1.2.0: {}
@@ -3798,6 +4294,8 @@ snapshots:
dependencies:
is-relative: 0.1.3
+ is-arrayish@0.2.1: {}
+
is-docker@2.2.1: {}
is-docker@3.0.0: {}
@@ -3806,6 +4304,12 @@ snapshots:
is-fullwidth-code-point@3.0.0: {}
+ is-fullwidth-code-point@4.0.0: {}
+
+ is-fullwidth-code-point@5.1.0:
+ dependencies:
+ get-east-asian-width: 1.4.0
+
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
@@ -3821,6 +4325,8 @@ snapshots:
global-directory: 4.0.1
is-path-inside: 4.0.0
+ is-interactive@2.0.0: {}
+
is-npm@6.1.0: {}
is-number@7.0.0: {}
@@ -3829,10 +4335,20 @@ snapshots:
is-path-inside@4.0.0: {}
+ is-plain-object@2.0.4:
+ dependencies:
+ isobject: 3.0.1
+
is-potential-custom-element-name@1.0.1: {}
+ is-primitive@3.0.1: {}
+
is-relative@0.1.3: {}
+ is-unicode-supported@1.3.0: {}
+
+ is-unicode-supported@2.1.0: {}
+
is-utf8@0.2.1: {}
is-wsl@2.2.0:
@@ -3849,6 +4365,8 @@ snapshots:
isexe@2.0.0: {}
+ isobject@3.0.1: {}
+
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
@@ -3876,6 +4394,8 @@ snapshots:
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
+ jiti@2.6.1: {}
+
jose@5.9.6: {}
js-tokens@4.0.0: {}
@@ -3920,12 +4440,16 @@ snapshots:
dependencies:
fast-deep-equal: 3.1.3
+ json-parse-even-better-errors@3.0.2: {}
+
json-schema-traverse@0.4.1: {}
json-schema-traverse@1.0.0: {}
json-stable-stringify-without-jsonify@1.0.1: {}
+ json5@2.2.3: {}
+
jsonfile@6.2.0:
dependencies:
universalify: 2.0.1
@@ -3943,6 +4467,8 @@ snapshots:
dependencies:
json-buffer: 3.0.1
+ kleur@3.0.3: {}
+
ky@1.12.0: {}
latest-version@9.0.0:
@@ -3965,12 +4491,50 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ lines-and-columns@2.0.4: {}
+
+ linkedom@0.18.12:
+ dependencies:
+ css-select: 5.2.2
+ cssom: 0.5.0
+ html-escaper: 3.0.3
+ htmlparser2: 10.0.0
+ uhyphen: 0.2.0
+
+ listr2@8.3.3:
+ dependencies:
+ cli-truncate: 4.0.0
+ colorette: 2.0.20
+ eventemitter3: 5.0.1
+ log-update: 6.1.0
+ rfdc: 1.4.1
+ wrap-ansi: 9.0.2
+
+ local-pkg@1.1.2:
+ dependencies:
+ mlly: 1.8.0
+ pkg-types: 2.3.0
+ quansync: 0.2.11
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
lodash.merge@4.6.2: {}
+ log-symbols@6.0.0:
+ dependencies:
+ chalk: 5.6.2
+ is-unicode-supported: 1.3.0
+
+ log-update@6.1.0:
+ dependencies:
+ ansi-escapes: 7.1.1
+ cli-cursor: 5.0.0
+ slice-ansi: 7.1.2
+ strip-ansi: 7.1.2
+ wrap-ansi: 9.0.2
+
loupe@3.2.1: {}
lru-cache@10.4.3: {}
@@ -3993,6 +4557,8 @@ snapshots:
make-error@1.3.6: {}
+ many-keys-map@2.0.1: {}
+
marky@1.3.0: {}
mdn-data@2.12.2: {}
@@ -4004,6 +4570,12 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
+ mimic-function@5.0.1: {}
+
+ minimatch@10.0.3:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.0
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -4016,6 +4588,13 @@ snapshots:
minipass@7.1.2: {}
+ mlly@1.8.0:
+ dependencies:
+ acorn: 8.15.0
+ pathe: 2.0.3
+ pkg-types: 1.3.1
+ ufo: 1.6.1
+
mrmime@2.0.1: {}
ms@2.1.3: {}
@@ -4027,10 +4606,14 @@ snapshots:
array-union: 3.0.1
minimatch: 3.1.2
+ nano-spawn@1.0.3: {}
+
nanoid@3.3.11: {}
natural-compare@1.4.0: {}
+ node-fetch-native@1.6.7: {}
+
node-forge@1.3.1: {}
node-notifier@10.0.1:
@@ -4042,16 +4625,38 @@ snapshots:
uuid: 8.3.2
which: 2.0.2
+ normalize-path@3.0.0: {}
+
nth-check@2.1.1:
dependencies:
boolbase: 1.0.0
+ nypm@0.6.2:
+ dependencies:
+ citty: 0.1.6
+ consola: 3.4.2
+ pathe: 2.0.3
+ pkg-types: 2.3.0
+ tinyexec: 1.0.1
+
+ ofetch@1.4.1:
+ dependencies:
+ destr: 2.0.5
+ node-fetch-native: 1.6.7
+ ufo: 1.6.1
+
+ ohash@2.0.11: {}
+
on-exit-leak-free@2.1.2: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
+ onetime@7.0.0:
+ dependencies:
+ mimic-function: 5.0.1
+
open@10.2.0:
dependencies:
default-browser: 5.2.1
@@ -4059,6 +4664,12 @@ snapshots:
is-inside-container: 1.0.0
wsl-utils: 0.1.0
+ open@8.4.2:
+ dependencies:
+ define-lazy-prop: 2.0.0
+ is-docker: 2.2.1
+ is-wsl: 2.2.0
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -4068,6 +4679,18 @@ snapshots:
type-check: 0.4.0
word-wrap: 1.2.5
+ ora@8.2.0:
+ dependencies:
+ chalk: 5.6.2
+ cli-cursor: 5.0.0
+ cli-spinners: 2.9.2
+ is-interactive: 2.0.0
+ is-unicode-supported: 2.1.0
+ log-symbols: 6.0.0
+ stdin-discarder: 0.2.2
+ string-width: 7.2.0
+ strip-ansi: 7.1.2
+
os-shim@0.1.3: {}
p-limit@3.1.0:
@@ -4093,6 +4716,14 @@ snapshots:
dependencies:
callsites: 3.1.0
+ parse-json@7.1.1:
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ error-ex: 1.3.4
+ json-parse-even-better-errors: 3.0.2
+ lines-and-columns: 2.0.4
+ type-fest: 3.13.1
+
parse-json@8.3.0:
dependencies:
'@babel/code-frame': 7.27.1
@@ -4133,6 +4764,8 @@ snapshots:
pend@1.2.0: {}
+ perfect-debounce@2.0.0: {}
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -4159,6 +4792,32 @@ snapshots:
sonic-boom: 4.2.0
thread-stream: 3.1.0
+ pino@9.7.0:
+ dependencies:
+ atomic-sleep: 1.0.0
+ fast-redact: 3.5.0
+ on-exit-leak-free: 2.1.2
+ pino-abstract-transport: 2.0.0
+ pino-std-serializers: 7.0.0
+ process-warning: 5.0.0
+ quick-format-unescaped: 4.0.4
+ real-require: 0.2.0
+ safe-stable-stringify: 2.5.0
+ sonic-boom: 4.2.0
+ thread-stream: 3.1.0
+
+ pkg-types@1.3.1:
+ dependencies:
+ confbox: 0.1.8
+ mlly: 1.8.0
+ pathe: 2.0.3
+
+ pkg-types@2.3.0:
+ dependencies:
+ confbox: 0.2.2
+ exsolve: 1.0.7
+ pathe: 2.0.3
+
postcss@8.5.6:
dependencies:
nanoid: 3.3.11
@@ -4181,18 +4840,41 @@ snapshots:
dependencies:
make-error: 1.3.6
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
proto-list@1.2.4: {}
+ publish-browser-extension@3.0.3:
+ dependencies:
+ cac: 6.7.14
+ consola: 3.4.2
+ dotenv: 17.2.3
+ form-data-encoder: 4.1.0
+ formdata-node: 6.0.3
+ listr2: 8.3.3
+ ofetch: 1.4.1
+ zod: 4.1.12
+
punycode@2.3.1: {}
pupa@3.3.0:
dependencies:
escape-goat: 4.0.0
+ quansync@0.2.11: {}
+
queue-microtask@1.2.3: {}
quick-format-unescaped@4.0.4: {}
+ rc9@2.1.2:
+ dependencies:
+ defu: 6.1.4
+ destr: 2.0.5
+
rc@1.2.8:
dependencies:
deep-extend: 0.6.0
@@ -4210,6 +4892,8 @@ snapshots:
string_decoder: 1.1.1
util-deprecate: 1.0.2
+ readdirp@4.1.2: {}
+
real-require@0.2.0: {}
registry-auth-token@5.1.0:
@@ -4226,8 +4910,15 @@ snapshots:
resolve-from@4.0.0: {}
+ restore-cursor@5.1.0:
+ dependencies:
+ onetime: 7.0.0
+ signal-exit: 4.1.0
+
reusify@1.1.0: {}
+ rfdc@1.4.1: {}
+
rimraf@3.0.2:
dependencies:
glob: 7.2.3
@@ -4280,10 +4971,17 @@ snapshots:
dependencies:
xmlchars: 2.2.0
+ scule@1.3.0: {}
+
semver@7.7.2: {}
semver@7.7.3: {}
+ set-value@4.1.0:
+ dependencies:
+ is-plain-object: 2.0.4
+ is-primitive: 3.0.1
+
setimmediate@1.0.5: {}
shebang-command@2.0.0:
@@ -4306,6 +5004,18 @@ snapshots:
mrmime: 2.0.1
totalist: 3.0.1
+ sisteransi@1.0.5: {}
+
+ slice-ansi@5.0.0:
+ dependencies:
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 4.0.0
+
+ slice-ansi@7.1.2:
+ dependencies:
+ ansi-styles: 6.2.3
+ is-fullwidth-code-point: 5.1.0
+
sonic-boom@4.2.0:
dependencies:
atomic-sleep: 1.0.0
@@ -4319,6 +5029,8 @@ snapshots:
source-map@0.6.1: {}
+ source-map@0.7.6: {}
+
spawn-sync@1.0.15:
dependencies:
concat-stream: 1.6.2
@@ -4334,6 +5046,8 @@ snapshots:
std-env@3.10.0: {}
+ stdin-discarder@0.2.2: {}
+
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
@@ -4379,6 +5093,8 @@ snapshots:
strip-json-comments@3.1.1: {}
+ strip-json-comments@5.0.2: {}
+
strip-json-comments@5.0.3: {}
strip-literal@3.1.0:
@@ -4415,6 +5131,8 @@ snapshots:
tinyexec@0.3.2: {}
+ tinyexec@1.0.1: {}
+
tinyglobby@0.2.15:
dependencies:
fdir: 6.5.0(picomatch@4.0.3)
@@ -4452,9 +5170,7 @@ snapshots:
dependencies:
typescript: 5.9.3
- tsconfck@3.1.6(typescript@5.9.3):
- optionalDependencies:
- typescript: 5.9.3
+ tslib@2.8.1: {}
type-check@0.4.0:
dependencies:
@@ -4462,31 +5178,66 @@ snapshots:
type-fest@0.20.2: {}
+ type-fest@3.13.1: {}
+
type-fest@4.41.0: {}
typedarray@0.0.6: {}
- typescript-eslint@8.46.1(eslint@9.38.0)(typescript@5.9.3):
+ typescript-eslint@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0)(typescript@5.9.3))(eslint@9.38.0)(typescript@5.9.3)
- '@typescript-eslint/parser': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
+ '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.46.1(eslint@9.38.0)(typescript@5.9.3)
- eslint: 9.38.0
+ '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.38.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
typescript@5.9.3: {}
+ ufo@1.6.1: {}
+
+ uhyphen@0.2.0: {}
+
undici-types@6.21.0: {}
undici-types@7.14.0: {}
undici@7.16.0: {}
+ unimport@5.5.0:
+ dependencies:
+ acorn: 8.15.0
+ escape-string-regexp: 5.0.0
+ estree-walker: 3.0.3
+ local-pkg: 1.1.2
+ magic-string: 0.30.19
+ mlly: 1.8.0
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ pkg-types: 2.3.0
+ scule: 1.3.0
+ strip-literal: 3.1.0
+ tinyglobby: 0.2.15
+ unplugin: 2.3.10
+ unplugin-utils: 0.3.1
+
universalify@2.0.1: {}
+ unplugin-utils@0.3.1:
+ dependencies:
+ pathe: 2.0.3
+ picomatch: 4.0.3
+
+ unplugin@2.3.10:
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ acorn: 8.15.0
+ picomatch: 4.0.3
+ webpack-virtual-modules: 0.6.2
+
upath@2.0.1: {}
update-notifier@7.3.1:
@@ -4510,13 +5261,13 @@ snapshots:
uuid@8.3.2: {}
- vite-node@3.2.4(@types/node@24.8.1):
+ vite-node@3.2.4(@types/node@24.8.1)(jiti@2.6.1):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.1.10(@types/node@24.8.1)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -4531,18 +5282,7 @@ snapshots:
- tsx
- yaml
- vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.1.10(@types/node@24.8.1)):
- dependencies:
- debug: 4.4.3
- globrex: 0.1.2
- tsconfck: 3.1.6(typescript@5.9.3)
- optionalDependencies:
- vite: 7.1.10(@types/node@24.8.1)
- transitivePeerDependencies:
- - supports-color
- - typescript
-
- vite@7.1.10(@types/node@24.8.1):
+ vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1):
dependencies:
esbuild: 0.25.11
fdir: 6.5.0(picomatch@4.0.3)
@@ -4553,12 +5293,13 @@ snapshots:
optionalDependencies:
'@types/node': 24.8.1
fsevents: 2.3.3
+ jiti: 2.6.1
- vitest@3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jsdom@27.0.1(postcss@8.5.6)):
+ vitest@3.2.4(@types/node@24.8.1)(@vitest/ui@3.2.4)(happy-dom@20.0.5)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6)):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.1.10(@types/node@24.8.1))
+ '@vitest/mocker': 3.2.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -4576,8 +5317,8 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.10(@types/node@24.8.1)
- vite-node: 3.2.4(@types/node@24.8.1)
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)
+ vite-node: 3.2.4(@types/node@24.8.1)(jiti@2.6.1)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 24.8.1
@@ -4611,6 +5352,31 @@ snapshots:
dependencies:
defaults: 1.0.4
+ web-ext-run@0.2.4:
+ dependencies:
+ '@babel/runtime': 7.28.2
+ '@devicefarmer/adbkit': 3.3.8
+ chrome-launcher: 1.2.0
+ debounce: 1.2.1
+ es6-error: 4.1.1
+ firefox-profile: 4.7.0
+ fx-runner: 1.4.0
+ multimatch: 6.0.0
+ node-notifier: 10.0.1
+ parse-json: 7.1.1
+ pino: 9.7.0
+ promise-toolbox: 0.21.0
+ set-value: 4.1.0
+ source-map-support: 0.5.21
+ strip-bom: 5.0.0
+ strip-json-comments: 5.0.2
+ tmp: 0.2.5
+ update-notifier: 7.3.1
+ watchpack: 2.4.4
+ zip-dir: 2.0.0
+ transitivePeerDependencies:
+ - supports-color
+
web-ext@9.0.0:
dependencies:
'@babel/runtime': 7.28.4
@@ -4649,6 +5415,8 @@ snapshots:
webidl-conversions@8.0.0: {}
+ webpack-virtual-modules@0.6.2: {}
+
whatwg-encoding@3.1.1:
dependencies:
iconv-lite: 0.6.3
@@ -4714,6 +5482,69 @@ snapshots:
dependencies:
is-wsl: 3.1.0
+ wxt@0.20.11(@types/node@24.8.1)(jiti@2.6.1)(rollup@4.52.5):
+ dependencies:
+ '@1natsu/wait-element': 4.1.2
+ '@aklinker1/rollup-plugin-visualizer': 5.12.0(rollup@4.52.5)
+ '@webext-core/fake-browser': 1.3.2
+ '@webext-core/isolated-element': 1.1.2
+ '@webext-core/match-patterns': 1.0.3
+ '@wxt-dev/browser': 0.1.4
+ '@wxt-dev/storage': 1.2.6
+ async-mutex: 0.5.0
+ c12: 3.3.1(magicast@0.3.5)
+ cac: 6.7.14
+ chokidar: 4.0.3
+ ci-info: 4.3.1
+ consola: 3.4.2
+ defu: 6.1.4
+ dotenv: 17.2.3
+ dotenv-expand: 12.0.3
+ esbuild: 0.25.11
+ fast-glob: 3.3.3
+ filesize: 11.0.13
+ fs-extra: 11.3.2
+ get-port-please: 3.2.0
+ giget: 2.0.0
+ hookable: 5.5.3
+ import-meta-resolve: 4.2.0
+ is-wsl: 3.1.0
+ json5: 2.2.3
+ jszip: 3.10.1
+ linkedom: 0.18.12
+ magicast: 0.3.5
+ minimatch: 10.0.3
+ nano-spawn: 1.0.3
+ normalize-path: 3.0.0
+ nypm: 0.6.2
+ ohash: 2.0.11
+ open: 10.2.0
+ ora: 8.2.0
+ perfect-debounce: 2.0.0
+ picocolors: 1.1.1
+ prompts: 2.4.2
+ publish-browser-extension: 3.0.3
+ scule: 1.3.0
+ unimport: 5.5.0
+ vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)
+ vite-node: 3.2.4(@types/node@24.8.1)(jiti@2.6.1)
+ web-ext-run: 0.2.4
+ transitivePeerDependencies:
+ - '@types/node'
+ - canvas
+ - jiti
+ - less
+ - lightningcss
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
xdg-basedir@5.1.0: {}
xml-name-validator@5.0.0: {}
@@ -4752,3 +5583,5 @@ snapshots:
dependencies:
async: 3.2.6
jszip: 3.10.1
+
+ zod@4.1.12: {}
diff --git a/public/content-styles.css b/public/content-styles.css
new file mode 100644
index 0000000..cdd2461
--- /dev/null
+++ b/public/content-styles.css
@@ -0,0 +1,22 @@
+/* Optional: Add a floating export button on Claude.ai pages */
+.claude-exporter-button {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ z-index: 9999;
+ background: #5436da;
+ color: white;
+ border: none;
+ border-radius: 50%;
+ width: 60px;
+ height: 60px;
+ font-size: 24px;
+ cursor: pointer;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ transition: all 0.3s;
+}
+
+.claude-exporter-button:hover {
+ background: #4329b8;
+ transform: scale(1.1);
+}
diff --git a/public/icon128.png b/public/icon128.png
new file mode 100644
index 0000000..23a9b5a
Binary files /dev/null and b/public/icon128.png differ
diff --git a/public/icon16.png b/public/icon16.png
new file mode 100644
index 0000000..06b49c2
Binary files /dev/null and b/public/icon16.png differ
diff --git a/public/icon48.png b/public/icon48.png
new file mode 100644
index 0000000..6bad8be
Binary files /dev/null and b/public/icon48.png differ
diff --git a/public/popup-header.png b/public/popup-header.png
new file mode 100644
index 0000000..de149e6
Binary files /dev/null and b/public/popup-header.png differ
diff --git a/src/chrome/scripts/popup.ts b/src/chrome/scripts/popup.ts
index 57ceb8a..cbec0b7 100644
--- a/src/chrome/scripts/popup.ts
+++ b/src/chrome/scripts/popup.ts
@@ -170,7 +170,9 @@ async function handleExportCurrent(): Promise {
* Handle browse conversations button
*/
function handleBrowseConversations(): void {
- void chrome.tabs.create({ url: chrome.runtime.getURL('src/chrome/scripts/browse.html') });
+ void chrome.tabs.create({
+ url: chrome.runtime.getURL('src/chrome/scripts/browse.html'),
+ });
}
/**
diff --git a/src/firefox/scripts/popup.ts b/src/firefox/scripts/popup.ts
index 97b1ef7..88dd716 100644
--- a/src/firefox/scripts/popup.ts
+++ b/src/firefox/scripts/popup.ts
@@ -168,7 +168,9 @@ async function handleExportCurrent(): Promise {
* Handle browse conversations button
*/
function handleBrowseConversations(): void {
- void browser.tabs.create({ url: browser.runtime.getURL('src/firefox/scripts/browse.html') });
+ void browser.tabs.create({
+ url: browser.runtime.getURL('src/firefox/scripts/browse.html'),
+ });
}
/**
diff --git a/tsconfig.json b/tsconfig.json
index 496b7df..0f776db 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -38,25 +38,13 @@
/* Path Mapping */
"baseUrl": ".",
"paths": {
- "@/*": ["src/*"]
+ "@/*": ["entrypoints/*"],
+ "~/*": ["src/*"]
},
/* Browser Extension Types */
"types": ["firefox-webext-browser", "vitest/globals"]
},
- "include": [
- "src/**/*.ts",
- "vite.config.ts",
- "vite.content.config.ts",
- "vite.content-chrome.config.ts",
- "vite.content-firefox.config.ts",
- "eslint.config.js"
- ],
- "exclude": [
- "node_modules",
- "dist",
- "src/**/*.js",
- "src/chrome/scripts/**/*",
- "src/firefox/scripts/**/*"
- ]
+ "include": ["entrypoints/**/*.ts", "src/**/*.ts", "wxt.config.ts", "*.config.ts", ".wxt/types/**/*.d.ts"],
+ "exclude": ["node_modules", "dist", ".wxt/**/*", "!.wxt/types/**/*.d.ts"]
}
diff --git a/type-check/.wxt/tsconfig.json b/type-check/.wxt/tsconfig.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/type-check/.wxt/tsconfig.json
@@ -0,0 +1 @@
+{}
diff --git a/vite.config.ts b/vite.config.ts
deleted file mode 100644
index 324b038..0000000
--- a/vite.config.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { defineConfig } from 'vite';
-import webExtension from '@samrum/vite-plugin-web-extension';
-import tsconfigPaths from 'vite-tsconfig-paths';
-import { resolve, dirname } from 'path';
-import { fileURLToPath } from 'url';
-import { readFileSync } from 'fs';
-
-const __dirname = dirname(fileURLToPath(import.meta.url));
-
-// Determine target platform from mode or environment
-function getTargetFromMode(mode: string): 'firefox' | 'chrome' {
- return mode === 'firefox' ? 'firefox' : 'chrome';
-}
-
-export default defineConfig(({ mode }) => {
- const target = getTargetFromMode(mode);
- const manifestPath = resolve(__dirname, `src/${target}/manifest.json`);
- const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<
- string,
- unknown
- >;
-
- return {
- plugins: [
- tsconfigPaths(),
- webExtension({
- manifest,
- useDynamicUrlWebAccessibleResources: false,
- additionalInputs: {
- html: [
- `src/${target}/scripts/browse.html`,
- `src/${target}/scripts/options.html`,
- ],
- scripts: [`src/${target}/scripts/content.ts`],
- },
- }),
- ],
- resolve: {
- alias: {
- '@': resolve(__dirname, 'src'),
- },
- },
- build: {
- outDir: `dist/${target}`,
- emptyOutDir: true,
- sourcemap: true,
- rollupOptions: {
- output: {
- entryFileNames: '[name].js',
- chunkFileNames: '[name].js',
- assetFileNames: '[name].[ext]',
- },
- },
- },
- test: {
- globals: true,
- environment: 'happy-dom',
- setupFiles: ['./src/tests/setup.ts'],
- include: ['src/tests/**/*.test.ts'],
- coverage: {
- provider: 'v8',
- reporter: ['text', 'json', 'html'],
- exclude: [
- 'node_modules/',
- 'dist/',
- 'src/tests/',
- '**/*.d.ts',
- '**/*.config.*',
- '**/mockData',
- ],
- },
- },
- };
-});
diff --git a/vite.content-chrome.config.ts b/vite.content-chrome.config.ts
deleted file mode 100644
index 47b7ff2..0000000
--- a/vite.content-chrome.config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { defineConfig } from 'vite';
-import { resolve, dirname } from 'path';
-import { fileURLToPath } from 'url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url));
-
-export default defineConfig({
- build: {
- outDir: 'dist-temp-content-chrome',
- emptyOutDir: true,
- lib: {
- entry: resolve(__dirname, 'src/chrome/scripts/content.ts'),
- name: 'ContentScript',
- formats: ['iife'],
- fileName: () => 'content.js',
- },
- rollupOptions: {
- output: {
- extend: true,
- },
- },
- },
-});
diff --git a/vite.content-firefox.config.ts b/vite.content-firefox.config.ts
deleted file mode 100644
index 84b9097..0000000
--- a/vite.content-firefox.config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { defineConfig } from 'vite';
-import { resolve, dirname } from 'path';
-import { fileURLToPath } from 'url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url));
-
-export default defineConfig({
- build: {
- outDir: 'dist-temp-content-firefox',
- emptyOutDir: true,
- lib: {
- entry: resolve(__dirname, 'src/firefox/scripts/content.ts'),
- name: 'ContentScript',
- formats: ['iife'],
- fileName: () => 'content.js',
- },
- rollupOptions: {
- output: {
- extend: true,
- },
- },
- },
-});
diff --git a/vite.content.config.ts b/vite.content.config.ts
deleted file mode 100644
index fbb126f..0000000
--- a/vite.content.config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { defineConfig } from 'vite';
-import { resolve, dirname } from 'path';
-import { fileURLToPath } from 'url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url));
-
-export default defineConfig({
- build: {
- outDir: 'dist-temp-content',
- emptyOutDir: true,
- lib: {
- entry: resolve(__dirname, 'src/content.ts'),
- name: 'ContentScript',
- formats: ['iife'],
- fileName: () => 'content.js',
- },
- rollupOptions: {
- output: {
- extend: true,
- },
- },
- },
-});
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..9d9fbf8
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,31 @@
+///
+import { defineConfig } from 'vitest/config';
+import { resolve } from 'path';
+
+export default defineConfig({
+ resolve: {
+ alias: {
+ '~': resolve(__dirname, 'src'),
+ },
+ },
+ test: {
+ globals: true,
+ environment: 'happy-dom',
+ setupFiles: ['./src/tests/setup.ts'],
+ include: ['src/tests/**/*.test.ts'],
+ coverage: {
+ provider: 'v8',
+ reporter: ['text', 'json', 'html'],
+ exclude: [
+ 'node_modules/',
+ 'dist/',
+ '.wxt/',
+ '.output/',
+ 'src/tests/',
+ '**/*.d.ts',
+ '**/*.config.*',
+ '**/mockData',
+ ],
+ },
+ },
+});
diff --git a/wxt.config.ts b/wxt.config.ts
new file mode 100644
index 0000000..a06f485
--- /dev/null
+++ b/wxt.config.ts
@@ -0,0 +1,23 @@
+import { defineConfig } from 'wxt';
+import { resolve } from 'path';
+
+// https://wxt.dev/api/config.html
+export default defineConfig({
+ manifest: {
+ name: 'Claude Conversation Exporter',
+ description: 'Export your Claude.ai conversations with full message history',
+ permissions: ['activeTab', 'storage'],
+ host_permissions: ['https://claude.ai/*'],
+ },
+ imports: false,
+ vite: () => ({
+ resolve: {
+ alias: {
+ '~': resolve(__dirname, 'src'),
+ },
+ },
+ }),
+ runner: {
+ startUrls: ['https://claude.ai'],
+ },
+});