1*e948b3e4Syifeizhao/** 2*e948b3e4Syifeizhao * HiRes Image: Enhances image sharpness by loading original files. 3*e948b3e4Syifeizhao */ 4*e948b3e4Syifeizhao(function() { 5*e948b3e4Syifeizhao "use strict"; 6*e948b3e4Syifeizhao 7*e948b3e4Syifeizhao const sharpen = function(img) { 8*e948b3e4Syifeizhao if (!img || img.dataset.hiResProcessed) return; 9*e948b3e4Syifeizhao 10*e948b3e4Syifeizhao try { 11*e948b3e4Syifeizhao const url = new URL(img.src); 12*e948b3e4Syifeizhao 13*e948b3e4Syifeizhao // Match images scaled by DokuWiki (containing w= or h=) 14*e948b3e4Syifeizhao if (url.searchParams.has('w') || url.searchParams.has('h')) { 15*e948b3e4Syifeizhao const w = url.searchParams.get('w'); 16*e948b3e4Syifeizhao const h = url.searchParams.get('h'); 17*e948b3e4Syifeizhao 18*e948b3e4Syifeizhao // Remove scaling parameters and security tokens to fetch original 19*e948b3e4Syifeizhao url.searchParams.delete('w'); 20*e948b3e4Syifeizhao url.searchParams.delete('h'); 21*e948b3e4Syifeizhao url.searchParams.delete('tok'); 22*e948b3e4Syifeizhao 23*e948b3e4Syifeizhao img.src = url.toString(); 24*e948b3e4Syifeizhao 25*e948b3e4Syifeizhao // Apply CSS constraints to maintain intended layout size 26*e948b3e4Syifeizhao if (w) { 27*e948b3e4Syifeizhao img.style.width = w + 'px'; 28*e948b3e4Syifeizhao img.style.height = 'auto'; 29*e948b3e4Syifeizhao } else if (h) { 30*e948b3e4Syifeizhao img.style.height = h + 'px'; 31*e948b3e4Syifeizhao img.style.width = 'auto'; 32*e948b3e4Syifeizhao } 33*e948b3e4Syifeizhao 34*e948b3e4Syifeizhao // Optimization for High-DPI (Retina) displays 35*e948b3e4Syifeizhao img.style.imageRendering = '-webkit-optimize-contrast'; 36*e948b3e4Syifeizhao img.dataset.hiResProcessed = "true"; 37*e948b3e4Syifeizhao } 38*e948b3e4Syifeizhao } catch (e) { 39*e948b3e4Syifeizhao // Ignore parsing errors for non-standard URLs 40*e948b3e4Syifeizhao } 41*e948b3e4Syifeizhao }; 42*e948b3e4Syifeizhao 43*e948b3e4Syifeizhao const scan = function() { 44*e948b3e4Syifeizhao const sel = 'img.media, img.medialeft, img.mediaright, img.mediacenter'; 45*e948b3e4Syifeizhao document.querySelectorAll(sel).forEach(sharpen); 46*e948b3e4Syifeizhao }; 47*e948b3e4Syifeizhao 48*e948b3e4Syifeizhao // Run on initial page load 49*e948b3e4Syifeizhao if (document.readyState === 'loading') { 50*e948b3e4Syifeizhao document.addEventListener('DOMContentLoaded', scan); 51*e948b3e4Syifeizhao } else { 52*e948b3e4Syifeizhao scan(); // Run immediately 53*e948b3e4Syifeizhao } 54*e948b3e4Syifeizhao 55*e948b3e4Syifeizhao // Dynamic observer for editors (like Prosemirror) or async content 56*e948b3e4Syifeizhao const observer = new MutationObserver(function(mutations) { 57*e948b3e4Syifeizhao mutations.forEach(function(mutation) { 58*e948b3e4Syifeizhao if (mutation.addedNodes) { 59*e948b3e4Syifeizhao mutation.addedNodes.forEach(function(node) { 60*e948b3e4Syifeizhao if (node.nodeType === 1) { 61*e948b3e4Syifeizhao if (node.tagName === 'IMG') { 62*e948b3e4Syifeizhao sharpen(node); 63*e948b3e4Syifeizhao } else { 64*e948b3e4Syifeizhao node.querySelectorAll('img').forEach(sharpen); 65*e948b3e4Syifeizhao } 66*e948b3e4Syifeizhao } 67*e948b3e4Syifeizhao }); 68*e948b3e4Syifeizhao } 69*e948b3e4Syifeizhao }); 70*e948b3e4Syifeizhao }); 71*e948b3e4Syifeizhao 72*e948b3e4Syifeizhao observer.observe(document.body, { childList: true, subtree: true }); 73*e948b3e4Syifeizhao})();