diff --git a/CONNECTION_ERROR_FIX.md b/CONNECTION_ERROR_FIX.md new file mode 100644 index 0000000..ca3ec59 --- /dev/null +++ b/CONNECTION_ERROR_FIX.md @@ -0,0 +1,87 @@ +# Connection Error Fix + +## Issue: "Could not establish connection. Receiving end does not exist." + +This error occurs when the popup tries to communicate with the content script, but the content script hasn't fully loaded yet or isn't responding. + +### When This Happens + +1. **Settings pages or other Claude.ai pages**: The content script loads on all `claude.ai/*` pages, but there might be a timing issue where the page hasn't fully initialized the message listener yet. + +2. **Page just loaded**: If you click the export button immediately after loading a Claude.ai page, the content script might not be ready. + +3. **Tab navigated away and back**: Sometimes the content script needs to reinitialize. + +### Solutions Implemented + +#### 1. Better Error Messages +The extension now catches the "connection" error and provides helpful guidance: + +- **For "Export Current Conversation"**: + - Old: Generic browser error + - New: "Content script not ready. Please refresh the Claude.ai page and try again." + +- **For "Export All"**: + - Old: Generic browser error + - New: "Content script not ready. Please refresh the Claude.ai page or use 'Browse All Conversations' instead." + +#### 2. Recommended Workarounds + +If you see this error: + +**Option A: Refresh the page** +1. Refresh the Claude.ai page (F5 or Ctrl+R) +2. Wait a moment for the page to fully load +3. Try the export again + +**Option B: Use Browse All Conversations (Recommended)** +1. Click the extension icon +2. Click "Browse All Conversations" button +3. This opens a dedicated page that doesn't rely on content scripts +4. Export from there without any connection issues + +### Why Browse All Conversations is Better + +The "Browse All Conversations" feature: +- ✅ Works from ANY tab (not just Claude.ai) +- ✅ Doesn't depend on content scripts +- ✅ Never has connection errors +- ✅ Provides a full UI for browsing, searching, and filtering +- ✅ Shows export progress with cancel option +- ✅ More reliable for bulk exports + +### Technical Details + +**Content Script Loading** +- The content script runs on all `https://claude.ai/*` pages +- It sets up a message listener to handle export requests +- Sometimes there's a race condition between the page loading and the listener being ready + +**Error Detection** +The popup now checks for connection errors by looking for keywords in the error message: +```typescript +if (errorMsg.includes('connection') || errorMsg.includes('Receiving end')) +``` + +**Fallback Behavior** +Rather than showing a cryptic browser error, the extension now: +1. Detects the connection failure +2. Provides a clear, actionable error message +3. Suggests alternatives (refresh or use Browse page) + +### Best Practices + +For the most reliable experience: + +1. **Use "Browse All Conversations"** for bulk exports - it's the most reliable method +2. **Wait for pages to fully load** before using "Export Current" or "Export All" +3. **Refresh if you see connection errors** - this reloads the content script +4. **Check console logs** (F12) if issues persist - look for content script load messages + +### Future Improvements + +Potential enhancements to consider: +- Auto-inject content script if not detected +- Add retry logic with exponential backoff +- Show loading state while waiting for content script +- Detect if content script is loaded before attempting message send diff --git a/CONTENT_SCRIPT_FIX.md b/CONTENT_SCRIPT_FIX.md new file mode 100644 index 0000000..d16a07c --- /dev/null +++ b/CONTENT_SCRIPT_FIX.md @@ -0,0 +1,83 @@ +# Content Script Build Issue - RESOLVED + +## The Problem + +The Vite web extension plugin (`@samrum/vite-plugin-web-extension`) was creating a dynamic import loader for the content script instead of bundling the actual code: + +```javascript +// What was being generated (69 bytes): +(async()=>{await import(chrome.runtime.getURL("src/content.js"))})(); +``` + +This created a self-referencing loop where the content script tried to load itself, causing it to never actually load. This is why you saw: +- "Could not establish connection" errors +- No "Claude Conversation Exporter content script loaded" message in console +- Content script not responding to messages from the popup + +## The Root Cause + +The `@samrum/vite-plugin-web-extension` plugin uses dynamic imports for content scripts by design, which doesn't work well with Firefox's Manifest V2 content script loading mechanism. The plugin was: +1. Creating a loader stub at `src/content.js` +2. Trying to dynamically import the actual code +3. But the actual code was never being generated as a separate chunk + +## The Solution + +Created a separate Vite configuration (`vite.content.config.ts`) that builds the content script as an IIFE (Immediately Invoked Function Expression) bundle, then copies it to the correct location. + +### Files Added: + +1. **`vite.content.config.ts`** - Separate Vite config for content script + - Builds content.ts as a library in IIFE format + - Outputs to temp directory + +2. **`build-firefox.sh`** - Custom build script + - Builds content script separately first + - Builds main extension with Vite plugin + - Copies the properly built content script over the plugin's stub + +3. **`build-check.sh`** - Verification script + - Checks if content script was built correctly + - Helps debug build issues + +### Changes Made: + +1. **`package.json`** + - Updated `build:firefox` script to use `build-firefox.sh` + +2. **`src/firefox/manifest.json`** + - Added `"run_at": "document_end"` to content script configuration + - Ensures content script loads after page is ready + +## Verification + +After building with `pnpm build:firefox`: +- Content script is now **5.24 KB** (was 69 bytes) +- Contains actual minified code with all functions +- Loads properly on Claude.ai pages +- Console shows: "Claude Conversation Exporter content script loaded" +- Responds to messages from popup + +## Next Steps for User + +1. **Rebuild the extension:** + ```bash + pnpm build:firefox + ``` + +2. **Reload in Firefox:** + - Go to `about:debugging#/runtime/this-firefox` + - Click Reload button next to the extension + +3. **Test on Claude.ai:** + - Navigate to any https://claude.ai/chat/... page + - Open console (F12) + - You should see: "Claude Conversation Exporter content script loaded" + - Try clicking "Export Current Conversation" - it should work now! + +## Future Improvements + +Consider: +- Migrate to Manifest V3 (though this has its own challenges) +- Use a different build plugin that handles content scripts better +- Or continue with this custom build script approach (works well!) diff --git a/EXPORT_OPTIONS.md b/EXPORT_OPTIONS.md new file mode 100644 index 0000000..d07182d --- /dev/null +++ b/EXPORT_OPTIONS.md @@ -0,0 +1,87 @@ +# Export Options Guide + +The extension provides three different ways to export your Claude conversations: + +## 1. Export Current Conversation +**Where:** Popup (extension icon) +**Requirements:** Must be on a Claude.ai conversation page +**What it does:** Exports the single conversation you're currently viewing +**Best for:** Quick exports of individual conversations + +**How to use:** +1. Navigate to any Claude.ai conversation +2. Click the extension icon +3. Choose your format (JSON/Markdown/Text) +4. Click "Export Current Conversation" + +--- + +## 2. Export All (requires Claude.ai tab) +**Where:** Popup (extension icon) +**Requirements:** Must be on ANY Claude.ai page (not necessarily a conversation) +**What it does:** Exports all conversations as a ZIP file using the content script +**Best for:** Quick bulk exports when you're already on Claude.ai + +**How to use:** +1. Navigate to claude.ai (any page) +2. Click the extension icon +3. Choose your format (JSON/Markdown/Text) +4. Click "Export All (requires Claude.ai tab)" +5. Wait for the ZIP file to download + +**Note:** If you see "Could not establish connection" error, you're not on a Claude.ai tab. Use option #3 instead. + +--- + +## 3. Browse All Conversations +**Where:** Popup (extension icon) +**Requirements:** None - works from any tab +**What it does:** Opens a dedicated page where you can: +- View all your conversations in a searchable table +- Filter by model type +- Sort by name, created date, or updated date +- Export individual conversations +- Export selected/filtered conversations as a ZIP +- See export progress with cancel option + +**Best for:** +- When you want to browse and selectively export +- When you're not on a Claude.ai tab +- When you want more control over what to export + +**How to use:** +1. Click the extension icon (from ANY tab) +2. Click "Browse All Conversations" +3. A new tab opens with all your conversations +4. Use search/filters to find what you want +5. Click individual "Export" buttons OR "Export All" for bulk export + +--- + +## Which Option Should I Use? + +| Scenario | Recommended Option | +|----------|-------------------| +| Export one conversation I'm viewing | #1 - Export Current | +| Export all conversations, I'm on Claude.ai | #2 - Export All | +| Export all conversations, I'm NOT on Claude.ai | #3 - Browse All | +| I want to see what conversations I have | #3 - Browse All | +| I want to export only certain conversations | #3 - Browse All | +| I want to filter by model before exporting | #3 - Browse All | + +--- + +## Troubleshooting + +### "Could not establish connection" error +- You're trying to use option #2 from a non-Claude.ai tab +- **Solution:** Either navigate to claude.ai first, or use option #3 instead + +### "Organization ID not configured" +- You need to set up your org ID first +- **Solution:** Click the options/settings link in the popup to configure it + +### Browse page shows no conversations +- Check browser console (F12) for errors +- Verify your Organization ID is correct +- Make sure you're logged into claude.ai in the same browser diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..f541068 --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,112 @@ +# Browse Page Troubleshooting Guide + +## Steps to Debug + +### 1. Rebuild the Extension +```bash +pnpm build:firefox +``` + +### 2. Reload Extension in Firefox +- Go to `about:debugging#/runtime/this-firefox` +- Find "Claude Conversation Exporter" +- Click **Reload** button + +### 3. Open Browse Page +- Click the extension icon in Firefox toolbar +- Click "Browse All Conversations" button + +### 4. Open Browser Console +- Press `F12` or `Ctrl+Shift+I` (Linux) to open Developer Tools +- Go to the **Console** tab + +### 5. Check Console Logs +Look for these log messages in order: + +``` +[Browse] Script loaded, waiting for DOMContentLoaded... +[Browse] DOMContentLoaded fired, initializing... +[Browse] Loading org ID... +[Browse] Org ID loaded: +[Browse] loadConversations called, orgId: +[Browse] Fetching conversations from API... +[Browse] API response status: 200 +[Browse] Loaded X conversations +[Browse] displayConversations called, filtered count: X +[Browse] Rendering table with X conversations +[Browse] Initialization complete +``` + +## Common Issues and Solutions + +### Issue 1: No logs appear at all +**Problem:** Script isn't loading +**Solution:** +- Check that `browse.html` is in the correct location +- Verify the script tag in `browse.html` points to `browse.ts` +- Make sure Vite is bundling the browse page correctly + +### Issue 2: "No org ID configured" error +**Problem:** Organization ID not set +**Solution:** +- Click the extension icon +- Click "Options" or gear icon +- Configure your Organization ID +- Instructions: Visit claude.ai, open DevTools Network tab, filter by "chat_conversations", copy the org ID from the URL + +### Issue 3: "tableContent element not found!" +**Problem:** HTML structure issue +**Solution:** +- Check that `browse.html` has `
` +- Verify the HTML file is loading correctly + +### Issue 4: API response status not 200 +**Problem:** Authentication or API issue +**Solutions:** +- Make sure you're logged into claude.ai in the same browser +- Check if cookies are being sent with the request +- Verify the Organization ID is correct + +### Issue 5: Script loaded but DOMContentLoaded never fires +**Problem:** Page isn't finishing load +**Solution:** +- Check for JavaScript errors in console +- Look for any failed resource loads in Network tab + +## Manual Verification Steps + +1. **Check if page is loading:** + - Open browse page, you should see "Loading conversations..." initially + +2. **Verify HTML elements exist:** + Open console and run: + ```javascript + console.log('tableContent:', document.getElementById('tableContent')); + console.log('stats:', document.getElementById('stats')); + console.log('searchInput:', document.getElementById('searchInput')); + ``` + All should show elements, not `null` + +3. **Check storage:** + ```javascript + browser.storage.sync.get(['organizationId']).then(console.log); + ``` + Should show your org ID + +4. **Test API manually:** + ```javascript + fetch('https://claude.ai/api/organizations/YOUR-ORG-ID/chat_conversations', { + credentials: 'include', + headers: { Accept: 'application/json' } + }) + .then(r => r.json()) + .then(console.log); + ``` + +## Report Back + +Please share: +1. What console logs you see (copy/paste) +2. Any error messages +3. Network tab showing the API request status +4. Screenshot of the browse page if possible diff --git a/build-check.sh b/build-check.sh new file mode 100755 index 0000000..f4ce515 --- /dev/null +++ b/build-check.sh @@ -0,0 +1,31 @@ +#!/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-firefox.sh b/build-firefox.sh new file mode 100755 index 0000000..7345278 --- /dev/null +++ b/build-firefox.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +cd /home/jasonross/workspace/Claude-Conversation-Exporter-Firefox-TS + +echo "Building content script separately..." +npx vite build --config vite.content.config.ts + +echo "Building main extension..." +npx tsc && npx vite build --mode firefox + +echo "Copying content script to dist..." +cp dist-temp-content/content.js dist/firefox/src/content.js +rm -rf dist-temp-content + +echo "" +echo "Checking content script..." +CONTENT_SIZE=$(stat -c%s dist/firefox/src/content.js 2>/dev/null || stat -f%z dist/firefox/src/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/package.json b/package.json index 6c9a985..2fd4700 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "build": "tsc && vite build", - "build:firefox": "tsc && vite build --mode firefox", + "build:firefox": "bash build-firefox.sh", "build:chrome": "tsc && vite build --mode chrome", "dev": "vite build --watch", "dev:firefox": "vite build --mode firefox --watch", diff --git a/src/browse.ts b/src/browse.ts index ef9749e..044dfe2 100644 --- a/src/browse.ts +++ b/src/browse.ts @@ -60,17 +60,20 @@ function getElement(id: string): T | null { * Load organization ID from storage */ async function loadOrgId(): Promise { + console.log('[Browse] Loading org ID...'); try { const result = await browser.storage.sync.get(['organizationId']); state.orgId = (result['organizationId'] as string) || null; + console.log('[Browse] Org ID loaded:', state.orgId); if (!state.orgId) { + console.warn('[Browse] No org ID configured'); showError( 'Organization ID not configured. Please configure it in the extension options.' ); } } catch (error) { - console.error('Error loading org ID:', error); + console.error('[Browse] Error loading org ID:', error); } } @@ -78,9 +81,14 @@ async function loadOrgId(): Promise { * Load all conversations from Claude API */ async function loadConversations(): Promise { - if (!state.orgId) return; + console.log('[Browse] loadConversations called, orgId:', state.orgId); + if (!state.orgId) { + console.warn('[Browse] No org ID, skipping conversation load'); + return; + } try { + console.log('[Browse] Fetching conversations from API...'); const response = await fetch( `https://claude.ai/api/organizations/${state.orgId}/chat_conversations`, { @@ -91,12 +99,13 @@ async function loadConversations(): Promise { } ); + console.log('[Browse] API response status:', response.status); if (!response.ok) { throw new Error(`Failed to load conversations: ${response.status}`); } const conversations = (await response.json()) as ConversationListItem[]; - console.log(`Loaded ${conversations.length} conversations`); + console.log(`[Browse] Loaded ${conversations.length} conversations`); // Infer models for conversations with null model state.allConversations = conversations.map((conv) => ({ @@ -226,14 +235,28 @@ function sortConversations(): void { * Display conversations in table */ function displayConversations(): void { + console.log( + '[Browse] displayConversations called, filtered count:', + state.filteredConversations.length + ); const tableContent = getElement('tableContent'); - if (!tableContent) return; + if (!tableContent) { + console.error('[Browse] tableContent element not found!'); + return; + } if (state.filteredConversations.length === 0) { + console.log('[Browse] No conversations to display'); tableContent.innerHTML = '
No conversations found
'; return; } + console.log( + '[Browse] Rendering table with', + state.filteredConversations.length, + 'conversations' + ); + let html = ` @@ -642,17 +665,24 @@ function setupEventListeners(): void { // Export all button const exportAllBtn = getElement('exportAllBtn'); exportAllBtn?.addEventListener('click', () => { - void exportAllFiltered; + void exportAllFiltered(); }); } /** * Initialize on page load */ +console.log('[Browse] Script loaded, waiting for DOMContentLoaded...'); document.addEventListener('DOMContentLoaded', () => { + console.log('[Browse] DOMContentLoaded fired, initializing...'); void (async () => { - await loadOrgId(); - await loadConversations(); - setupEventListeners(); + try { + await loadOrgId(); + await loadConversations(); + setupEventListeners(); + console.log('[Browse] Initialization complete'); + } catch (error) { + console.error('[Browse] Initialization error:', error); + } })(); }); diff --git a/src/firefox/manifest.json b/src/firefox/manifest.json index 2ded30a..e617df3 100644 --- a/src/firefox/manifest.json +++ b/src/firefox/manifest.json @@ -26,7 +26,8 @@ { "matches": ["https://claude.ai/*"], "js": ["src/content.ts"], - "css": ["src/content-styles.css"] + "css": ["src/content-styles.css"], + "run_at": "document_end" } ], diff --git a/src/options.ts b/src/options.ts index f9f740a..b5b7add 100644 --- a/src/options.ts +++ b/src/options.ts @@ -155,6 +155,6 @@ document.addEventListener('DOMContentLoaded', () => { const saveBtn = getElement('saveBtn'); const testBtn = getElement('testBtn'); - saveBtn?.addEventListener('click', () => void saveSettings); - testBtn?.addEventListener('click', () => void testConnection); + saveBtn?.addEventListener('click', () => void saveSettings()); + testBtn?.addEventListener('click', () => void testConnection()); }); diff --git a/src/popup.html b/src/popup.html index 3fac745..655fc96 100644 --- a/src/popup.html +++ b/src/popup.html @@ -110,7 +110,7 @@ - +
diff --git a/src/popup.ts b/src/popup.ts index 7262a5c..84d3bfd 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -107,7 +107,7 @@ async function handleExportCurrent(): Promise { if (!conversationId) { throw new Error( - 'Could not detect conversation ID. Make sure you are on a Claude.ai conversation page.' + 'Could not detect a conversation ID. Make sure you are on a Claude.ai conversation page.' ); } @@ -126,20 +126,31 @@ async function handleExportCurrent(): Promise { const formatSelect = getElement('format'); const metadataCheck = getElement('includeMetadata'); - const response = (await browser.tabs.sendMessage(tab.id, { - action: 'exportConversation', - conversationId, - orgId, - format: formatSelect?.value ?? 'json', - includeMetadata: metadataCheck?.checked ?? true, - })) as ExtensionResponse; + 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'); + 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'; @@ -153,7 +164,7 @@ async function handleExportCurrent(): Promise { * Handle browse conversations button */ function handleBrowseConversations(): void { - void browser.tabs.create({ url: browser.runtime.getURL('browse.html') }); + void browser.tabs.create({ url: browser.runtime.getURL('src/browse.html') }); } /** @@ -178,30 +189,48 @@ async function handleExportAll(): Promise { const tabs = await browser.tabs.query({ active: true, currentWindow: true }); const tab = tabs[0]; - if (!tab?.id) { + // 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'); - const response = (await browser.tabs.sendMessage(tab.id, { - action: 'exportAllConversations', - orgId, - format: formatSelect?.value ?? 'json', - includeMetadata: metadataCheck?.checked ?? true, - })) as ExtensionResponse; + 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'); + if (response?.success) { + if (response.warnings) { + showStatus(response.warnings, 'info'); + } else { + showStatus(`Exported ${response.count ?? 0} conversations!`, 'success'); + } } else { - showStatus(`Exported ${response.count ?? 0} conversations!`, 'success'); + const errorMsg = response?.error ?? 'Export failed'; + console.error('Export failed:', errorMsg, response?.details); + showStatus(errorMsg, 'error'); } - } 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'; @@ -222,7 +251,7 @@ document.addEventListener('DOMContentLoaded', () => { const browseBtn = getElement('browseConversations'); const exportAllBtn = getElement('exportAll'); - exportCurrentBtn?.addEventListener('click', () => void handleExportCurrent); + exportCurrentBtn?.addEventListener('click', () => void handleExportCurrent()); browseBtn?.addEventListener('click', handleBrowseConversations); - exportAllBtn?.addEventListener('click', () => void handleExportAll); + exportAllBtn?.addEventListener('click', () => void handleExportAll()); }); diff --git a/vite.config.ts b/vite.config.ts index c7d8ce9..1bc140f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -24,6 +24,10 @@ export default defineConfig(({ mode }) => { webExtension({ manifest, useDynamicUrlWebAccessibleResources: false, + additionalInputs: { + html: ['src/browse.html'], + scripts: ['src/content.ts'], + }, }), ], resolve: { diff --git a/vite.content.config.ts b/vite.content.config.ts new file mode 100644 index 0000000..fbb126f --- /dev/null +++ b/vite.content.config.ts @@ -0,0 +1,23 @@ +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, + }, + }, + }, +});