-
Notifications
You must be signed in to change notification settings - Fork 0
Selector Maintenance
Language: English · فارسی
Bale Web is a React app bundled with CSS Modules: every class name in the DOM is a
per-build hash like _BKsFW, so it changes on every deploy. The extension anchors on
attributes that survive a rebuild instead. When one of those is renamed upstream, a
category stops blurring — and this page is how it gets fixed.
Reference version in the repo: docs/SELECTORS.md.
1. aria-label — hand-written for accessibility, semantic, rarely churned.
| Value | Marks |
|---|---|
dialog-item |
one row in the sidebar chat list |
message-item |
one message row |
avatar |
any avatar container |
member-dialog |
one person in the profile / members panel |
ChatAppBar |
the header above the open conversation |
editable-message-text |
the composer |
count-badge-text |
unread counter — never blurred |
2. data-sentry-source-file / data-sentry-component — emitted by Sentry's
component-annotate plugin, derived from source names: Dialog.tsx, BaseBubble.tsx,
Text.tsx, Preview.tsx, Thumbnail.tsx, SmallDialog.tsx, NewTextContainerFC.
3. data-testid — photo-message, thumbnail, story-item.
<!-- sidebar row -->
<div aria-label="dialog-item" data-sentry-source-file="Dialog.tsx">
<div aria-label="avatar">…</div>
<div>
<div><div><bdi>chat name</bdi></div><span>12:04</span></div>
<div title="…"><div><div dir="rtl"><span>last message</span></div></div></div>
</div>
</div>
<!-- message -->
<div aria-label="message-item" data-sid="client-message:…">
<div aria-label="avatar">…</div>
<div data-sentry-source-file="BaseBubble.tsx">
<p><span>sender name</span></p> <!-- groups only -->
<div data-sentry-source-file="Preview.tsx">…</div>
<div data-sentry-source-file="Text.tsx">…</div>
<div data-sentry-source-file="Info.tsx"><p>12:05</p></div>
</div>
</div>Two details worth remembering:
- The sender name is the only
pwrapping aspan; the timestamppholds its text directly. That is what keeps timestamps readable. -
Message text is blurred at the container, not at leaf elements, because a bubble
legitimately contains inline markup (
<strong>, links) and a leaf rule leaves the surrounding text sharp.
Options page → Advanced selectors → Log selector diagnostics, reload
web.bale.ai, read the console table. Rows with 0 matches are dead.
Paste tools/dom-probe.js
into DevTools on a Bale tab:
bp.status() // dead vs matching selectors, read from the injected stylesheet
bp.inventory() // every attribute the page renders, with value counts
bp.el($0) // ancestors + subtree of the element you inspected
copy(bp.last)bp.inventory() is usually the whole answer: it shows which attribute families still
exist and what their values are now.
npm run build
npm run browser # log in once, window stays open
node scripts/browser.mjs eval tools/leak-scan.js # what is still readable
node scripts/browser.mjs shot out.png
node scripts/browser.mjs hover '[data-sentry-source-file="Text.tsx"]'The profile persists in .browser-profile/, so you log in once and iterate.
Add it to the right entry in
src/content/engine/selectors.ts.
Picture-only selectors go under mediaSelectors, which get the stronger graphic blur
under the same user-facing switch.
Two traps that have already bitten this project:
-
Keep
:has()last in a compound.*:not(:has(*)):not(:empty)is valid CSS but some engines — including the one jsdom uses, and therefore the test suite — reject it. -
Put a type selector before an attribute inside
:has(> …). Write:has(> div[data-sentry-component="X"]), not:has(> [data-sentry-component="X"]), for the same reason.
npm test parses every shipped selector and checks the targeting rules against a
fixture transcribed from the real markup, so both traps fail loudly.
Options page → Advanced selectors, one selector per line under the matching
category. Braces, <, ;, @, backslashes, comment markers and commas are rejected;
at most 20 selectors per category, 200 characters each.
English — using it
English — working on it
فارسی — استفاده
فارسی — توسعه
Links