@@ -199,7 +199,7 @@ app.get('/corpus/:key/:mode(clean|gitcasso)', async (req, res) => {
199199 html = html . replace ( regex , `/asset/${ key } ` )
200200 } )
201201 if ( mode === 'gitcasso' ) {
202- html = await injectGitcassoScript ( key , html )
202+ html = injectGitcassoScriptForHAR ( key , html )
203203 }
204204 return res . send ( html )
205205 } else if ( entry . type === 'html' ) {
@@ -211,7 +211,7 @@ app.get('/corpus/:key/:mode(clean|gitcasso)', async (req, res) => {
211211 html = stripCSPFromHTML ( html )
212212
213213 if ( mode === 'gitcasso' ) {
214- html = await injectGitcassoScript ( key , html )
214+ html = await injectGitcassoScriptForHTML ( key , html )
215215 }
216216
217217 // Set permissive headers for HTML corpus
@@ -365,7 +365,206 @@ function stripCSPFromHTML(html: string): string {
365365 return html
366366}
367367
368- async function injectGitcassoScript ( key : string , html : string ) : Promise < string > {
368+ // HAR version - uses fetch() to load content script (original approach)
369+ function injectGitcassoScriptForHAR ( key : string , html : string ) : string {
370+ const urlParts = getUrlParts ( key )
371+
372+ // Inject patched content script with location patching
373+ const contentScriptTag =
374+ `
375+ <script>
376+ console.log('Loading Gitcasso with mocked location:', '${ urlParts . href } ');
377+
378+ // Fetch and patch the content script to remove webextension-polyfill issues
379+ fetch('/chrome-mv3-dev/content-scripts/content.js')
380+ .then(response => response.text())
381+ .then(code => {
382+ console.log('Fetched content script, patching webextension-polyfill and detectLocation...');
383+
384+ // Replace the problematic webextension-polyfill error check
385+ let patchedCode = code.replace(
386+ 'throw new Error("This script should only be loaded in a browser extension.")',
387+ 'console.warn("Webextension-polyfill check bypassed for corpus testing")'
388+ );
389+ window.gitcassoMockLocation = {
390+ host: '${ urlParts . host } ',
391+ pathname: '${ urlParts . pathname } '
392+ };
393+
394+ // Execute the patched script with browser API mocks prepended
395+ const browserMocks = 'window.chrome=window.chrome||{runtime:{getURL:path=>"chrome-extension://gitcasso-test/"+path,onMessage:{addListener:()=>{}},sendMessage:()=>Promise.resolve(),id:"gitcasso-test"}};window.browser=window.chrome;';
396+ const script = document.createElement('script');
397+ script.textContent = browserMocks + patchedCode;
398+ document.head.appendChild(script);
399+ console.log('Gitcasso content script loaded with location patching for:', '` +
400+ urlParts . href +
401+ `');
402+ })
403+ .catch(error => {
404+ console.error('Failed to load and patch content script:', error);
405+ });
406+
407+ // Create floating rebuild button
408+ const rebuildButton = document.createElement('div');
409+ rebuildButton.id = 'gitcasso-rebuild-btn';
410+ rebuildButton.innerHTML = '🔄';
411+ rebuildButton.title = 'Rebuild Extension';
412+ rebuildButton.style.cssText = \`
413+ position: fixed;
414+ top: 20px;
415+ right: 20px;
416+ width: 50px;
417+ height: 50px;
418+ background: #007acc;
419+ color: white;
420+ border-radius: 50%;
421+ display: flex;
422+ align-items: center;
423+ justify-content: center;
424+ font-size: 20px;
425+ cursor: pointer;
426+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
427+ z-index: 999999;
428+ user-select: none;
429+ transition: all 0.2s ease;
430+ font-family: system-ui, -apple-system, sans-serif;
431+ \`;
432+
433+ rebuildButton.addEventListener('mouseenter', () => {
434+ rebuildButton.style.transform = 'scale(1.1)';
435+ rebuildButton.style.backgroundColor = '#005a9e';
436+ });
437+
438+ rebuildButton.addEventListener('mouseleave', () => {
439+ rebuildButton.style.transform = 'scale(1)';
440+ rebuildButton.style.backgroundColor = '#007acc';
441+ });
442+
443+ rebuildButton.addEventListener('click', async () => {
444+ try {
445+ rebuildButton.innerHTML = '⏳';
446+ rebuildButton.style.backgroundColor = '#ffa500';
447+ rebuildButton.title = 'Rebuilding...';
448+
449+ const response = await fetch('/rebuild', {
450+ method: 'POST',
451+ headers: { 'Content-Type': 'application/json' }
452+ });
453+
454+ const result = await response.json();
455+
456+ if (result.success) {
457+ rebuildButton.innerHTML = '✅';
458+ rebuildButton.style.backgroundColor = '#28a745';
459+ rebuildButton.title = 'Build successful! Reloading...';
460+
461+ setTimeout(() => {
462+ location.reload(true);
463+ }, 1000);
464+ } else {
465+ rebuildButton.innerHTML = '❌';
466+ rebuildButton.style.backgroundColor = '#dc3545';
467+ rebuildButton.title = 'Build failed: ' + (result.error || result.message);
468+
469+ setTimeout(() => {
470+ rebuildButton.innerHTML = '🔄';
471+ rebuildButton.style.backgroundColor = '#007acc';
472+ rebuildButton.title = 'Rebuild Extension';
473+ }, 3000);
474+ }
475+ } catch (error) {
476+ console.error('Rebuild failed:', error);
477+ rebuildButton.innerHTML = '❌';
478+ rebuildButton.style.backgroundColor = '#dc3545';
479+ rebuildButton.title = 'Network error: ' + error.message;
480+
481+ setTimeout(() => {
482+ rebuildButton.innerHTML = '🔄';
483+ rebuildButton.style.backgroundColor = '#007acc';
484+ rebuildButton.title = 'Rebuild Extension';
485+ }, 3000);
486+ }
487+ });
488+
489+ document.body.appendChild(rebuildButton);
490+
491+ // Create CommentSpot display
492+ const commentSpotDisplay = document.createElement('div');
493+ commentSpotDisplay.id = 'gitcasso-comment-spots';
494+ commentSpotDisplay.style.cssText =
495+ 'position: fixed;' +
496+ 'top: 80px;' +
497+ 'right: 20px;' +
498+ 'width: 400px;' +
499+ 'max-height: 400px;' +
500+ 'background: rgba(255, 255, 255, 0.95);' +
501+ 'border: 1px solid #ddd;' +
502+ 'border-radius: 8px;' +
503+ 'padding: 15px;' +
504+ 'font-family: Monaco, Menlo, Ubuntu Mono, monospace;' +
505+ 'font-size: 11px;' +
506+ 'line-height: 1.4;' +
507+ 'overflow-y: auto;' +
508+ 'z-index: 999998;' +
509+ 'box-shadow: 0 4px 12px rgba(0,0,0,0.2);' +
510+ 'backdrop-filter: blur(10px);';
511+
512+ // Simplified display formatting
513+ const styles = {
514+ header: 'font-weight: bold; margin-bottom: 8px; color: #333;',
515+ spotContainer: 'margin-bottom: 12px; padding: 8px; border: 1px solid #eee; border-radius: 4px;',
516+ spotTitle: 'font-weight: bold; color: #555;',
517+ jsonPre: 'margin: 4px 0; font-size: 10px;',
518+ textareaHeader: 'font-weight: bold; color: #007acc; margin-top: 8px;',
519+ textareaPre: 'margin: 4px 0; font-size: 10px; color: #666;',
520+ noInfo: 'color: #999; font-style: italic; margin-top: 4px;',
521+ empty: 'color: #666; font-style: italic;'
522+ };
523+
524+ function updateCommentSpotDisplay() {
525+ const textareas = document.querySelectorAll('textarea');
526+ const spotsFound = [];
527+
528+ for (const textarea of textareas) {
529+ const forValue = 'id=' + textarea.id + ' name=' + textarea.name + ' className=' + textarea.className;
530+ const enhancedItem = window.gitcassoTextareaRegistry ? window.gitcassoTextareaRegistry.get(textarea) : undefined;
531+ if (enhancedItem) {
532+ spotsFound.push({
533+ for: forValue,
534+ spot: enhancedItem.spot,
535+ title: enhancedItem.enhancer.tableTitle(enhancedItem.spot),
536+ });
537+ } else {
538+ spotsFound.push({
539+ for: forValue,
540+ spot: 'NO_SPOT',
541+ });
542+ }
543+ }
544+
545+ console.log('Enhanced textareas:', spotsFound.filter(s => s.spot !== 'NO_SPOT').length);
546+ console.log('All textareas on page:', textareas.length);
547+ commentSpotDisplay.innerHTML = '<div style="' + styles.header + '"><pre>${ urlParts . href } \\n' + JSON.stringify(spotsFound, null, 2) + '</pre></div>';
548+ }
549+
550+ // Initial update
551+ setTimeout(updateCommentSpotDisplay, 100);
552+
553+ // Update display periodically
554+ setInterval(updateCommentSpotDisplay, 2000);
555+
556+ document.body.appendChild(commentSpotDisplay);
557+ </script>
558+ `
559+ if ( html . includes ( '</body>' ) ) {
560+ return html . replace ( '</body>' , `${ contentScriptTag } </body>` )
561+ } else {
562+ return html + contentScriptTag
563+ }
564+ }
565+
566+ // HTML version - embeds content script directly to avoid CSP issues
567+ async function injectGitcassoScriptForHTML ( key : string , html : string ) : Promise < string > {
369568 const urlParts = getUrlParts ( key )
370569
371570 // Read and embed the content script directly to avoid CSP issues
0 commit comments