From 9de70df74e400ab0122b264d293a9f0d967db931 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 01:49:51 +0000 Subject: [PATCH] fix: reveal mode not reverting when turned OFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reveal mode was turned OFF, text stayed showing real data (e.g. "John Smith") instead of reverting to the AI's actual text ("Ademo Demo"). The unreveal function relied on a WeakMap of original text nodes which lost entries when DOM nodes were replaced during streaming responses. Fixed by replacing WeakMap-based restore with active reverse replacement: unrevealText() replaces real→substitute (the opposite direction of revealText). This is reliable regardless of DOM changes. Removed originalTexts WeakMap entirely. https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- src/content/content.js | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/content/content.js b/src/content/content.js index 81de025..7ea70b1 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -1337,7 +1337,23 @@ return result; } - const originalTexts = new WeakMap(); + /** + * Reverse of revealText: replace real values back to substitutes. + * Used when reveal mode is turned OFF to restore the AI's actual text. + */ + function unrevealText(text) { + const pairs = getRevealPairs(); + let result = text; + // Reverse direction: real (p.to) → substitute (p.from) + // Sort by length descending to avoid partial matches + const reversed = [...pairs].sort((a, b) => b.to.length - a.to.length); + for (const p of reversed) { + const escaped = esc(p.to); + const regex = new RegExp(escaped, p.caseSensitive ? 'g' : 'gi'); + result = result.replace(regex, p.from); + } + return result; + } function revealInElement(el) { if (SKIP_REVEAL_TAGS.has(el.tagName)) return; @@ -1350,7 +1366,6 @@ const parent = node.parentElement; if (parent && SKIP_REVEAL_TAGS.has(parent.tagName)) return NodeFilter.FILTER_REJECT; if (parent?.closest?.('.ss-autodetect-warning, .ss-presend-warning, .ss-reveal-badge')) return NodeFilter.FILTER_REJECT; - // Skip contenteditable areas (chat input) if (parent?.closest?.('[contenteditable="true"]')) return NodeFilter.FILTER_REJECT; return NodeFilter.FILTER_ACCEPT; } @@ -1361,10 +1376,6 @@ const text = textNode.textContent; if (!text || text.length < MIN_STRING_LENGTH) continue; - if (!originalTexts.has(textNode)) { - originalTexts.set(textNode, text); - } - const revealed = revealText(text); if (revealed !== text) { textNode.textContent = revealed; @@ -1385,9 +1396,13 @@ }); let textNode; while ((textNode = walker.nextNode())) { - const original = originalTexts.get(textNode); - if (original && textNode.textContent !== original) { - textNode.textContent = original; + const text = textNode.textContent; + if (!text || text.length < MIN_STRING_LENGTH) continue; + + // Actively replace real→substitute (reverse of reveal) + const unrevealed = unrevealText(text); + if (unrevealed !== text) { + textNode.textContent = unrevealed; } } } @@ -1502,9 +1517,6 @@ if (parent?.closest?.('[contenteditable="true"]')) continue; const text = node.textContent; if (text && text.length >= MIN_STRING_LENGTH) { - if (!originalTexts.has(node)) { - originalTexts.set(node, text); - } const revealed = revealText(text); if (revealed !== text) { node.textContent = revealed; @@ -1524,9 +1536,6 @@ // Skip contenteditable (chat input) if (parent?.closest?.('[contenteditable="true"]')) continue; if (parent && !SKIP_REVEAL_TAGS.has(parent.tagName)) { - if (!originalTexts.has(mutation.target)) { - originalTexts.set(mutation.target, text); - } const revealed = revealText(text); if (revealed !== text) { mutation.target.textContent = revealed;