diff --git a/packages/web/server/lib/preview/proxy-runtime.js b/packages/web/server/lib/preview/proxy-runtime.js index 36a21266..7aefcc5d 100644 --- a/packages/web/server/lib/preview/proxy-runtime.js +++ b/packages/web/server/lib/preview/proxy-runtime.js @@ -1041,21 +1041,6 @@ export const rewritePreviewBody = ({ bodyText, proxyBasePath, targetOrigin, kind } return value; }; - const rewriteHtml = (text) => text - .replace(/\b(src|href|action)=(['"])([^'"]*)\2/gi, (_match, attr, quote, value) => { - return `${attr}=${quote}${rewriteResourceUrl(value)}${quote}`; - }) - .replace(/\bsrcset=(['"])([^'"]*)\1/gi, (_match, quote, value) => { - const rewritten = String(value).split(',').map((part) => { - const trimmed = part.trim(); - if (!trimmed) return trimmed; - const segments = trimmed.split(/\s+/); - const url = segments[0] || ''; - segments[0] = rewriteResourceUrl(url); - return segments.join(' '); - }).join(', '); - return `srcset=${quote}${rewritten}${quote}`; - }); const stripPreviewCspMeta = (text) => text .replace(/]*\bhttp-equiv\s*=\s*(['"])content-security-policy\1)[^>]*>/gi, '') .replace(/]*\bhttp-equiv\s*=\s*content-security-policy\b)[^>]*>/gi, ''); @@ -1077,6 +1062,35 @@ export const rewritePreviewBody = ({ bodyText, proxyBasePath, targetOrigin, kind .replace(/\bimport\(\s*(['"])\/(?!\/)([^'"]*)\1\s*\)/gi, (_match, quote, path) => { return `import(${quote}${rewriteResourceUrl(`/${path}`)}${quote})`; }); + const rewriteInlineModuleScripts = (text) => text.replace( + /`; + }, + ); + const rewriteHtml = (text) => rewriteInlineModuleScripts(text + .replace(/\b(src|href|action)=(['"])([^'"]*)\2/gi, (_match, attr, quote, value) => { + return `${attr}=${quote}${rewriteResourceUrl(value)}${quote}`; + }) + .replace(/\bsrcset=(['"])([^'"]*)\1/gi, (_match, quote, value) => { + const rewritten = String(value).split(',').map((part) => { + const trimmed = part.trim(); + if (!trimmed) return trimmed; + const segments = trimmed.split(/\s+/); + const url = segments[0] || ''; + segments[0] = rewriteResourceUrl(url); + return segments.join(' '); + }).join(', '); + return `srcset=${quote}${rewritten}${quote}`; + })); if (kind === 'html') return stripPreviewCspMeta(rewriteHtml(bodyText)); if (kind === 'css') return rewriteCss(bodyText); diff --git a/packages/web/server/lib/preview/proxy-runtime.test.js b/packages/web/server/lib/preview/proxy-runtime.test.js index 06770a2c..e810a173 100644 --- a/packages/web/server/lib/preview/proxy-runtime.test.js +++ b/packages/web/server/lib/preview/proxy-runtime.test.js @@ -97,6 +97,21 @@ describe('preview body URL rewriting', () => { expect(output).toContain('const url = "/api/data";'); }); + it('rewrites inline module imports in HTML responses', () => { + const input = [ + '', + '', + ].join(''); + const output = rewrite(input, 'html'); + + expect(output).toContain('from "/api/preview/proxy/abc123/@react-refresh"'); + expect(output).toContain('window.__vite_plugin_react_preamble_installed__ = true;'); + expect(output).toContain('const refreshUrl = "/@react-refresh";'); + }); + it('removes CSP meta tags that block the preview bridge', () => { const input = '