fix: reveal mode not reverting when turned OFF

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
This commit is contained in:
Claude
2026-03-27 01:49:51 +00:00
parent 75845d7ec7
commit 9de70df74e
+24 -15
View File
@@ -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;