From ed355ff2efe69e66d16e27566c2f45b6ee9c9f3b Mon Sep 17 00:00:00 2001 From: Greg Hogue Date: Thu, 18 Sep 2025 12:08:30 -0400 Subject: [PATCH 1/2] fix dark/light mode disclaimer footer bug --- public/custom.js | 76 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/public/custom.js b/public/custom.js index 67abcde..6fbec78 100644 --- a/public/custom.js +++ b/public/custom.js @@ -17,45 +17,73 @@ `.trim(); const WATERMARK_SELECTOR = 'a.watermark'; - const APPLIED_ATTR = 'data-custom-watermark'; + const STYLE_ID = 'custom-watermark-style'; + const SIBLING_ATTR = 'data-custom-watermark-sibling'; - function replaceFooterContents(root = document) { + function injectStyles() { + if (document.getElementById(STYLE_ID)) return; + + const style = document.createElement('style'); + style.id = STYLE_ID; + style.textContent = ` + /* Remove the watermark element from layout completely. */ + a.watermark { + display: none !important; + } + `; + document.head.appendChild(style); + } + + function ensureSiblingAfterWatermark(el) { + if (!(el instanceof HTMLElement)) return; + + // If the immediate next sibling is our disclaimer, update it; otherwise, insert one. + const nextEl = el.nextElementSibling; + if (nextEl && nextEl.getAttribute(SIBLING_ATTR) === '1') { + if (nextEl.innerHTML.trim() !== CUSTOM_FOOTER_HTML) { + nextEl.innerHTML = CUSTOM_FOOTER_HTML; + } + return; + } + + const container = document.createElement('div'); + container.setAttribute(SIBLING_ATTR, '1'); + container.style.margin = '0'; // no extra spacing; let parent gap handle layout + container.style.pointerEvents = 'auto'; + container.setAttribute('aria-live', 'polite'); + container.innerHTML = CUSTOM_FOOTER_HTML; + + // Insert directly after the watermark anchor + el.insertAdjacentElement('afterend', container); + } + + function applyAll(root = document) { const nodes = root instanceof Element ? root.querySelectorAll(WATERMARK_SELECTOR) : document.querySelectorAll(WATERMARK_SELECTOR); - nodes.forEach((el) => { - if (!(el instanceof HTMLElement)) return; - if (el.getAttribute(APPLIED_ATTR) === '1') return; - - el.innerHTML = CUSTOM_FOOTER_HTML; - - // disable the link behaviour - el.removeAttribute('href'); - el.removeAttribute('target'); - el.style.pointerEvents = 'none'; + nodes.forEach((el) => ensureSiblingAfterWatermark(el)); + } - el.setAttribute(APPLIED_ATTR, '1'); - }); + function init() { + injectStyles(); + applyAll(document); } - // Initial run (in case the element is already present). if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', () => replaceFooterContents(document)); + document.addEventListener('DOMContentLoaded', init); } else { - replaceFooterContents(document); + init(); } // Re-apply on future UI updates (SPA re-renders). const mo = new MutationObserver((mutations) => { for (const m of mutations) { - for (const node of m.addedNodes) { - if (node instanceof Element) { - // If the watermark itself is added or its parent subtree changes, update. - if (node.matches?.(WATERMARK_SELECTOR) || node.querySelector?.(WATERMARK_SELECTOR)) { - replaceFooterContents(node); - } - } + if (m.type === 'childList') { + // Re-ensure CSS and siblings if the UI changes. + if (!document.getElementById(STYLE_ID)) injectStyles(); + applyAll(document); + break; } } }); From 560c6e7a35e966e07a3ac21e55fa637250eabd60 Mon Sep 17 00:00:00 2001 From: Greg Hogue Date: Thu, 18 Sep 2025 16:32:00 -0400 Subject: [PATCH 2/2] remove extraneous GPT comments --- public/custom.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/public/custom.js b/public/custom.js index 6fbec78..df2a934 100644 --- a/public/custom.js +++ b/public/custom.js @@ -26,7 +26,6 @@ const style = document.createElement('style'); style.id = STYLE_ID; style.textContent = ` - /* Remove the watermark element from layout completely. */ a.watermark { display: none !important; } @@ -48,7 +47,7 @@ const container = document.createElement('div'); container.setAttribute(SIBLING_ATTR, '1'); - container.style.margin = '0'; // no extra spacing; let parent gap handle layout + container.style.margin = '0'; container.style.pointerEvents = 'auto'; container.setAttribute('aria-live', 'polite'); container.innerHTML = CUSTOM_FOOTER_HTML; @@ -76,7 +75,7 @@ init(); } - // Re-apply on future UI updates (SPA re-renders). + // Re-apply on future UI updates const mo = new MutationObserver((mutations) => { for (const m of mutations) { if (m.type === 'childList') {