Skip to content
This repository was archived by the owner on Aug 8, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions handlers/csp.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ func enforceContentSecurityPolicy(next http.Handler) http.Handler {
values: []string{
"'self'",
"'nonce-" + nonce + "'",
// for htmx 2.0.4 inline style
"'sha256-bsV5JivYxvGywDAZ22EZJKBFip65Ng9xoJVLbBg7bdo='",
},
},
{
Expand Down
50 changes: 33 additions & 17 deletions handlers/static/js/htmx-settings.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
/* global htmx */

// Tighten security.
// Keep htmx requests limited to this origin so hx-* attributes can't be used to
// send data to another site.
htmx.config.selfRequestsOnly = true;

// Server-rendered htmx responses don't need response-provided script execution.
htmx.config.allowScriptTags = false;

// Keep htmx from evaluating dynamic JavaScript strings.
htmx.config.allowEval = false;

// Disable htmx's history cache to avoid stale pages and storing page contents in
// long-lived browser storage.
htmx.config.historyCacheSize = 0;

// History restores should fetch full pages, not HX-Request partial responses.
htmx.config.historyRestoreAsHxRequest = false;

// Indicator CSS lives in screenjournal.css, so htmx shouldn't inject its own
// inline style tag.
htmx.config.includeIndicatorStyles = false;

// Fail stalled requests instead of leaving controls disabled indefinitely.
htmx.config.timeout = 5000;

// Don't let response-targets override isError.
htmx.config.responseTargetUnsetsError = false;

document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener("htmx:beforeSwap", function (evt) {
if (evt.detail.xhr.status === 204) {
evt.detail.shouldSwap = true;
}
if (evt.detail.xhr.status === 422) {
// allow 422 responses to swap as we are using this as a signal that
// a form was submitted with bad data and want to rerender with the
// errors
//
// set isError to false to avoid error logging in console
evt.detail.shouldSwap = true;
evt.detail.isError = false;
}
});
});
htmx.config.responseHandling = [
// Empty 204 responses from delete endpoints should clear their target.
{ code: "204", swap: true },

// Validation errors should swap normally without console error noise.
{ code: "422", swap: true, error: false },

// Successful non-empty responses should swap normally.
{ code: "[23]..", swap: true },

// Let response-targets route error responses to hx-target-error elements.
{ code: "[45]..", swap: false, error: true },
];
Loading