61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
import type { SiteAdapter } from './adapter-interface';
|
|
|
|
/** Matches "Buy", "Buy pixelcat", etc. — never a hardcoded token name. */
|
|
const NOOB_MODE_BUY_TEXT = /^Buy\s/i;
|
|
|
|
/** Axiom's "increase"/"decrease" Tailwind color tokens are its buy(green)/sell(red) convention. */
|
|
const INCREASE_MARKER_SELECTOR = '[class*="increase"]';
|
|
|
|
function looksLikeBuyPill(el: HTMLElement): boolean {
|
|
return el.matches(INCREASE_MARKER_SELECTOR) || el.querySelector(INCREASE_MARKER_SELECTOR) !== null;
|
|
}
|
|
|
|
function findQuickBuyContainers(root: ParentNode): HTMLElement[] {
|
|
// `.buy-click-container` is a *shared* wrapper around both the buy and
|
|
// sell quick-amount pills as siblings — it is NOT buy-only. The buy pill
|
|
// is always its first child element; the sell pill is another sibling.
|
|
// Never treat the wrapper itself as the buy element/container.
|
|
const buyPills: HTMLElement[] = [];
|
|
for (const wrapper of root.querySelectorAll<HTMLElement>('.buy-click-container')) {
|
|
const firstChild = wrapper.firstElementChild;
|
|
if (firstChild instanceof HTMLElement && looksLikeBuyPill(firstChild)) {
|
|
buyPills.push(firstChild);
|
|
}
|
|
}
|
|
return buyPills;
|
|
}
|
|
|
|
function findNoobModeBuyButtons(root: ParentNode): HTMLElement[] {
|
|
// Buy and Sell noob-mode buttons are siblings too; the buy one is
|
|
// identified by its own text starting with "Buy", never by position.
|
|
return Array.from(root.querySelectorAll<HTMLElement>('button.bg-increase')).filter((button) =>
|
|
NOOB_MODE_BUY_TEXT.test(button.textContent?.trim() ?? ''),
|
|
);
|
|
}
|
|
|
|
export const axiomAdapter: SiteAdapter = {
|
|
id: 'axiom.trade',
|
|
|
|
matches(url) {
|
|
try {
|
|
return new URL(url).hostname.endsWith('axiom.trade');
|
|
} catch {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
findBuyElements(root) {
|
|
return [...findQuickBuyContainers(root), ...findNoobModeBuyButtons(root)];
|
|
},
|
|
|
|
getContainer(el) {
|
|
// findBuyElements() above already resolves to exactly the buy-side
|
|
// element in both cases — the quick-buy pill (first child of the shared
|
|
// buy/sell wrapper) or the noob-mode button whose own text is "Buy …".
|
|
// Do NOT climb to any ancestor (e.g. via closest('.buy-click-container'))
|
|
// — that wrapper holds the sell pill too, so treating it as the
|
|
// container would blur/disable sell right along with buy.
|
|
return el;
|
|
},
|
|
};
|