Skip to content

Commit ed355ff

Browse files
committed
fix dark/light mode disclaimer footer bug
1 parent 5615ca8 commit ed355ff

1 file changed

Lines changed: 52 additions & 24 deletions

File tree

public/custom.js

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,73 @@
1717
`.trim();
1818

1919
const WATERMARK_SELECTOR = 'a.watermark';
20-
const APPLIED_ATTR = 'data-custom-watermark';
20+
const STYLE_ID = 'custom-watermark-style';
21+
const SIBLING_ATTR = 'data-custom-watermark-sibling';
2122

22-
function replaceFooterContents(root = document) {
23+
function injectStyles() {
24+
if (document.getElementById(STYLE_ID)) return;
25+
26+
const style = document.createElement('style');
27+
style.id = STYLE_ID;
28+
style.textContent = `
29+
/* Remove the watermark element from layout completely. */
30+
a.watermark {
31+
display: none !important;
32+
}
33+
`;
34+
document.head.appendChild(style);
35+
}
36+
37+
function ensureSiblingAfterWatermark(el) {
38+
if (!(el instanceof HTMLElement)) return;
39+
40+
// If the immediate next sibling is our disclaimer, update it; otherwise, insert one.
41+
const nextEl = el.nextElementSibling;
42+
if (nextEl && nextEl.getAttribute(SIBLING_ATTR) === '1') {
43+
if (nextEl.innerHTML.trim() !== CUSTOM_FOOTER_HTML) {
44+
nextEl.innerHTML = CUSTOM_FOOTER_HTML;
45+
}
46+
return;
47+
}
48+
49+
const container = document.createElement('div');
50+
container.setAttribute(SIBLING_ATTR, '1');
51+
container.style.margin = '0'; // no extra spacing; let parent gap handle layout
52+
container.style.pointerEvents = 'auto';
53+
container.setAttribute('aria-live', 'polite');
54+
container.innerHTML = CUSTOM_FOOTER_HTML;
55+
56+
// Insert directly after the watermark anchor
57+
el.insertAdjacentElement('afterend', container);
58+
}
59+
60+
function applyAll(root = document) {
2361
const nodes = root instanceof Element
2462
? root.querySelectorAll(WATERMARK_SELECTOR)
2563
: document.querySelectorAll(WATERMARK_SELECTOR);
2664

27-
nodes.forEach((el) => {
28-
if (!(el instanceof HTMLElement)) return;
29-
if (el.getAttribute(APPLIED_ATTR) === '1') return;
30-
31-
el.innerHTML = CUSTOM_FOOTER_HTML;
32-
33-
// disable the link behaviour
34-
el.removeAttribute('href');
35-
el.removeAttribute('target');
36-
el.style.pointerEvents = 'none';
65+
nodes.forEach((el) => ensureSiblingAfterWatermark(el));
66+
}
3767

38-
el.setAttribute(APPLIED_ATTR, '1');
39-
});
68+
function init() {
69+
injectStyles();
70+
applyAll(document);
4071
}
4172

42-
// Initial run (in case the element is already present).
4373
if (document.readyState === 'loading') {
44-
document.addEventListener('DOMContentLoaded', () => replaceFooterContents(document));
74+
document.addEventListener('DOMContentLoaded', init);
4575
} else {
46-
replaceFooterContents(document);
76+
init();
4777
}
4878

4979
// Re-apply on future UI updates (SPA re-renders).
5080
const mo = new MutationObserver((mutations) => {
5181
for (const m of mutations) {
52-
for (const node of m.addedNodes) {
53-
if (node instanceof Element) {
54-
// If the watermark itself is added or its parent subtree changes, update.
55-
if (node.matches?.(WATERMARK_SELECTOR) || node.querySelector?.(WATERMARK_SELECTOR)) {
56-
replaceFooterContents(node);
57-
}
58-
}
82+
if (m.type === 'childList') {
83+
// Re-ensure CSS and siblings if the UI changes.
84+
if (!document.getElementById(STYLE_ID)) injectStyles();
85+
applyAll(document);
86+
break;
5987
}
6088
}
6189
});

0 commit comments

Comments
 (0)