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