feat: self-host HTMX 2.0.10 and Hyperscript 0.9.91, remove unpkg CDN
- Download htmx.min.js v2.0.10 and _hyperscript.min.js v0.9.91 locally - Update head-scripts.html to load from /static/ instead of unpkg CDN - Remove https://unpkg.com from CSP script-src whitelist - Update all documentation references to reflect self-hosted paths - No breaking changes: all hx-* attributes are HTMX 2.0 compatible
This commit is contained in:
@@ -1316,7 +1316,7 @@ end
|
||||
<script type="text/hyperscript" src="/static/hyperscript/color-theme._hs"></script>
|
||||
|
||||
<!-- 2. Then load hyperscript library -->
|
||||
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
|
||||
<script src="/static/hyperscript/_hyperscript.min.js"></script>
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
+2
-2
@@ -988,7 +988,7 @@ isHTMX := r.Header.Get("HX-Request") != ""
|
||||
hx-push-url="/?lang=en"
|
||||
class="lang-btn">
|
||||
English
|
||||
</button>
|
||||
</button>
|
||||
|
||||
<button
|
||||
hx-get="/cv?lang=es"
|
||||
@@ -1669,7 +1669,7 @@ func RateLimitMiddleware(limiter *IPRateLimiter) func(http.Handler) http.Handler
|
||||
class="lang-btn active"
|
||||
hx-get="/cv?lang=en"
|
||||
hx-target="#cv-content"
|
||||
hx-swap="innerHTML"
|
||||
hx-swap="innerHTML"
|
||||
hx-push-url="/?lang=en"
|
||||
onclick="setActive(this)">
|
||||
English
|
||||
|
||||
@@ -147,7 +147,7 @@ static/hyperscript/
|
||||
<script type="text/hyperscript" src="/static/hyperscript/keyboard._hs"></script>
|
||||
<script type="text/hyperscript" src="/static/hyperscript/zoom._hs"></script>
|
||||
<script type="text/hyperscript" src="/static/hyperscript/pdf-modal._hs"></script>
|
||||
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
|
||||
<script src="/static/hyperscript/_hyperscript.min.js"></script>
|
||||
```
|
||||
|
||||
## Required Functions
|
||||
@@ -288,5 +288,5 @@ end
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-11-30
|
||||
**Hyperscript Version**: 0.9.14
|
||||
**Hyperscript Version**: 0.9.91
|
||||
**Status**: MANDATORY - ALWAYS FOLLOW
|
||||
|
||||
@@ -202,7 +202,7 @@ func Setup(cvHandler *handlers.CVHandler, healthHandler *handlers.HealthHandler)
|
||||
<meta charset="UTF-8">
|
||||
<title>Contact Form</title>
|
||||
<!-- Include HTMX -->
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
<script src="/static/htmx/htmx.min.js"></script>
|
||||
<style>
|
||||
.form-group { margin-bottom: 1rem; }
|
||||
label { display: block; margin-bottom: 0.5rem; }
|
||||
|
||||
+11
-11
@@ -170,7 +170,7 @@ POST /switch-language
|
||||
```go
|
||||
// Strong CSP policy
|
||||
Content-Security-Policy: default-src 'self';
|
||||
script-src 'self' 'unsafe-inline' https://unpkg.com https://cdn.jsdelivr.net;
|
||||
script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net;
|
||||
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
|
||||
...
|
||||
|
||||
@@ -221,8 +221,8 @@ go-git/go-git v5.16.4 // Git operations (no shell commands)
|
||||
**Frontend Dependencies:**
|
||||
```javascript
|
||||
// index.html - Using CDN with SRI
|
||||
htmx.org@1.9.10 (SRI: sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX...)
|
||||
hyperscript.org@0.9.14 (no SRI - ADD THIS)
|
||||
htmx 2.0.10 (self-hosted at /static/htmx/htmx.min.js)
|
||||
hyperscript 0.9.91 (self-hosted at /static/hyperscript/_hyperscript.min.js)
|
||||
iconify-icon@2.1.0 (no SRI - ADD THIS)
|
||||
```
|
||||
|
||||
@@ -259,9 +259,9 @@ iconify-icon@2.1.0 (no SRI - ADD THIS)
|
||||
|
||||
**Recommendations:**
|
||||
```html
|
||||
<!-- Add SRI hashes -->
|
||||
<script src="https://unpkg.com/hyperscript.org@0.9.14"
|
||||
integrity="sha384-[GENERATE_SRI_HASH]"
|
||||
<!-- HTMX and Hyperscript are now self-hosted (no SRI needed) -->
|
||||
<script src="/static/htmx/htmx.min.js"></script>
|
||||
<script src="/static/hyperscript/_hyperscript.min.js"></script>
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
|
||||
@@ -1112,7 +1112,7 @@ server {
|
||||
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
|
||||
# CSP (delegated to Go app, but backup here)
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://unpkg.com https://cdn.jsdelivr.net https://matomo.morenorub.io; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.iconify.design https://matomo.morenorub.io; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://matomo.morenorub.io; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.iconify.design https://matomo.morenorub.io; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" always;
|
||||
|
||||
# Hide Nginx version
|
||||
server_tokens off;
|
||||
@@ -1224,10 +1224,10 @@ go mod tidy
|
||||
|
||||
### Frontend Dependencies
|
||||
```bash
|
||||
# Check CDN resources for updates
|
||||
# HTMX: https://unpkg.com/htmx.org@latest
|
||||
# Hyperscript: https://unpkg.com/hyperscript.org@latest
|
||||
# Iconify: https://cdn.jsdelivr.net/npm/iconify-icon@latest
|
||||
# HTMX and Hyperscript are self-hosted (update by downloading new versions)
|
||||
# HTMX: static/htmx/htmx.min.js (currently 2.0.10)
|
||||
# Hyperscript: static/hyperscript/_hyperscript.min.js (currently 0.9.91)
|
||||
# Iconify (CDN): https://cdn.jsdelivr.net/npm/iconify-icon@latest
|
||||
|
||||
# Generate SRI hashes
|
||||
https://www.srihash.org/
|
||||
|
||||
@@ -222,7 +222,7 @@ func (h *CVHandler) renderContactError(w http.ResponseWriter, r *http.Request, e
|
||||
}
|
||||
|
||||
// Render the error template
|
||||
// Return 200 OK with error content - HTMX 1.9.x logs console.error for non-2xx responses
|
||||
// Return 200 OK with error content - HTMX logs console.error for non-2xx responses
|
||||
// Validation errors are expected form feedback, not system errors
|
||||
w.Header().Set(c.HeaderContentType, c.ContentTypeHTML)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
@@ -32,7 +32,7 @@ func SecurityHeaders(next http.Handler) http.Handler {
|
||||
|
||||
// Content Security Policy (comprehensive)
|
||||
csp := "default-src 'self'; " +
|
||||
"script-src 'self' 'unsafe-inline' https://unpkg.com https://cdn.jsdelivr.net https://esm.sh https://matomo.txeo.club; " +
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://esm.sh https://matomo.txeo.club; " +
|
||||
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
|
||||
"font-src 'self' https://fonts.gstatic.com; " +
|
||||
"img-src 'self' data: https:; " +
|
||||
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
+22
File diff suppressed because one or more lines are too long
@@ -2,10 +2,8 @@
|
||||
<!-- Device Detection - Detect real mobile devices vs desktop browser -->
|
||||
<script src="/static/js/device-detection.js"></script>
|
||||
|
||||
<!-- HTMX with SRI (Subresource Integrity) -->
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"
|
||||
integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
|
||||
crossorigin="anonymous"></script>
|
||||
<!-- HTMX 2.0.10 (self-hosted) -->
|
||||
<script src="/static/htmx/htmx.min.js"></script>
|
||||
|
||||
<!-- Hyperscript Functions - Must load BEFORE hyperscript library -->
|
||||
<!-- NOTE: cv-functions.js removed - hyperscript def statements are globally available -->
|
||||
@@ -23,12 +21,12 @@
|
||||
<!-- NOTE: footer-buttons-interaction.js removed - moved to hyperscript on footer element -->
|
||||
<!-- NOTE: scroll-at-bottom-handler.js removed - duplicate of handleScroll() in utils._hs -->
|
||||
|
||||
<!-- Hyperscript - Declarative event handling for enhanced interactivity -->
|
||||
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
|
||||
<!-- Hyperscript 0.9.91 (self-hosted) -->
|
||||
<script src="/static/hyperscript/_hyperscript.min.js"></script>
|
||||
|
||||
<!-- Ninja Keys - Lazy loaded on CMD+K (see body-scripts for loader) -->
|
||||
|
||||
<!-- Iconify - Load synchronously for immediate rendering -->
|
||||
<!-- Using unpkg CDN (more reliable than code.iconify.design) -->
|
||||
<!-- Using jsdelivr CDN (more reliable than code.iconify.design) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"></script>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user