← back to Designerwallcoverings
TK-11307: tag-driven Boost card hider (Steve's ruling: keep MDC findable in search)
5b789a209dfc638f83a2c72c6d9e70b46fba6517 · 2026-09-10 17:52:26 -0700 · Steve Abrams
The approved plan could not work. Every browse/search grid is rendered by Boost
SD, not Liquid -- /collections/all serves 0 `class="product-list-item"` against
273 boost-sd__product-item -- so the render-time skip never executes there, and
the JS backstop hooked [data-tags], which no card emits (0 across 59 cards on 4
surfaces). Steve chose to keep MDC findable in on-site search, ruling out a
Boost index exclusion.
So this generalizes the one mechanism proven to hide a Boost card on this store,
assets/dw-pj-hide.js:
- build-showroom-hide-asset.mjs queries live Shopify for the EXACT 'ShowroomOnly'
tag and generates dw-showroom-hide.js. A rendered Boost card exposes only
data-product-id (no tags), so the tag is resolved at BUILD time and the runtime
test is an O(1) id-set lookup. 4,728 ids, sorted-delta base36: 22.1KB packed vs
64.6KB raw.
- The asset returns immediately on /search or ?q=, so search stays findable --
"addressable but not discoverable".
- test-showroom-hide-asset.mjs proves it in real headless Chrome: all MDC cards
hidden, ZERO of 6 live 'Showroom Line' controls hidden (two of which share the
'Phillipe Romano' vendor), nothing hidden on search, and an injected over-broad
hider trips the control assertion. A render that produces no result is a
failure, never a pass.
- hide-browse-hidden.liquid: removed the dead data-tags hook (dead code that
invited someone to arm the 'Showroom Line' landmine by emitting data-tags) and
added the asset include.
- product-list-item.liquid REMOVED from the push set: it cannot help, and the
local copy predates the live Newmor feature so pushing it would revert it.
Nothing pushed. Dry-run resolves the published theme and shows the 2-file diff.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FAPArHdMKRiNHqJiorUFm
Files touched
A scripts/tk11186-showroom-hide/theme-deploy/dw-showroom-hide.jsM scripts/tk11186-showroom-hide/theme-deploy/hide-browse-hidden.liquidM scripts/tk11186-showroom-hide/theme-deploy/push-theme-assets.mjsA scripts/tk11307-showroom-tag/build-showroom-hide-asset.mjsA scripts/tk11307-showroom-tag/data/hide-asset-fixtures.jsonA scripts/tk11307-showroom-tag/test-showroom-hide-asset.mjs
Diff
commit 5b789a209dfc638f83a2c72c6d9e70b46fba6517
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 10 17:52:26 2026 -0700
TK-11307: tag-driven Boost card hider (Steve's ruling: keep MDC findable in search)
The approved plan could not work. Every browse/search grid is rendered by Boost
SD, not Liquid -- /collections/all serves 0 `class="product-list-item"` against
273 boost-sd__product-item -- so the render-time skip never executes there, and
the JS backstop hooked [data-tags], which no card emits (0 across 59 cards on 4
surfaces). Steve chose to keep MDC findable in on-site search, ruling out a
Boost index exclusion.
So this generalizes the one mechanism proven to hide a Boost card on this store,
assets/dw-pj-hide.js:
- build-showroom-hide-asset.mjs queries live Shopify for the EXACT 'ShowroomOnly'
tag and generates dw-showroom-hide.js. A rendered Boost card exposes only
data-product-id (no tags), so the tag is resolved at BUILD time and the runtime
test is an O(1) id-set lookup. 4,728 ids, sorted-delta base36: 22.1KB packed vs
64.6KB raw.
- The asset returns immediately on /search or ?q=, so search stays findable --
"addressable but not discoverable".
- test-showroom-hide-asset.mjs proves it in real headless Chrome: all MDC cards
hidden, ZERO of 6 live 'Showroom Line' controls hidden (two of which share the
'Phillipe Romano' vendor), nothing hidden on search, and an injected over-broad
hider trips the control assertion. A render that produces no result is a
failure, never a pass.
- hide-browse-hidden.liquid: removed the dead data-tags hook (dead code that
invited someone to arm the 'Showroom Line' landmine by emitting data-tags) and
added the asset include.
- product-list-item.liquid REMOVED from the push set: it cannot help, and the
local copy predates the live Newmor feature so pushing it would revert it.
Nothing pushed. Dry-run resolves the published theme and shows the 2-file diff.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FAPArHdMKRiNHqJiorUFm
---
.../theme-deploy/dw-showroom-hide.js | 18 ++++
.../theme-deploy/hide-browse-hidden.liquid | 35 +++++---
.../theme-deploy/push-theme-assets.mjs | 33 +++++++-
.../build-showroom-hide-asset.mjs | 88 +++++++++++++++++++
.../data/hide-asset-fixtures.json | 49 +++++++++++
.../test-showroom-hide-asset.mjs | 99 ++++++++++++++++++++++
6 files changed, 304 insertions(+), 18 deletions(-)
diff --git a/scripts/tk11186-showroom-hide/theme-deploy/dw-showroom-hide.js b/scripts/tk11186-showroom-hide/theme-deploy/dw-showroom-hide.js
new file mode 100644
index 0000000..93d4388
--- /dev/null
+++ b/scripts/tk11186-showroom-hide/theme-deploy/dw-showroom-hide.js
@@ -0,0 +1,18 @@
+/* TK-11307 showroom-only Boost card hider — GENERATED by build-showroom-hide-asset.mjs.
+ Hides products tagged 'ShowroomOnly' from Boost-rendered browse grids while leaving on-site
+ search and direct /products/ URLs untouched ("addressable but not discoverable").
+ 4728 product ids, sorted delta base36. Do not hand-edit — regenerate. */
+(function(){
+ if(/\/search/i.test(location.pathname)||/[?&]q=/i.test(location.search))return; /* keep search findable */
+ var P="2ssn8ye5v,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,eqyo,pa8,7q4g,5m9s,4wzk,5m9s,pa8,pa8,1ekg,pa8,pa8,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,23uo,pa8,7q4g,1ekg,47pc,47pc,3if4,47pc,3if4,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,1ekg,pa8,1ekg,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,bxts,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,23uo,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,23uo,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,4wzk,2t4w,4wzk,47pc,2t4w,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,47pc,47pc,3if4,5m9s,3if4,4wzk,47pc,3if4,5m9s,4wzk,7q4g,47pc,4wzk,1ekg,pa8,47pc,4wzk,47pc,4wzk,4wzk,4wzk,6bk0,4wzk,4wzk,47pc,6bk0,4wzk,4wzk,5m9s,pa8,23uo,4wzk,4wzk,4wzk,3if4,3if4,2t4w,3if4,2t4w,3if4,2t4w,4wzk,47pc,47pc,47pc,4wzk,47pc,pa8,2t4w,47pc,47pc,4wzk,47pc,3if4,4wzk,4wzk,47pc,4wzk,47pc,4wzk,4wzk,3if4,pa8,47pc,4wzk,2t4w,5m9s,47pc,47pc,47pc,5m9s,5m9s,3if4,4wzk,4wzk,47pc,4wzk,4wzk,2t4w,pa8,4wzk,6bk0,47pc,6bk0,5m9s,4wzk,4wzk,6bk0,47pc,70u8,5m9s,47pc,3if4,pa8,3if4,3if4,47pc,4wzk,4wzk,4wzk,6bk0,3if4,47pc,4wzk,5m9s,47pc,47pc,pa8,pa8,47pc,4wzk,5m9s,47pc,4wzk,4wzk,5m9s,5m9s,2t4w,4wzk,47pc,6bk0,5m9s,47pc,47pc,pa8,47pc,4wzk,47pc,4wzk,47pc,5m9s,47pc,6bk0,47pc,47pc,5m9s,4wzk,47pc,47pc,47pc,1ekg,47pc,eqyo,fg8w,8feo,5m9s,47pc,4wzk,3if4,4wzk,4wzk,3if4,47pc,47pc,2t4w,pa8,7q4g,5m9s,5m9s,2t4w,pa8,1ekg,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,23uo,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,23uo,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,1ekg,pa8,1ekg,1ekg,pa8,1ekg,pa8,23uo,pa8,1ekg,pa8,1ekg,1ekg,1ekg,1ekg,pa8,23uo,pa8,1ekg,23uo,1ekg,pa8,2t4w,pa8,pa8,23uo,pa8,pa8,pa8,23uo,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,1ekg,pa8,pa8,1ekg,pa8,1ekg,pa8,pa8,23uo,1ekg,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,1ekg,pa8,pa8,23uo,3if4,4wzk,47pc,3if4,2t4w,pa8,pa8,23uo,pa8,pa8,pa8,2t4w,pa8,pa8,23uo,pa8,pa8,1ekg,pa8,23uo,23uo,pa8,pa8,1ekg,pa8,pa8,1ekg,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,23uo,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,1ekg,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,3if4,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,pa8,pa8,pa8,1ekg,1ekg,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,3if4,3if4,47pc,3if4,2t4w,23uo,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,pa8,1ekg,pa8,7q4g,aj9c,aj9c,23uo,1ekg,pa8,pa8,pa8,pa8,pa8,1ekg,1ekg,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,4wzk,23uo,23uo,2t4w,3if4,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,23uo,2t4w,3if4,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,3if4,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,23uo,23uo,23uo,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,1ekg,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,23uo,3if4,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,pa8,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,4wzk,3if4,3if4,47pc,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,2t4w,47pc,2t4w,3if4,3if4,3if4,23uo,2t4w,3if4,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,3if4,3if4,2t4w,3if4,2t4w,3if4,3if4,2t4w,3if4,2t4w,23uo,47pc,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,23uo,3if4,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,23uo,2t4w,2t4w,3if4,23uo,23uo,2t4w,2t4w,2t4w,23uo,3if4,3if4,23uo,3if4,23uo,23uo,23uo,23uo,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,2t4w,47pc,2t4w,23uo,3if4,2t4w,23uo,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,23uo,3if4,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,23uo,3if4,2t4w,2t4w,2t4w,23uo,2t4w,3if4,2t4w,23uo,23uo,3if4,4wzk,3if4,2t4w,3if4,3if4,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,3if4,3if4,2t4w,2t4w,1ekg,23uo,2t4w,23uo,2t4w,23uo,2t4w,23uo,3if4,23uo,1ekg,23uo,1ekg,2t4w,23uo,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,2t4w,2t4w,23uo,23uo,2t4w,2t4w,2t4w,2t4w,3if4,47pc,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,4wzk,5m9s,6bk0,5m9s,6bk0,4wzk,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,23uo,2t4w,2t4w,23uo,4wzk,2t4w,4wzk,pa8,23uo,3if4,2t4w,2t4w,2t4w,2t4w,3if4,23uo,23uo,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,23uo,23uo,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,47pc,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,23uo,23uo,2t4w,2t4w,2t4w,2t4w,23uo,1ekg,23uo,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,23uo,3if4,23uo,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,3if4,2t4w,4wzk,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,1ekg,3if4,2t4w,2t4w,2t4w,3if4,23uo,pa8,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,3if4,23uo,23uo,2t4w,2t4w,2t4w,3if4,23uo,23uo,1ekg,3if4,2t4w,2t4w,3if4,2t4w,2t4w,3if4,3if4,2t4w,47pc,2t4w,3if4,23uo,2t4w,3if4,2t4w,2t4w,47pc,2t4w,3if4,3if4,3if4,2t4w,2t4w,3if4,2t4w,2t4w,47pc,23uo,23uo,1ekg,3if4,23uo,3if4,3if4,23uo,4wzk,47pc,47pc,3if4,47pc,3if4,2t4w,3if4,47pc,47pc,2t4w,3if4,2t4w,2t4w,2t4w,23uo,2t4w,3if4,2t4w,3if4,23uo,47pc,23uo,3if4,2t4w,3if4,3if4,23uo,3if4,3if4,3if4,2t4w,3if4,3if4,3if4,47pc,3if4,2t4w,2t4w,3if4,3if4,2t4w,47pc,2t4w,47pc,3if4,23uo,3if4,2t4w,3if4,47pc,47pc,47pc,2t4w,2t4w,4wzk,23uo,2t4w,23uo,2t4w,3if4,23uo,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,23uo,23uo,2t4w,2t4w,3if4,2t4w,47pc,23uo,2t4w,2t4w,2t4w,lrsw,7q4g,b8jk,47pc,5m9s,23uo,4wzk,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,23uo,47pc,3if4,gutc,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,47pc,23uo,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,1ekg,3if4,2t4w,2t4w,4wzk,5m9s,5m9s,5m9s,5m9s,5m9s,47pc,2t4w,47pc,2t4w,2t4w,47pc,2t4w,2t4w,23uo,3if4,2t4w,3if4,47pc,2t4w,2t4w,47pc,2t4w,3if4,3if4,3if4,2t4w,3if4,3if4,2t4w,4wzk,2t4w,2t4w,3if4,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,2t4w,47pc,47pc,2t4w,3if4,3if4,47pc,3if4,2t4w,3if4,47pc,3if4,5m9s,3if4,3if4,47pc,2t4w,47pc,3if4,2t4w,47pc,47pc,47pc,47pc,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,3if4,2t4w,2t4w,2t4w,2t4w,23uo,3if4,3if4,23uo,47pc,2t4w,23uo,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,3if4,23uo,2t4w,2t4w,2t4w,4wzk,23uo,2t4w,3if4,23uo,2t4w,2t4w,23uo,23uo,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,23uo,3if4,2t4w,23uo,23uo,1ekg,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,2t4w,3if4,1ekg,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,23uo,pa8,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,47pc,23uo,3if4,2t4w,2t4w,2t4w,3if4,3if4,2t4w,23uo,3if4,2t4w,3if4,47pc,2t4w,2t4w,3if4,2t4w,3if4,2t4w,4wzk,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,3if4,23uo,1ekg,23uo,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,3if4,3if4,3if4,3if4,2t4w,3if4,2t4w,5m9s,47pc,3if4,3if4,3if4,2t4w,3if4,3if4,3if4,47pc,1ekg,2t4w,3if4,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,23uo,23uo,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,23uo,23uo,1ekg,2t4w,3if4,23uo,4wzk,23uo,3if4,3if4,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,23uo,3if4,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,23uo,2t4w,3if4,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,3if4,3if4,2t4w,23uo,2t4w,3if4,2t4w,3if4,2t4w,3if4,23uo,2t4w,3if4,3if4,1ekg,pa8,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,3if4,3if4,3if4,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,5m9s,2t4w,47pc,3if4,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,6bk0,5m9s,5m9s,5m9s,5m9s,2t4w,2t4w,23uo,2t4w,3if4,3if4,2t4w,2t4w,6bk0,eqyo,eqyo,4wzk,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,3if4,2t4w,2t4w,3if4,3if4,3if4,2t4w,4wzk,2t4w,3if4,2t4w,3if4,23uo,3if4,2t4w,3if4,3if4,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,23uo,2t4w,3if4,3if4,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,23uo,2t4w,3if4,23uo,47pc,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,1ekg,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,6bk0,7q4g,6bk0,70u8,5m9s,5m9s,47pc,47pc,47pc,5m9s,47pc,47pc,4wzk,47pc,3if4,4wzk,3if4,3if4,3if4,3if4,2t4w,23uo,3if4,3if4,47pc,47pc,47pc,47pc,3if4,2t4w,3if4,2t4w,3if4,47pc,3if4,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,47pc,5m9s,3if4,3if4,3if4,23uo,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,3if4,47pc,3if4,2t4w,47pc,2t4w,3if4,2t4w,2t4w,47pc,2t4w,47pc,2t4w,23uo,2t4w,47pc,2t4w,23uo,2t4w,47pc,2t4w,2t4w,2t4w,23uo,2t4w,3if4,1ekg,3if4,2t4w,2t4w,2t4w,3if4,3if4,47pc,70u8,70u8,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,47pc,2t4w,2t4w,23uo,1ekg,23uo,23uo,2t4w,23uo,23uo,2t4w,23uo,2t4w,23uo,23uo,2t4w,23uo,23uo,23uo,2t4w,23uo,23uo,23uo,2t4w,3if4,23uo,23uo,2t4w,23uo,23uo,2t4w,23uo,3if4,23uo,2t4w,1ekg,2t4w,3if4,23uo,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,1ekg,2t4w,5m9s,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,2t4w,23uo,23uo,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,2t4w,pa8,pa8,23uo,2t4w,23uo,2t4w,23uo,23uo,2t4w,23uo,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,23uo,3if4,2t4w,23uo,3if4,2t4w,23uo,2t4w,47pc,6bk0,2t4w,2t4w,2t4w,23uo,23uo,2t4w,2t4w,4wzk,23uo,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,1ekg,2t4w,2t4w,2t4w,23uo,3if4,3if4,2t4w,2t4w,23uo,3if4,23uo,2t4w,2t4w,2t4w,23uo,47pc,5m9s,5m9s,4wzk,3if4,4wzk,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,47pc,23uo,2t4w,1ekg,23uo,2t4w,23uo,aj9c,6bk0,2t4w,2t4w,23uo,2t4w,23uo,23uo,23uo,2t4w,2t4w,23uo,2t4w,3if4,23uo,23uo,3if4,2t4w,23uo,2t4w,23uo,2t4w,23uo,23uo,2t4w,23uo,23uo,23uo,2t4w,2t4w,2t4w,2t4w,1ekg,pa8,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,47pc,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,23uo,23uo,23uo,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,23uo,2t4w,2t4w,23uo,2t4w,23uo,23uo,23uo,2t4w,23uo,23uo,3if4,23uo,3if4,2t4w,2t4w,23uo,23uo,23uo,23uo,23uo,3if4,2t4w,23uo,23uo,2t4w,23uo,23uo,2t4w,23uo,23uo,23uo,23uo,23uo,2t4w,2t4w,23uo,23uo,2t4w,3if4,23uo,2t4w,2t4w,23uo,3if4,2t4w,23uo,2t4w,23uo,2t4w,2t4w,23uo,3if4,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,5m9s,70u8,6bk0,94ow,5m9s,70u8,70u8,70u8,70u8,5m9s,23uo,9tz4,6bk0,b8jk,7q4g,8feo,9tz4,7q4g,b8jk,6bk0,6bk0,6bk0,7q4g,6bk0,2t4w,6bk0,70u8,6bk0,6bk0,5m9s,70u8,70u8,70u8,3if4,3if4,23uo,2t4w,23uo,3if4,2t4w,2t4w,3if4,47pc,3if4,2t4w,47pc,2t4w,1ekg,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,47pc,3if4,23uo,2t4w,2t4w,3if4,1ekg,3if4,2t4w,2t4w,3if4,3if4,3if4,2t4w,pa8,2t4w,2t4w,3if4,3if4,2t4w,47pc,2t4w,47pc,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,47pc,2t4w,3if4,2t4w,1ekg,23uo,23uo,23uo,23uo,2t4w,2t4w,3if4,2t4w,23uo,23uo,2t4w,3if4,23uo,3if4,2t4w,3if4,2t4w,3if4,23uo,23uo,23uo,47pc,23uo,2t4w,23uo,2t4w,2t4w,2t4w,23uo,1ekg,3if4,47pc,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,3if4,3if4,2t4w,2t4w,5m9s,4wzk,2t4w,3if4,2t4w,3if4,3if4,2t4w,3if4,2t4w,47pc,2t4w,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,1ekg,23uo,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,47pc,2t4w,3if4,2t4w,47pc,2t4w,3if4,2t4w,2t4w,2t4w,23uo,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,3if4,47pc,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,70u8,5m9s,6bk0,6bk0,4wzk,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,1ekg,1ekg,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,2t4w,3if4,3if4,2t4w,2t4w,47pc,2t4w,3if4,47pc,2t4w,2t4w,3if4,23uo,2t4w,23uo,1ekg,3if4,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,47pc,3if4,2t4w,3if4,2t4w,47pc,2t4w,47pc,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,3if4,3if4,3if4,2t4w,47pc,47pc,2t4w,2t4w,3if4,5m9s,2t4w,2t4w,2t4w,3if4,3if4,3if4,3if4,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,3if4,3if4,3if4,2t4w,2t4w,47pc,23uo,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,4wzk,2t4w,2t4w,3if4,3if4,2t4w,23uo,4wzk,47pc,1ekg,23uo,47pc,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,4wzk,47pc,2t4w,3if4,3if4,3if4,3if4,2t4w,3if4,2t4w,3if4,1ekg,2t4w,47pc,2t4w,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,3if4,23uo,3if4,4wzk,2t4w,2t4w,23uo,2t4w,2t4w,47pc,3if4,2t4w,2t4w,3if4,2t4w,5m9s,2t4w,2t4w,2t4w,3if4,3if4,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,2t4w,23uo,2t4w,2t4w,2t4w,23uo,3if4,2t4w,23uo,2t4w,3if4,2t4w,23uo,3if4,3if4,2t4w,23uo,2t4w,23uo,pa8,2t4w,2t4w,3if4,3if4,23uo,3if4,3if4,2t4w,3if4,3if4,23uo,3if4,47pc,47pc,2t4w,2t4w,3if4,4wzk,23uo,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,3if4,47pc,2t4w,2t4w,47pc,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,47pc,2t4w,23uo,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,23uo,23uo,2t4w,47pc,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,2t4w,3if4,2t4w,2t4w,3if4,3if4,2t4w,3if4,pa8,2t4w,2t4w,2t4w,4wzk,2t4w,2t4w,4wzk,3if4,2t4w,3if4,23uo,2t4w,3if4,2t4w,2t4w,23uo,1ekg,1ekg,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,47pc,3if4,2t4w,2t4w,3if4,2t4w,23uo,2t4w,3if4,2t4w,2t4w,23uo,2t4w,1ekg,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,23uo,23uo,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,4wzk,6bk0,6bk0,5m9s,70u8,47pc,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,3if4,23uo,23uo,2t4w,47pc,47pc,3if4,2t4w,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,1ekg,23uo,2t4w,47pc,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,23uo,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,23uo,3if4,3if4,3if4,2t4w,2t4w,1ekg,2t4w,2t4w,3if4,2t4w,4wzk,2t4w,2t4w,4wzk,3if4,47pc,3if4,23uo,3if4,3if4,5m9s,2t4w,2t4w,4wzk,2t4w,5m9s,3if4,3if4,23uo,3if4,2t4w,3if4,3if4,2t4w,3if4,2t4w,2t4w,5m9s,2t4w,2t4w,3if4,3if4,23uo,2t4w,2t4w,47pc,2t4w,3if4,47pc,3if4,2t4w,3if4,3if4,3if4,3if4,2t4w,3if4,2t4w,2t4w,6bk0,4wzk,2t4w,2t4w,2t4w,47pc,3if4,2t4w,2t4w,2t4w,4wzk,2t4w,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,47pc,2t4w,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,47pc,2t4w,2t4w,3if4,2t4w,3if4,2t4w,23uo,23uo,2t4w,2t4w,23uo,23uo,23uo,2t4w,2t4w,23uo,23uo,2t4w,23uo,2t4w,2t4w,23uo,23uo,23uo,23uo,2t4w,2t4w,23uo,2t4w,3if4,23uo,23uo,2t4w,23uo,2t4w,2t4w,1ekg,23uo,47pc,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,47pc,23uo,2t4w,3if4,2t4w,23uo,3if4,2t4w,2t4w,23uo,23uo,23uo,3if4,2t4w,3if4,2t4w,47pc,2t4w,23uo,pa8,23uo,2t4w,2t4w,3if4,3if4,23uo,2t4w,47pc,4wzk,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,3if4,2t4w,2t4w,3if4,2t4w,3if4,3if4,2t4w,3if4,23uo,3if4,4wzk,47pc,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,4wzk,3if4,2t4w,2t4w,23uo,2t4w,2t4w,3if4,1ekg,1ekg,2t4w,23uo,47pc,47pc,2t4w,2t4w,23uo,2t4w,47pc,2t4w,47pc,2t4w,2t4w,23uo,3if4,23uo,23uo,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,3if4,3if4,2t4w,2t4w,3if4,3if4,3if4,4wzk,47pc,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,3if4,23uo,3if4,47pc,3if4,23uo,23uo,2t4w,23uo,23uo,3if4,23uo,23uo,23uo,23uo,2t4w,23uo,23uo,2t4w,2t4w,23uo,23uo,23uo,2t4w,2t4w,6bk0,5m9s,4wzk,6bk0,5m9s,pa8,2t4w,3if4,2t4w,23uo,3if4,3if4,3if4,2t4w,3if4,2t4w,47pc,2t4w,47pc,23uo,2t4w,3if4,47pc,3if4,2t4w,2t4w,47pc,47pc,2t4w,2t4w,23uo,47pc,47pc,3if4,3if4,3if4,4wzk,2t4w,3if4,3if4,4wzk,3if4,47pc,47pc,47pc,3if4,2t4w,23uo,47pc,3if4,47pc,3if4,47pc,3if4,3if4,4wzk,3if4,3if4,3if4,47pc,3if4,47pc,3if4,3if4,47pc,3if4,23uo,2t4w,3if4,47pc,1ekg,2t4w,4wzk,3if4,3if4,4wzk,3if4,47pc,3if4,3if4,47pc,2t4w,2t4w,2t4w,47pc,3if4,2t4w,47pc,2t4w,47pc,47pc,2t4w,2t4w,5m9s,47pc,47pc,2t4w,3if4,47pc,47pc,3if4,3if4,1ekg,3if4,47pc,3if4,2t4w,3if4,23uo,23uo,3if4,2t4w,3if4,47pc,2t4w,3if4,47pc,3if4,3if4,47pc,2t4w,2t4w,3if4,47pc,3if4,47pc,3if4,47pc,47pc,2t4w,2t4w,4wzk,2t4w,2t4w,23uo,47pc,3if4,3if4,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,47pc,3if4,23uo,2t4w,2t4w,47pc,23uo,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,23uo,2t4w,3if4,47pc,2t4w,23uo,2t4w,4wzk,2t4w,2t4w,2t4w,47pc,2t4w,23uo,2t4w,2t4w,1ekg,23uo,23uo,2t4w,47pc,3if4,2t4w,2t4w,3if4,3if4,2t4w,2t4w,3if4,2t4w,23uo,2t4w,3if4,2t4w,23uo,2t4w,1ekg,3if4,2t4w,23uo,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,3if4,23uo,2t4w,23uo,3if4,23uo,2t4w,23uo,2t4w,3if4,2t4w,23uo,2t4w,23uo,2t4w,23uo,3if4,1ekg,2t4w,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,47pc,2t4w,2t4w,2t4w,3if4,23uo,3if4,3if4,2t4w,2t4w,3if4,4wzk,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,23uo,3if4,23uo,2t4w,2t4w,2t4w,3if4,23uo,2t4w,2t4w,2t4w,3if4,2t4w,23uo,2t4w,2t4w,3if4,23uo,2t4w,3if4,1ekg,1ekg,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,3if4,2t4w,47pc,23uo,3if4,2t4w,2t4w,3if4,23uo,2t4w,3if4,2t4w,2t4w,2t4w,23uo,3if4,23uo,3if4,23uo,2t4w,2t4w,2t4w,2t4w,3if4,23uo,23uo,2t4w,23uo,2t4w,2t4w,3if4,3if4,23uo,2t4w,2t4w,2t4w,2t4w,23uo,23uo,1ekg,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,3if4,3if4,3if4,47pc,2t4w,2t4w,4wzk,23uo,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,23uo,pa8,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,3if4,23uo,2t4w,3if4,3if4,2t4w,2t4w,23uo,3if4,2t4w,23uo,2t4w,6bk0,6bk0,5m9s,4wzk,5m9s,3if4,2t4w,2t4w,2t4w,1ekg,1ekg,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,23uo,2t4w,2t4w,2t4w,1ekg,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,3if4,23uo,2t4w,3if4,2t4w,23uo,2t4w,23uo,2t4w,2t4w,23uo,pa8,23uo,23uo,3if4,23uo,2t4w,23uo,2t4w,23uo,3if4,23uo,23uo,23uo,2t4w,2t4w,2t4w,3if4,2t4w,3if4,23uo,3if4,2t4w,23uo,2t4w,2t4w,47pc,2t4w,2t4w,23uo,47pc,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,3if4,23uo,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,23uo,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,23uo,2t4w,2t4w,2t4w,23uo,3if4,2t4w,2t4w,2t4w,23uo,2t4w,23uo,23uo,23uo,2t4w,23uo,3if4,23uo,2t4w,2t4w,23uo,2t4w,3if4,3if4,2t4w,23uo,3if4,2t4w,4wzk,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,3if4,1ekg,23uo,23uo,2t4w,23uo,23uo,3if4,23uo,2t4w,1ekg,1ekg,pa8,2t4w,23uo,2t4w,23uo,23uo,2t4w,23uo,2t4w,2t4w,23uo,23uo,2t4w,23uo,23uo,23uo,3if4,23uo,2t4w,23uo,23uo,2t4w,23uo,2t4w,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,2t4w,23uo,2t4w,23uo,2t4w,3if4,2t4w,3if4,4wzk,1ekg,23uo,pa8,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,2t4w,2t4w,23uo,3if4,2t4w,3if4,2t4w,47pc,2t4w,23uo,2t4w,23uo,3if4,2t4w,5m9s,3if4,2t4w,3if4,23uo,47pc,2t4w,2t4w,4wzk,3if4,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,2t4w,3if4,1ekg,23uo,23uo,2t4w,3if4,23uo,23uo,23uo,3if4,23uo,23uo,23uo,2t4w,23uo,23uo,23uo,2t4w,2t4w,23uo,2t4w,2t4w,23uo,2t4w,2t4w,2t4w,23uo,3if4,23uo,2t4w,23uo,2t4w,23uo,23uo,2t4w,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,47pc,3if4,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,3if4,2t4w,2t4w,2t4w,3if4,3if4,2t4w,3if4,2t4w,2t4w,2t4w,2t4w,47pc,2t4w,23uo,2t4w,3if4,3if4,1ekg,2t4w,23uo,23uo,3if4,2t4w,3if4,2t4w,47pc,47pc,2t4w,3if4,2t4w,47pc,2t4w,3if4,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,2t4w,3if4,2t4w,2t4w,3if4,23uo,23uo,1ekg,1ekg,pa8,pa8,1ekg,pa8,1ekg,1ekg,23uo,1ekg,2t4w,2t4w,pa8,1ekg,pa8,pa8,pa8,1ekg,pa8",S=new Set(),p=0,a=P.split(","),i;
+ for(i=0;i<a.length;i++){p+=parseInt(a[i],36);S.add(String(p));}
+ function hit(el){var id=el.getAttribute("data-product-id")||el.id||"";return S.has(String(id));}
+ var pend=!1;
+ function sweep(){
+ var items=document.querySelectorAll(".boost-sd__product-item:not([data-dw-showroom])"),k;
+ for(k=0;k<items.length;k++){var el=items[k];el.setAttribute("data-dw-showroom","1");if(hit(el))el.style.display="none";}
+ }
+ function schedule(){if(!pend){pend=!0;requestAnimationFrame(function(){pend=!1;sweep();});}}
+ function start(){sweep();new MutationObserver(schedule).observe(document.documentElement,{childList:!0,subtree:!0});}
+ document.readyState!=="loading"?start():document.addEventListener("DOMContentLoaded",start);
+})();
diff --git a/scripts/tk11186-showroom-hide/theme-deploy/hide-browse-hidden.liquid b/scripts/tk11186-showroom-hide/theme-deploy/hide-browse-hidden.liquid
index 16ced71..5f19aa4 100644
--- a/scripts/tk11186-showroom-hide/theme-deploy/hide-browse-hidden.liquid
+++ b/scripts/tk11186-showroom-hide/theme-deploy/hide-browse-hidden.liquid
@@ -55,20 +55,16 @@
document.querySelectorAll('[data-vendor]').forEach(function(el){
if (HIDDEN.indexOf(String(el.getAttribute('data-vendor')||'').trim().toLowerCase()) > -1){ el.style.display = 'none'; }
});
- // TK-11307: hide any card whose product tags include the EXACT 'ShowroomOnly' tag.
- // Split on COMMAS ONLY, then trim + compare whole tags — mirrors the canonical
- // hasShowroomTag() in fix-live-board/config/showroom-vendor.cjs. A whitespace split
- // here was a live landmine: the pre-existing 'Showroom Line' tag sits on 18,500+
- // ACTIVE SELLABLE products (Kravet, China Seas, Scalamandre, Osborne & Little,
- // sellable Phillipe Romano, ...) and tokenizes to ['showroom','line'], so a token
- // match would have hidden the entire catalog's showroom-LINE products. Exact only.
- // NOTE: no card currently emits data-tags, so this backstop selects nothing today;
- // Boost/AJAX coverage is NOT delivered by this hook (see the gated deploy note).
- document.querySelectorAll('[data-tags]').forEach(function(el){
- if (String(el.getAttribute('data-tags')||'').split(',').map(function(t){ return t.trim().toLowerCase(); }).indexOf(SHOWROOM_TAG) > -1){
- var c = el.closest(CARD_SEL) || el; if (c && c.style.display !== 'none') c.style.display = 'none';
- }
- });
+ // TK-11307: the product-level showroom hide is NOT done here.
+ // A data-tags hook used to live in this function. It was dead code — no product card on
+ // this store emits data-tags (measured: 59 cards across 4 surfaces, 0 data-tags) — and it
+ // was actively dangerous, because an earlier revision split tags on WHITESPACE and matched
+ // 'showroom', which makes the unrelated 'Showroom Line' tag on 18,518+ ACTIVE SELLABLE
+ // products (Kravet, China Seas, Scalamandre, Osborne & Little, sellable Phillipe Romano...)
+ // tokenize to ['showroom','line'] and MATCH. Leaving a dead hook in place invites someone
+ // to "make it work" by emitting data-tags, which arms exactly that landmine.
+ // Browse grids here are rendered by Boost SD, not Liquid, so the working mechanism is the
+ // id-keyed asset included below — see assets/dw-showroom-hide.js.
}
hideProducts();
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', hideProducts);
@@ -76,3 +72,14 @@
if (document.body){ new MutationObserver(function(){ setTimeout(hideProducts, 100); }).observe(document.body, { childList:true, subtree:true }); }
})();
</script>
+
+{%- comment -%}
+ TK-11307 — product-level showroom-only hide for Boost-rendered browse grids.
+ Boost renders every browse/search grid client-side, so neither product-list-item.liquid nor
+ the observer above can reach those cards; a rendered Boost card exposes only data-product-id
+ (no tags). dw-showroom-hide.js is GENERATED from the live 'ShowroomOnly' tag by
+ scripts/tk11307-showroom-tag/build-showroom-hide-asset.mjs and matches on that id.
+ It deliberately no-ops on /search and ?q= so the line stays findable on-site — Steve's rule
+ is "addressable but not discoverable". Regenerate the asset whenever the tagged set changes.
+{%- endcomment -%}
+<script src="{{ 'dw-showroom-hide.js' | asset_url }}" defer></script>
diff --git a/scripts/tk11186-showroom-hide/theme-deploy/push-theme-assets.mjs b/scripts/tk11186-showroom-hide/theme-deploy/push-theme-assets.mjs
index ebf38d6..034a206 100644
--- a/scripts/tk11186-showroom-hide/theme-deploy/push-theme-assets.mjs
+++ b/scripts/tk11186-showroom-hide/theme-deploy/push-theme-assets.mjs
@@ -48,11 +48,24 @@ const BASE = () => `https://${SHOP}/admin/api/${VER}/themes/${THEME_ID}/assets.j
const md5 = s => crypto.createHash('md5').update(s).digest('hex');
const H = { 'X-Shopify-Access-Token': FULL, 'Content-Type': 'application/json' };
+// TK-11307 PUSH SET.
+// The generated asset goes FIRST: the snippet references it with asset_url, so uploading the
+// snippet first would briefly point at a 404.
+//
+// snippets/product-list-item.liquid was DELIBERATELY REMOVED from this set:
+// (1) it cannot help — every browse/search grid is rendered by Boost SD, not Liquid
+// (/collections/all serves 0 `class="product-list-item"` vs 273 boost-sd__product-item),
+// so its render-time skip never executes on a browse surface; and
+// (2) pushing it would CAUSE a regression — the local copy was branched from the Sep-3
+// baseline and never rebased, so it is missing the live Newmor feature ('Newmor' appears
+// 2x live, 0x locally) and would revert the data-newmor-showroom price block and the
+// Newmor quick-shop exclusion.
+// If it is ever re-added, rebase it onto the LIVE bytes first.
const FILES = [
+ { key: 'assets/dw-showroom-hide.js',
+ fix: 'dw-showroom-hide.js', orig: null, newAsset: true },
{ key: 'snippets/hide-browse-hidden.liquid',
fix: 'hide-browse-hidden.liquid', orig: 'hide-browse-hidden.ORIGINAL.liquid' },
- { key: 'snippets/product-list-item.liquid',
- fix: 'product-list-item.liquid', orig: 'product-list-item.ORIGINAL.liquid' },
];
async function getAsset(key) {
@@ -118,6 +131,13 @@ if (ROLLBACK && ROLLBACK_TO_ORIGINAL) {
for (const f of FILES) {
let localPath = path.join(__dirname, f[which]);
+ if (ROLLBACK && f.newAsset) {
+ // A file that did not exist before this deploy has no previous state to restore. Rolling
+ // back the snippet removes the <script> include, which makes this asset inert, so leaving
+ // the orphan file on the theme is harmless and avoids a destructive delete.
+ console.log(`\n ${f.key}: new asset — nothing to restore. The snippet rollback removes its include, leaving it inert.`);
+ continue;
+ }
if (ROLLBACK && !ROLLBACK_TO_ORIGINAL) {
const pre = newestPreimage(f.key);
if (!pre) {
@@ -130,10 +150,15 @@ for (const f of FILES) {
console.log(`\n ${f.key} rollback source: ${path.basename(pre)}`);
}
const local = fs.readFileSync(localPath, 'utf8');
- const live = await getAsset(f.key);
+ let live;
+ try { live = await getAsset(f.key); }
+ catch (e) {
+ if (f.newAsset && /HTTP 404/.test(e.message)) { live = { value: '', absent: true }; }
+ else throw e;
+ }
const liveSum = md5(live.value), localSum = md5(local);
console.log(`\n ${f.key}`);
- console.log(` live md5 ${liveSum} (${live.value.length}b)`);
+ console.log(live.absent ? ' live (absent — new asset)' : ` live md5 ${liveSum} (${live.value.length}b)`);
console.log(` -> ${which} md5 ${localSum} (${local.length}b) ${liveSum === localSum ? '(already matches — no-op)' : ''}`);
if (!APPLY && !ROLLBACK) continue;
if (liveSum === localSum) { console.log(' skip (identical)'); continue; }
diff --git a/scripts/tk11307-showroom-tag/build-showroom-hide-asset.mjs b/scripts/tk11307-showroom-tag/build-showroom-hide-asset.mjs
new file mode 100644
index 0000000..11dc7cf
--- /dev/null
+++ b/scripts/tk11307-showroom-tag/build-showroom-hide-asset.mjs
@@ -0,0 +1,88 @@
+#!/usr/bin/env node
+/**
+ * TK-11307 — build the tag-driven Boost card-hider theme asset.
+ *
+ * WHY THIS EXISTS. Every browse/search grid on this store is rendered client-side by
+ * Boost SD, not by Liquid: /collections/all serves 0 `class="product-list-item"` elements
+ * against 273 `boost-sd__product-item` nodes. So the render-time skip in
+ * product-list-item.liquid never executes on a browse surface, and the JS backstop in
+ * hide-browse-hidden.liquid hooks `[data-tags]`, which no product card emits. Neither can
+ * hide the MDC cohort. The ONLY mechanism demonstrably able to hide a Boost card on this
+ * store is assets/dw-pj-hide.js — so this generalizes that proven pattern.
+ *
+ * WHY IT MATCHES ON ID, NOT TAG. A rendered Boost card exposes exactly two data attributes,
+ * `data-product-id` and whatever a previous script stamped on it; Boost does NOT put tags in
+ * the DOM (0 occurrences of "tags" in the rendered page). So the tag cannot be read at
+ * runtime. It is read HERE, at build time, from live Shopify — the rule stays tag-driven,
+ * the runtime lookup is just an O(1) id-set membership test.
+ *
+ * SEARCH IS DELIBERATELY PRESERVED. Steve's rule is "addressable but not discoverable":
+ * hidden from browse grids, still reachable by direct URL AND by on-site search. Like
+ * dw-pj-hide.js, the emitted asset returns immediately on /search or ?q=, so search results
+ * are untouched. That is also why we are NOT using a Boost index exclusion, which would
+ * remove the cohort from search too.
+ *
+ * Output: dw-showroom-hide.js (an asset to be pushed to the PUBLISHED theme, gated).
+ * Read-only against Shopify. $0.
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { gql } from '../lib/shopify.mjs';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const TAG = 'ShowroomOnly';
+const OUT = path.join(__dirname, '..', 'tk11186-showroom-hide', 'theme-deploy', 'dw-showroom-hide.js');
+
+// Pull every product carrying the EXACT tag. Never query `tag:Showroom` — it is a prefix/token
+// matcher that returns the 18,518+ 'Showroom Line' SELLABLE products and hits the 10000 cap.
+async function fetchIds() {
+ const ids = []; let after = null, more = true;
+ while (more) {
+ const q = `query($after:String){ products(first:250, query:"tag:'${TAG}'", after:$after){
+ pageInfo{hasNextPage endCursor} nodes{ id } } }`;
+ const r = await gql(q, { after });
+ if (r?.__err) throw new Error('gql: ' + JSON.stringify(r.__err).slice(0, 300));
+ for (const n of r.products.nodes) ids.push(Number(n.id.split('/').pop()));
+ more = r.products.pageInfo.hasNextPage; after = r.products.pageInfo.endCursor;
+ process.stdout.write(`\r fetched ${ids.length}`);
+ }
+ process.stdout.write('\n');
+ return ids;
+}
+
+// Sorted delta + base36 keeps ~4.7k 13-digit ids small enough to inline in a theme asset.
+function encode(ids) {
+ const s = [...ids].sort((a, b) => a - b);
+ let prev = 0;
+ return s.map(v => { const d = v - prev; prev = v; return d.toString(36); }).join(',');
+}
+
+const ids = await fetchIds();
+if (!ids.length) { console.error('refusing to write an empty hide list'); process.exit(1); }
+const packed = encode(ids);
+
+const asset = `/* TK-11307 showroom-only Boost card hider — GENERATED by build-showroom-hide-asset.mjs.
+ Hides products tagged '${TAG}' from Boost-rendered browse grids while leaving on-site
+ search and direct /products/ URLs untouched ("addressable but not discoverable").
+ ${ids.length} product ids, sorted delta base36. Do not hand-edit — regenerate. */
+(function(){
+ if(/\\/search/i.test(location.pathname)||/[?&]q=/i.test(location.search))return; /* keep search findable */
+ var P="${packed}",S=new Set(),p=0,a=P.split(","),i;
+ for(i=0;i<a.length;i++){p+=parseInt(a[i],36);S.add(String(p));}
+ function hit(el){var id=el.getAttribute("data-product-id")||el.id||"";return S.has(String(id));}
+ var pend=!1;
+ function sweep(){
+ var items=document.querySelectorAll(".boost-sd__product-item:not([data-dw-showroom])"),k;
+ for(k=0;k<items.length;k++){var el=items[k];el.setAttribute("data-dw-showroom","1");if(hit(el))el.style.display="none";}
+ }
+ function schedule(){if(!pend){pend=!0;requestAnimationFrame(function(){pend=!1;sweep();});}}
+ function start(){sweep();new MutationObserver(schedule).observe(document.documentElement,{childList:!0,subtree:!0});}
+ document.readyState!=="loading"?start():document.addEventListener("DOMContentLoaded",start);
+})();
+`;
+fs.writeFileSync(OUT, asset);
+const kb = n => (n / 1024).toFixed(1) + 'KB';
+console.log(` ids: ${ids.length}`);
+console.log(` packed: ${kb(packed.length)} (raw ids would be ${kb(ids.join(',').length)})`);
+console.log(` asset: ${OUT} (${kb(asset.length)})`);
diff --git a/scripts/tk11307-showroom-tag/data/hide-asset-fixtures.json b/scripts/tk11307-showroom-tag/data/hide-asset-fixtures.json
new file mode 100644
index 0000000..4a1ef4f
--- /dev/null
+++ b/scripts/tk11307-showroom-tag/data/hide-asset-fixtures.json
@@ -0,0 +1,49 @@
+{
+ "note": "MDC ids scraped from a live rendered /collections/phillipe-romano DOM; controls are live ACTIVE products carrying the colliding 'Showroom Line' tag (two share the 'Phillipe Romano' vendor with MDC).",
+ "mdc": [
+ "7899344994355",
+ "7899344830515",
+ "7899344699443",
+ "7899344568371",
+ "7899344437299",
+ "7899344273459",
+ "7899344142387",
+ "7899344011315",
+ "7899343880243",
+ "7899343716403",
+ "7899343421491",
+ "7899343224883"
+ ],
+ "controls": [
+ {
+ "id": "1494907846768",
+ "vendor": "Retro Walls",
+ "title": "Swimming Koi Fish"
+ },
+ {
+ "id": "1495864279152",
+ "vendor": "Phillipe Romano",
+ "title": "Hilary's Horizontal Grasscloth"
+ },
+ {
+ "id": "1495872438384",
+ "vendor": "Scalamandre Wallpaper",
+ "title": "Zoe's Zebra Wallcovering"
+ },
+ {
+ "id": "1495913988208",
+ "vendor": "Retro Walls",
+ "title": "Metalisimo Silver Stripes"
+ },
+ {
+ "id": "1495914315888",
+ "vendor": "Retro Walls",
+ "title": "Metalisimo Gold Stripes"
+ },
+ {
+ "id": "1495922901104",
+ "vendor": "Phillipe Romano",
+ "title": "Kumiko Grasscloth Horizontal Weave"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/scripts/tk11307-showroom-tag/test-showroom-hide-asset.mjs b/scripts/tk11307-showroom-tag/test-showroom-hide-asset.mjs
new file mode 100644
index 0000000..7f2012c
--- /dev/null
+++ b/scripts/tk11307-showroom-tag/test-showroom-hide-asset.mjs
@@ -0,0 +1,99 @@
+#!/usr/bin/env node
+/**
+ * TK-11307 — proof test for the Boost card-hider asset (dw-showroom-hide.js).
+ *
+ * Runs the REAL generated asset in REAL headless Chrome against realistic Boost card
+ * markup, and asserts three things:
+ *
+ * BROWSE every MDC card is hidden, and ZERO control cards are hidden. The controls are
+ * live ACTIVE products carrying the colliding 'Showroom Line' tag — including two
+ * on the SAME shared 'Phillipe Romano' vendor — because hiding a sellable sibling
+ * is the exact failure this whole rollout exists to avoid.
+ * SEARCH with ?q= present, NOTHING is hidden. Steve's rule is "addressable but not
+ * discoverable": out of browse grids, still findable in on-site search.
+ * MUTATION an over-broad hider (hide every card — the 'Showroom Line' collision failure
+ * mode) must make the BROWSE assertion go RED. A positive-only test on a hider
+ * proves nothing; if the mutant passes, this test is not guarding anything.
+ *
+ * Read-only, no network beyond a throwaway localhost server, $0.
+ * Run: node test-showroom-hide-asset.mjs
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import http from 'node:http';
+import { execFile } from 'node:child_process';
+import { fileURLToPath } from 'node:url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const ASSET = path.join(__dirname, '..', 'tk11186-showroom-hide', 'theme-deploy', 'dw-showroom-hide.js');
+const CHROME = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
+const FIXTURES = path.join(__dirname, 'data', 'hide-asset-fixtures.json');
+
+if (!fs.existsSync(ASSET)) { console.error(`missing asset ${ASSET} — run build-showroom-hide-asset.mjs`); process.exit(1); }
+if (!fs.existsSync(CHROME)) { console.error('Google Chrome not found — cannot run the DOM proof'); process.exit(1); }
+const asset = fs.readFileSync(ASSET, 'utf8');
+const fx = JSON.parse(fs.readFileSync(FIXTURES, 'utf8')); // {mdc:[id...], controls:[{id,vendor,title}...]}
+const controlIds = fx.controls.map(c => String(c.id));
+
+function harness(js) {
+ const cards = [...fx.mdc, ...controlIds]
+ .map(i => `<div class="boost-sd__product-item" id="${i}" data-product-id="${i}"><a href="/products/x-${i}">c</a></div>`).join('');
+ return `<!doctype html><html><body><div class="boost-sd__product-list">${cards}</div><pre id="R"></pre>
+<script>${js}</script>
+<script>window.addEventListener('load',function(){setTimeout(function(){
+var MDC=${JSON.stringify(fx.mdc)},CTL=${JSON.stringify(controlIds)};
+function h(id){var e=document.getElementById(id);return !!(e&&e.style.display==='none');}
+document.getElementById('R').textContent=JSON.stringify({mdc:MDC.length,mdcHidden:MDC.filter(h).length,ctl:CTL.length,ctlHidden:CTL.filter(h).length});
+},400);});</script></body></html>`;
+}
+
+function run(html, query) {
+ // Chrome MUST be spawned asynchronously: a sync spawn blocks the event loop, so the
+ // throwaway server can never answer Chrome's request and both sides hang until timeout.
+ const dir = fs.mkdtempSync('/tmp/tk11307-hide-');
+ fs.writeFileSync(path.join(dir, 'h.html'), html);
+ const srv = http.createServer((req, res) => {
+ res.writeHead(200, { 'Content-Type': 'text/html' });
+ res.end(fs.readFileSync(path.join(dir, 'h.html')));
+ });
+ return new Promise(resolve => {
+ srv.listen(0, '127.0.0.1', () => {
+ const url = `http://127.0.0.1:${srv.address().port}/h.html${query || ''}`;
+ execFile(CHROME, ['--headless', '--disable-gpu', '--no-sandbox',
+ '--virtual-time-budget=4000', '--dump-dom', url],
+ { encoding: 'utf8', timeout: 60000, maxBuffer: 64 * 1024 * 1024 },
+ (err, stdout) => {
+ srv.close(); fs.rmSync(dir, { recursive: true, force: true });
+ const m = String(stdout || '').match(/<pre id="R">(.*?)<\/pre>/s);
+ let parsed = null;
+ try { parsed = m ? JSON.parse(m[1]) : null; } catch { parsed = null; }
+ resolve(parsed);
+ });
+ });
+ });
+}
+
+let fail = 0;
+const say = (ok, name, detail) => { console.log(` ${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ' — ' + detail : ''}`); if (!ok) fail++; };
+
+console.log(`dw-showroom-hide.js proof — ${fx.mdc.length} MDC cards, ${controlIds.length} controls`);
+
+const browse = await run(harness(asset));
+// An unreadable result is NOT a pass — never let a failed render read as success.
+if (!browse) { console.log(' FAIL BROWSE produced no result (render failed)'); process.exit(1); }
+say(browse.mdcHidden === browse.mdc, 'BROWSE hides every MDC card', `${browse.mdcHidden}/${browse.mdc}`);
+say(browse.ctlHidden === 0, 'BROWSE hides ZERO Showroom Line controls', `${browse.ctlHidden}/${browse.ctl} hidden`);
+
+const search = await run(harness(asset), '?q=test');
+if (!search) { console.log(' FAIL SEARCH produced no result (render failed)'); process.exit(1); }
+say(search.mdcHidden === 0 && search.ctlHidden === 0, 'SEARCH hides nothing (stays findable)',
+ `${search.mdcHidden} mdc / ${search.ctlHidden} ctl hidden`);
+
+const MUTANT = '(function(){var it=document.querySelectorAll(".boost-sd__product-item");for(var i=0;i<it.length;i++)it[i].style.display="none";})();';
+const mut = await run(harness(MUTANT));
+if (!mut) { console.log(' FAIL MUTATION produced no result (render failed)'); process.exit(1); }
+say(mut.ctlHidden > 0, 'MUTATION detected (over-broad hider trips the control assertion)',
+ `${mut.ctlHidden}/${mut.ctl} controls wrongly hidden`);
+
+console.log(`\n ${fail ? fail + ' FAILED' : 'all checks passed'}`);
+process.exit(fail ? 1 : 0);
← 8dcc371 Verify Sanderson gallery remediation for TK-11302
·
back to Designerwallcoverings
·
Verify TK-11301 containment and document durable fix gate 9a66543 →