diff --git a/extension/manifest.json b/extension/manifest.json index 1e27937..a3df04a 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -42,5 +42,17 @@ }, "description": "Toggle InsightReply Sidebar" } - } + }, + "web_accessible_resources": [ + { + "resources": [ + "src/assets/*", + "assets/*" + ], + "matches": [ + "https://twitter.com/*", + "https://x.com/*" + ] + } + ] } \ No newline at end of file diff --git a/extension/src/content/sidebar-mount.ts b/extension/src/content/sidebar-mount.ts index 13d9ea6..9b7fe9c 100644 --- a/extension/src/content/sidebar-mount.ts +++ b/extension/src/content/sidebar-mount.ts @@ -8,13 +8,16 @@ const currentTweetData = ref(null) const sidebarVisible = ref(false) let isMounted = false +let isMounting = false -function initSidebar() { - if (isMounted) return +async function initSidebar() { + if (isMounted || isMounting) return let host = document.getElementById(MOUNT_ID) if (host) return + isMounting = true + // 1. Create Host Element host = document.createElement('div') host.id = MOUNT_ID @@ -45,17 +48,51 @@ function initSidebar() { ` shadowRoot.appendChild(container) - // 4. Inject Styles - const injectStyles = () => { - const styles = document.querySelectorAll('style, link[rel="stylesheet"]') - styles.forEach(style => { - shadowRoot.appendChild(style.cloneNode(true)) - }) + // 4. Inject Styles (Bypassing X.com CSP via fetch) + const injectStyles = async () => { + try { + // Check for Vite dev mode styles first + const devStyles = document.querySelectorAll('style[data-vite-dev-id]') + if (devStyles.length > 0) { + devStyles.forEach(style => shadowRoot.appendChild(style.cloneNode(true))) + console.log('[InsightReply] Injected dev styles into shadow DOM') + return + } + + // Production mode: fetch the CSS file directly to bypass rigid CSP + // CRXJS usually puts built CSS in assets/index-[hash].css + const cssUrl = chrome.runtime.getURL('assets/index.css') + // In Vite dev mode the raw file might be available + const devUrl = chrome.runtime.getURL('src/assets/tailwind.css') + + const urlToFetch = chrome.runtime.id.includes('extension') ? cssUrl : devUrl + + const response = await fetch(urlToFetch) + if (response.ok) { + const cssText = await response.text() + const styleEl = document.createElement('style') + styleEl.textContent = cssText + shadowRoot.appendChild(styleEl) + console.log('[InsightReply] Successfully injected fetched CSS into shadow DOM') + } else { + console.warn('[InsightReply] Failed to fetch CSS file directly, falling back to basic link tag') + const linkEl = document.createElement('link') + linkEl.rel = 'stylesheet' + linkEl.href = chrome.runtime.getURL('src/assets/tailwind.css') + shadowRoot.appendChild(linkEl) + } + } catch (err) { + console.error('[InsightReply] Error injecting styles:', err) + } } - injectStyles() + + // Inject and wait + await injectStyles() // 5. Create Vue App with reactive provide const app = createApp(Sidebar) + + isMounting = false app.provide('currentTweetData', currentTweetData) app.provide('sidebarVisible', sidebarVisible) app.mount(container)