@@ -5,11 +5,24 @@ import { fileURLToPath } from 'node:url'
55
66const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
77const app = express ( )
8- const PORT = 3000
8+ const PORT = 3001
99
1010// Store HAR data
1111const harCache = new Map < string , any > ( )
1212
13+ // Check if WXT dev server is running
14+ async function checkDevServer ( ) : Promise < boolean > {
15+ try {
16+ const response = await fetch ( 'http://localhost:3000/@vite/client' , {
17+ method : 'HEAD' ,
18+ signal : AbortSignal . timeout ( 2000 )
19+ } )
20+ return response . ok
21+ } catch {
22+ return false
23+ }
24+ }
25+
1326// Load and cache HAR file
1427async function loadHar ( filename : string ) {
1528 if ( harCache . has ( filename ) ) {
@@ -29,10 +42,28 @@ app.get('/', async (req, res) => {
2942 const harDir = path . join ( __dirname , 'har' )
3043 const files = await fs . readdir ( harDir )
3144 const harFiles = files . filter ( file => file . endsWith ( '.har' ) )
45+ const devServerRunning = await checkDevServer ( )
46+
47+ const devServerWarning = ! devServerRunning ? `
48+ <div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 15px; margin-bottom: 20px;">
49+ <strong>⚠️ Warning:</strong> WXT dev server is not running on localhost:3000<br>
50+ <small>Gitcasso-enabled links won't work. Run <code>npm run dev</code> to start the server and <strong>then refresh this page</strong>.</small>
51+ </div>
52+ ` : ''
3253
3354 const links = harFiles . map ( file => {
3455 const basename = path . basename ( file , '.har' )
35- return `<li><a href="/page/${ file } ">${ basename } </a></li>`
56+ return `
57+ <li>
58+ <div style="margin-bottom: 10px; font-weight: bold; color: #555;">${ basename } </div>
59+ <div style="display: flex; gap: 10px;">
60+ <a href="/page/${ file } " style="flex: 1; text-align: center;">🔍 Clean</a>
61+ <a href="/page/${ file } /gitcasso" style="flex: 1; text-align: center; ${ ! devServerRunning ? 'opacity: 0.5; pointer-events: none;' : '' } ">
62+ 🚀 Gitcasso-enabled
63+ </a>
64+ </div>
65+ </li>
66+ `
3667 } ) . join ( '' )
3768
3869 res . send ( `
@@ -43,27 +74,30 @@ app.get('/', async (req, res) => {
4374 <style>
4475 body {
4576 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
46- max-width: 600px ;
77+ max-width: 700px ;
4778 margin: 50px auto;
4879 padding: 20px;
4980 }
5081 h1 { color: #333; }
5182 ul { list-style: none; padding: 0; }
52- li { margin: 10px 0 ; }
83+ li { margin: 20px 0; padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef ; }
5384 a {
5485 display: block;
55- padding: 15px 20px;
56- background: #f8f9fa ;
86+ padding: 12px 20px;
87+ background: #fff ;
5788 text-decoration: none;
5889 color: #333;
5990 border-radius: 6px;
60- border: 1px solid #e9ecef;
91+ border: 1px solid #dee2e6;
92+ transition: all 0.2s;
6193 }
62- a:hover { background: #e9ecef; }
94+ a:hover:not([style*="pointer-events: none"]) { background: #e9ecef; transform: translateY(-1px); }
95+ code { background: #f1f3f4; padding: 2px 4px; border-radius: 3px; font-size: 0.9em; }
6396 </style>
6497</head>
6598<body>
6699 <h1>📄 HAR Page Viewer</h1>
100+ ${ devServerWarning }
67101 <p>Select a recorded page to view:</p>
68102 <ul>${ links } </ul>
69103</body>
@@ -110,11 +144,66 @@ app.get('/page/:filename', async (req, res) => {
110144 }
111145} )
112146
147+ // Serve the main HTML page from HAR with Gitcasso content script injected
148+ app . get ( '/page/:filename/gitcasso' , async ( req , res ) => {
149+ try {
150+ const filename = req . params . filename
151+ if ( ! filename . endsWith ( '.har' ) ) {
152+ return res . status ( 400 ) . send ( 'Invalid file type' )
153+ }
154+
155+ const harData = await loadHar ( filename )
156+
157+ // Find the main HTML response
158+ const mainEntry = harData . log . entries . find ( ( entry : any ) =>
159+ entry . request . url . includes ( 'github.com' ) &&
160+ entry . response . content . mimeType ?. includes ( 'text/html' ) &&
161+ entry . response . content . text
162+ )
163+
164+ if ( ! mainEntry ) {
165+ return res . status ( 404 ) . send ( 'No HTML content found in HAR file' )
166+ }
167+
168+ let html = mainEntry . response . content . text
169+
170+ // Replace external URLs with local asset URLs
171+ html = html . replace (
172+ / h t t p s : \/ \/ ( g i t h u b \. c o m | a s s e t s \. g i t h u b \. c o m | a v a t a r s \. g i t h u b u s e r c o n t e n t \. c o m | u s e r - i m a g e s \. g i t h u b u s e r c o n t e n t \. c o m ) / g,
173+ `/asset/${ filename . replace ( '.har' , '' ) } `
174+ )
175+
176+ // Inject the Gitcasso content script at the end of the body
177+ const contentScriptTag = `
178+ <script>
179+ // Load the Gitcasso content script from the dev server
180+ const script = document.createElement('script');
181+ script.src = 'http://localhost:3000/content-scripts/content.js';
182+ script.onload = () => console.log('Gitcasso content script loaded successfully');
183+ script.onerror = () => console.error('Failed to load Gitcasso content script - is the dev server running?');
184+ document.body.appendChild(script);
185+ </script>
186+ `
187+
188+ // Insert script before closing body tag, or at the end if no body tag
189+ if ( html . includes ( '</body>' ) ) {
190+ html = html . replace ( '</body>' , `${ contentScriptTag } </body>` )
191+ } else {
192+ html += contentScriptTag
193+ }
194+
195+ res . send ( html )
196+ } catch ( error ) {
197+ console . error ( 'Error serving page:' , error )
198+ res . status ( 500 ) . send ( 'Error loading page' )
199+ }
200+ } )
201+
113202// Serve assets from HAR file
114203app . get ( '/asset/:harname/*' , async ( req , res ) => {
115204 try {
116205 const harname = req . params . harname + '.har'
117- const assetPath = req . params [ 0 ]
206+ const assetPath = ( req . params as any ) [ 0 ] as string
118207
119208 const harData = await loadHar ( harname )
120209
0 commit comments