feat: preload images

This commit is contained in:
2026-03-19 22:07:02 +01:00
parent 1c67eb0cff
commit b384c70c39
9 changed files with 412 additions and 6 deletions
+2 -1
View File
@@ -17,6 +17,7 @@ templ Head(cfg config.Cfg, title string) {
<script src="/js/htmx.min.js"></script>
<script src="/js/head-support.min.js"></script>
<script src="/js/preload.min.js"></script>
<script src="/js/preload-links.min.js"></script>
<script src={ cfg.Tracking.ScriptSrc } data-website-id={ cfg.Tracking.WebsiteID }></script>
for _, h := range templer.GetHeader(ctx) {
@templ.Raw(h)
@@ -29,7 +30,7 @@ templ Base(cfg config.Cfg, title string) {
<!DOCTYPE html>
<html lang={ translate.Language(ctx) }>
@Head(cfg, title)
<body class="bg-black dark" hx-boost="true" hx-target="main" hx-ext="head-support,preload">
<body class="bg-black dark" hx-boost="true" hx-target="main" hx-ext="head-support,preload,preload-links">
<header
class="fixed z-50 mix-blend-difference p-1 w-full flex justify-between items-start"
>
+1 -1
View File
@@ -13,7 +13,7 @@ templ Home(pages []page.PageHeader) {
class="flex items-center justify-center h-full "
href={ translate.Path(ctx, "/"+page.UID) }
preload="mouseover"
preload-images="true"
hx-load-links="true"
>
<h2
class="text-3xl font-bold text-white hover:underline text-shadow-lg"
+63
View File
@@ -0,0 +1,63 @@
/**
* @file preload-links.js
* @description HTMX extension to extract <link rel="preload"> from preloaded HTML responses.
* @generated By opencode (AI Agent)
* @model gemini-3-flash-preview
* @date Thu Mar 19 2026
*/
(function () {
// Save the original XHR methods
const originalOpen = XMLHttpRequest.prototype.open;
const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
const originalSend = XMLHttpRequest.prototype.send;
// We need to track which XHRs are preloads
XMLHttpRequest.prototype.open = function () {
this._isHtmxPreload = false;
return originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
if (header.toLowerCase() === "hx-preloaded" && value === "true") {
this._isHtmxPreload = true;
}
return originalSetRequestHeader.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function () {
if (this._isHtmxPreload) {
this.addEventListener("load", function () {
// Parse the response text as HTML
const parser = new DOMParser();
const doc = parser.parseFromString(this.responseText, "text/html");
// Find all preload links
const links = doc.querySelectorAll('link[rel="preload"]');
links.forEach((link) => {
const href = link.getAttribute("href");
// Only inject if the current document doesn't already have it
if (
href &&
!document.querySelector(`link[rel="preload"][href="${href}"]`)
) {
const newLink = document.createElement("link");
newLink.rel = "preload";
newLink.href = href;
// Copy relevant attributes
["as", "type", "media", "fetchpriority", "crossorigin"].forEach(
(attr) => {
const val = link.getAttribute(attr);
if (val) newLink.setAttribute(attr, val);
},
);
document.head.appendChild(newLink);
}
});
});
}
return originalSend.apply(this, arguments);
};
})();
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
(function(){const p=XMLHttpRequest.prototype.open,a=XMLHttpRequest.prototype.setRequestHeader,l=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(){return this._isHtmxPreload=!1,p.apply(this,arguments)},XMLHttpRequest.prototype.setRequestHeader=function(r,o){return r.toLowerCase()==="hx-preloaded"&&o==="true"&&(this._isHtmxPreload=!0),a.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){return this._isHtmxPreload&&this.addEventListener("load",function(){new DOMParser().parseFromString(this.responseText,"text/html").querySelectorAll('link[rel="preload"]').forEach(n=>{const t=n.getAttribute("href");if(t&&!document.querySelector(`link[rel="preload"][href="${t}"]`)){const e=document.createElement("link");e.rel="preload",e.href=t,["as","type","media","fetchpriority","crossorigin"].forEach(s=>{const i=n.getAttribute(s);i&&e.setAttribute(s,i)}),document.head.appendChild(e)}})}),l.apply(this,arguments)}})();