[object Object]

← back to Rentv

pr/adapters: Cody gate — decode & LAST in stripTags (after the numeric passes). Decoding it first turned a double-encoded '&' (literal '&') into '&' then the numeric pass collapsed it to '&' — corrupting the intended literal. Moved to last so double-encoded refs survive; single-encoded &/& still decode. Verified

e246fdef43a0e380e50ef7f36e5cf7482b9b060d · 2026-08-06 01:29:48 -0700 · Steve

Files touched

Diff

commit e246fdef43a0e380e50ef7f36e5cf7482b9b060d
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 01:29:48 2026 -0700

    pr/adapters: Cody gate — decode &amp; LAST in stripTags (after the numeric passes). Decoding it first turned a double-encoded '&amp;#38;' (literal '&#38;') into '&#38;' then the numeric pass collapsed it to '&' — corrupting the intended literal. Moved to last so double-encoded refs survive; single-encoded &#38;/&amp; still decode. Verified
---
 src/pr/adapters/index.js | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/pr/adapters/index.js b/src/pr/adapters/index.js
index fe4ba47b..e524d715 100644
--- a/src/pr/adapters/index.js
+++ b/src/pr/adapters/index.js
@@ -87,13 +87,16 @@ function stripTags(html) {
   const num = (n) => { try { return (n >= 32 && n !== 127) ? String.fromCodePoint(n) : ' '; } catch { return ' '; } };
   return String(html || '')
     .replace(/<script[\s\S]*?<\/script>/gi, ' ').replace(/<style[\s\S]*?<\/style>/gi, ' ')
-    .replace(/<[^>]+>/g, ' ').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&')
+    .replace(/<[^>]+>/g, ' ').replace(/&nbsp;/g, ' ')
     .replace(/&#0?39;|&rsquo;|&lsquo;|&#8217;/g, "'").replace(/&quot;|&ldquo;|&rdquo;/g, '"')
     .replace(/&ndash;|&#8211;/g, '\u2013').replace(/&mdash;|&#8212;/g, '\u2014')
     .replace(/&hellip;/g, '\u2026').replace(/&reg;/g, '\u00ae').replace(/&copy;/g, '\u00a9').replace(/&trade;/g, '\u2122')
     // numeric character references (decimal + hex) \u2014 covers &#38; &#233; &#8230; &#x26; that named-only decoding misses
     .replace(/&#(\d{1,7});/g, (_, n) => num(+n))
     .replace(/&#x([0-9a-f]{1,6});/gi, (_, h) => num(parseInt(h, 16)))
+    // &amp; decoded LAST (after the numeric passes) so a double-encoded '&amp;#38;' stays the literal
+    // text '&#38;' instead of collapsing to '&' \u2014 the numeric pass can't match while the & is still &amp;
+    .replace(/&amp;/g, '&')
     .replace(/\s+/g, ' ').trim();
 }
 

← 8d77a6f0 pr/adapters: stripTags now decodes numeric character referen  ·  back to Rentv  ·  auto-save: 2026-08-06T01:47:30 (7 files) — data/deals-regist 9bdae722 →