From 275f9e02fa487af59f2e23a2c2fdd6a56458c99a Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Wed, 9 Jul 2025 16:26:24 -0400 Subject: [PATCH] fix: convert ALL relative URLs to absolute in translated pages - Convert CSS links, script sources, image sources, and navigation links - Use current page URL as base for proper relative URL resolution - Skip data: URLs, fragments, and protocol-relative URLs - Ensure all assets load properly in new window context --- src/translation.js | 52 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/translation.js b/src/translation.js index d8b85c0..1e78108 100644 --- a/src/translation.js +++ b/src/translation.js @@ -378,22 +378,52 @@ export async function translateCurrentPage(targetLanguage) { // Replace the body content with translated content doc.body.innerHTML = translatedContent; - // Convert relative CSS URLs to absolute URLs so they work in new window - const cssLinks = doc.querySelectorAll('link[rel="stylesheet"]'); + // Convert ALL relative URLs to absolute URLs so they work in new window const currentOrigin = window.location.origin; + const currentUrl = window.location.href; + // Convert CSS links + const cssLinks = doc.querySelectorAll('link[rel="stylesheet"]'); cssLinks.forEach(link => { const href = link.getAttribute('href'); - - // Skip if already absolute URL - if (href.startsWith('http') || href.startsWith('//')) { - return; + if (href && !href.startsWith('http') && !href.startsWith('//')) { + const absoluteUrl = new URL(href, currentUrl).href; + link.setAttribute('href', absoluteUrl); + console.log('Converted CSS URL:', href, '->', absoluteUrl); + } + }); + + // Convert script sources + const scripts = doc.querySelectorAll('script[src]'); + scripts.forEach(script => { + const src = script.getAttribute('src'); + if (src && !src.startsWith('http') && !src.startsWith('//')) { + const absoluteUrl = new URL(src, currentUrl).href; + script.setAttribute('src', absoluteUrl); + console.log('Converted script URL:', src, '->', absoluteUrl); + } + }); + + // Convert image sources + const images = doc.querySelectorAll('img[src]'); + images.forEach(img => { + const src = img.getAttribute('src'); + if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith('data:')) { + const absoluteUrl = new URL(src, currentUrl).href; + img.setAttribute('src', absoluteUrl); + console.log('Converted image URL:', src, '->', absoluteUrl); + } + }); + + // Convert link hrefs (for navigation) + const links = doc.querySelectorAll('a[href]'); + links.forEach(link => { + const href = link.getAttribute('href'); + if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith('#') && !href.startsWith('mailto:') && !href.startsWith('tel:')) { + const absoluteUrl = new URL(href, currentUrl).href; + link.setAttribute('href', absoluteUrl); + console.log('Converted link URL:', href, '->', absoluteUrl); } - - // Convert relative URL to absolute - const absoluteUrl = new URL(href, currentOrigin).href; - link.setAttribute('href', absoluteUrl); - console.log('Converted CSS URL:', href, '->', absoluteUrl); }); return doc.documentElement.outerHTML;