Changeset f7d142f in Klonkt for src/views/shell.ejs


Ignore:
Timestamp:
06/28/2026 03:36:22 PM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
81bb9c5
Parents:
127f87e
Message:

chore(csp): drop the last script unsafe-inline + add Permissions-Policy

Move every inline on* handler to a shared delegated data-* handler, so script-src-attr
can be 'none' instead of 'unsafe-inline'. Add a Permissions-Policy header disabling
camera/microphone/geolocation/Topics (embed features left at default).

  • views/shell.ejs — shared delegated submit/change/click/error handler (data-confirm, data-autosubmit, data-lang-switch, data-selectall, data-back, data-fallback)
  • views/{pages,partials}/*.ejs — 18 inline on* handlers -> data-* attributes (14 files)
  • server.js — scriptSrcAttr 'unsafe-inline' -> 'none'; Permissions-Policy header
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/shell.ejs

    r127f87e rf7d142f  
    747747</script>
    748748
     749<script>
     750// Delegated replacements for inline on* handlers, so the CSP needs no
     751// script-src-attr 'unsafe-inline'. Document-level → also covers htmx-swapped content.
     752(function () {
     753  if (window.__pcmsHandlersWired) return; window.__pcmsHandlersWired = true;
     754  // Confirm before submitting a form that carries data-confirm.
     755  document.addEventListener('submit', function (e) {
     756    var f = e.target;
     757    if (f && f.dataset && f.dataset.confirm && !window.confirm(f.dataset.confirm)) e.preventDefault();
     758  });
     759  // Auto-submit a form / switch language when a <select> changes.
     760  document.addEventListener('change', function (e) {
     761    var el = e.target;
     762    if (!el || !el.dataset) return;
     763    if (el.dataset.autosubmit !== undefined && el.form) el.form.submit();
     764    else if (el.dataset.langSwitch !== undefined) {
     765      location.href = '/lang/' + encodeURIComponent(el.value) + '?r=' + encodeURIComponent(location.pathname + location.search);
     766    }
     767  });
     768  // Misc click helpers (select-all in a field, history-back button).
     769  document.addEventListener('click', function (e) {
     770    var el = e.target.closest && e.target.closest('[data-selectall],[data-back]');
     771    if (!el) return;
     772    if (el.dataset.selectall !== undefined && el.select) el.select();
     773    if (el.dataset.back !== undefined) { e.preventDefault(); history.back(); }
     774  });
     775  // Image fallback (the error event doesn't bubble → capture phase).
     776  document.addEventListener('error', function (e) {
     777    var el = e.target;
     778    if (el && el.tagName === 'IMG' && el.dataset && el.dataset.fallback !== undefined && el.parentElement) {
     779      el.parentElement.innerHTML = '<span class="pl-cover-empty">⚠️</span>';
     780    }
     781  }, true);
     782})();
     783</script>
     784
    749785<!-- Per-site custom footer HTML -->
    750786<% if (safeSite.custom_foot_html) { %>
Note: See TracChangeset for help on using the changeset viewer.