- Pin Dockerfile to Go 1.23 to match go.mod - Record README front-door audit findings
49 lines
2.1 KiB
JavaScript
49 lines
2.1 KiB
JavaScript
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
// Copy-to-clipboard for `.js-copy` buttons, loaded by the Domains page only
|
|
// (domains-registry D9).
|
|
//
|
|
// Delegated on document so it survives the claim status view's 5s HTMX
|
|
// self-swap, and CSP-safe: strict CSP drops inline handlers, so every button
|
|
// carries its payload in data-copy and nothing else.
|
|
//
|
|
// An integration's dashboard card that needs the same behavior ships its own
|
|
// copy inside its card script (the member-dashboard contract requires card
|
|
// scripts to come from the integration's own static mount), so this handler
|
|
// may be functionally duplicated by integration bundles. Core's copy and an
|
|
// integration's never load on the same page — this one belongs to core
|
|
// surfaces — so there is no double-fire and neither may be deleted in favor
|
|
// of the other.
|
|
(function () {
|
|
document.addEventListener("click", function (evt) {
|
|
var button = evt.target.closest(".js-copy");
|
|
if (!button || !button.dataset.copy) return;
|
|
// Clipboard API requires a secure context (HTTPS or localhost — both true
|
|
// for every supported deployment).
|
|
if (!navigator.clipboard) return;
|
|
var showFeedback = function (html) {
|
|
if (button.dataset.copyRestore) return; // feedback already showing
|
|
button.dataset.copyRestore = button.innerHTML;
|
|
button.innerHTML = html;
|
|
setTimeout(function () {
|
|
// The 5s poll may have replaced the node; only restore if it's live.
|
|
if (button.isConnected && button.dataset.copyRestore) {
|
|
button.innerHTML = button.dataset.copyRestore;
|
|
delete button.dataset.copyRestore;
|
|
}
|
|
}, 1500);
|
|
};
|
|
navigator.clipboard
|
|
.writeText(button.dataset.copy)
|
|
.then(function () {
|
|
showFeedback('<span class="small text-success">Copied ✓</span>');
|
|
})
|
|
.catch(function () {
|
|
// Permission denied or document unfocused — tell the member instead
|
|
// of failing silently (and swallow the rejection).
|
|
showFeedback('<span class="small text-danger">Copy failed</span>');
|
|
});
|
|
});
|
|
})();
|